diff --git a/.github/workflows/build-fork.yml b/.github/workflows/build-fork.yml deleted file mode 100644 index 5520cf746b..0000000000 --- a/.github/workflows/build-fork.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Publish Fork Image to GHCR - -on: - push: - branches: [main] - tags: - - "v*" - workflow_dispatch: - -# Least-privilege default: read-only at the top level; the build job that pushes to -# GHCR grants packages: write itself (Scorecard TokenPermissions). -permissions: - contents: read - -env: - IMAGE_NAME: ghcr.io/kang-heewon/omniroute - -jobs: - build: - name: Build and Push Fork Image - if: github.repository == 'kang-heewon/OmniRoute' - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - name: Checkout - uses: actions/checkout@v7 - with: - persist-credentials: false - - - name: Set up QEMU - uses: docker/setup-qemu-action@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v4 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v6 - with: - images: ${{ env.IMAGE_NAME }} - tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=sha,prefix=sha- - type=ref,event=tag - labels: | - org.opencontainers.image.title=omniroute - org.opencontainers.image.description=Unified AI proxy/router — fork image - org.opencontainers.image.url=https://github.com/kang-heewon/OmniRoute - org.opencontainers.image.source=https://github.com/kang-heewon/OmniRoute - org.opencontainers.image.licenses=MIT - - - name: Build and push - uses: docker/build-push-action@v7 - with: - context: . - target: runner-base - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max diff --git a/.github/workflows/build-rinseaid-image.yml b/.github/workflows/build-rinseaid-image.yml deleted file mode 100644 index e601976245..0000000000 --- a/.github/workflows/build-rinseaid-image.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Build Rinseaid OmniRoute image - -on: - push: - branches: [build-k3-reasoning-image] - paths: - - Dockerfile - - package-lock.json - - package.json - - open-sse/** - - scripts/build/** - - .github/workflows/build-rinseaid-image.yml - workflow_dispatch: - -permissions: - contents: read - packages: write - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - - uses: docker/setup-buildx-action@v3 - - - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - uses: docker/build-push-action@v6 - with: - context: . - target: runner-base - platforms: linux/amd64 - push: true - tags: ghcr.io/rinseaid/omniroute:k3-reasoning-${{ github.sha }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a517e69d5..542f44b973 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,6 +42,18 @@ jobs: - uses: actions/setup-node@v7 with: node-version: ${{ env.CI_NODE_VERSION }} + # Refuse a PR that targets its own head branch before spending anything on it. #8912 has + # head == base == release/v3.8.50: no diff, can never merge, and it sits in the queue with + # a full check board attached on every push to that branch. One field comparison. + - name: Reject a PR that targets its own branch + if: github.event_name == 'pull_request' + env: + HEAD_REF: ${{ github.head_ref }} + BASE_REF: ${{ github.base_ref }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: node scripts/check/check-pr-self-target.mjs + - id: classify env: EVENT_NAME: ${{ github.event_name }} @@ -125,6 +137,17 @@ jobs: - run: npm run check:route-guard-membership - run: npm run check:test-discovery - run: npm run check:tracked-artifacts + # (gap 30) Also lives in quality.yml's PR-only "Merge integrity" job — because the + # CHANGELOG half of that job needs a base to diff against. This half does NOT: the + # generator either reproduces the committed SKILL.md files or it does not. + # + # Keeping it PR-only left a real hole. This cycle's merge trains landed in batches with + # `--admin`, which bypasses required checks, so three SKILL.md files drifted from the route + # catalog, rode the release squash into `main`, and the next cycle's sync-back turned them + # into a base-red that blocked EVERY PR into release/v3.8.50 until #8954. Running it here + # means a push to `main` catches the drift at the source instead of the next cycle + # inheriting it. + - run: npm run check:agent-skills-sync # WS1.7 (v3.8.49 plan): Dockerfile lint (hadolint, pinned by digest). # failure-threshold=error keeps the 5 pre-existing warnings (DL3008/DL3003/ # DL3016 version pinning / WORKDIR) visible without blocking; any ERROR fails. @@ -330,8 +353,16 @@ jobs: install -m 0755 /tmp/osv/*linux_amd64 "$HOME/.local/bin/osv-scanner" # actionlint — official download script bash <(curl -fsSL https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) latest "$HOME/.local/bin" - # zizmor — PyPI (pipx preferred, pip --user fallback); lands in ~/.local/bin - pipx install zizmor || pip install --user zizmor + # zizmor — PyPI (pipx preferred, pip --user fallback); lands in ~/.local/bin. + # PINNED on purpose. Unpinned, the runner installed whatever PyPI served that day and + # measured 1 finding MORE than the devbox on the identical commit (190 vs 189) during + # the v3.8.49 cycle — which cost a second rebaseline push per release, chasing a + # number that was never the code's. The ratchet compares counts across machines, so + # the auditor version has to be the same on both. Bump this deliberately, and + # rebaseline in the same commit: check-workflows.mjs now prints `zizmorVersion=` next + # to the count so the new number is traceable to the tool that produced it. + ZIZMOR_VERSION=1.25.2 + pipx install "zizmor==$ZIZMOR_VERSION" || pip install --user "zizmor==$ZIZMOR_VERSION" # oasdiff — download latest linux amd64 tarball via gh (authed), extract binary rm -rf /tmp/oasd && mkdir -p /tmp/oasd gh release download --repo oasdiff/oasdiff --pattern '*linux_amd64.tar.gz' --dir /tmp/oasd @@ -720,7 +751,13 @@ jobs: test-unit: name: Unit Tests (${{ matrix.shard }}/8) # Same dynamic-runner rule as Build (own-origin only; fallback ubuntu-latest). - runs-on: ${{ (vars.USE_VPS_RUNNER == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)) && fromJSON('["self-hosted","omni-release"]') || 'ubuntu-latest' }} + # PINNED to hosted, deliberately not on the USE_VPS_RUNNER switch (gap 19). One variable + # governed the build and the test jobs, which want OPPOSITE machines: the build needs the + # .113's RAM, the tests need the hosted runner's link. Measured on 2026-07-29 — + # actions/setup-node took 20m06s on .113 with 4 concurrent runners versus 16s hosted (npm + # cache restore saturating the link), while the tests themselves tied, 2m54 vs 2m31. So + # self-hosted is strictly worse here and there is nothing to configure. + runs-on: ubuntu-latest timeout-minutes: 25 # needs: changes (not build) — this job never downloads the next-build artifact; # gating it on Build only serialized ~20min of wall-clock for nothing. Jobs that @@ -792,7 +829,13 @@ jobs: test-vitest: name: Vitest (MCP / autoCombo / UI components) # Same dynamic-runner rule as Build (own-origin only; fallback ubuntu-latest). - runs-on: ${{ (vars.USE_VPS_RUNNER == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)) && fromJSON('["self-hosted","omni-release"]') || 'ubuntu-latest' }} + # PINNED to hosted, deliberately not on the USE_VPS_RUNNER switch (gap 19). One variable + # governed the build and the test jobs, which want OPPOSITE machines: the build needs the + # .113's RAM, the tests need the hosted runner's link. Measured on 2026-07-29 — + # actions/setup-node took 20m06s on .113 with 4 concurrent runners versus 16s hosted (npm + # cache restore saturating the link), while the tests themselves tied, 2m54 vs 2m31. So + # self-hosted is strictly worse here and there is nothing to configure. + runs-on: ubuntu-latest timeout-minutes: 15 # needs: changes (not build) — no artifact consumed; see test-unit note. needs: changes @@ -1126,7 +1169,8 @@ jobs: if FILES=$(node scripts/quality/balance-e2e-shards.mjs "$SHARD" 9); then if [ -z "$FILES" ]; then echo "[e2e-balance] shard $SHARD has no files"; exit 0; fi echo "[e2e-balance] shard $SHARD runs:"; echo "$FILES" - # shellcheck disable=SC2086 — FILES is our own newline-separated path list + # FILES is our own newline-separated path list, so word-splitting is intended + # shellcheck disable=SC2086,SC2046 npx playwright test $(echo "$FILES" | tr '\n' ' ') --reporter=line,junit else echo "[e2e-balance] balancer unavailable — plain --shard fallback" @@ -1228,6 +1272,8 @@ jobs: - name: Generate dashboard env: EVENT_NAME: ${{ github.event_name }} + # Workflow-controlled data (job results), not user input — safe to read here. + NEEDS_JSON: ${{ toJSON(needs) }} run: | status() { case "$1" in @@ -1242,6 +1288,29 @@ jobs: echo "# 🚀 CI Dashboard" >> "$GITHUB_STEP_SUMMARY" echo "" >> "$GITHUB_STEP_SUMMARY" + # (gap 12) A cancelled job never reported a verdict, and in a long table that reads the + # same as a green one. `cancel-in-progress` plus incremental fixing cancels jobs on every + # push, and this cycle the Vitest job was cancelled in rounds 1, 2 and 3 — it only ran to + # completion in round 4, where it revealed a suite that had been broken the whole cycle + # plus two production bugs. A gate that never finishes is indistinguishable from one that + # passes, so name them at the TOP instead of leaving them to be spotted mid-table. + CANCELLED_JOBS=$(printf '%s' "$NEEDS_JSON" \ + | jq -r 'to_entries | map(select(.value.result == "cancelled")) | .[].key' 2>/dev/null \ + | sort | paste -sd", " -) || CANCELLED_JOBS="" + if [ -n "$CANCELLED_JOBS" ]; then + { + echo "> ### ⚫ Cancelled — no verdict was reported" + echo ">" + echo "> \`$CANCELLED_JOBS\`" + echo ">" + echo "> These did not fail; they never finished, so nothing was checked. Treat this" + echo "> run as INCOMPLETE for those gates. If the cancellation came from" + echo "> \`cancel-in-progress\` on a newer push, the newer run covers it — otherwise" + echo "> re-run them before reading this dashboard as green." + echo "" + } >> "$GITHUB_STEP_SUMMARY" + fi + echo "## 🧱 Core Checks" >> "$GITHUB_STEP_SUMMARY" echo "| Job | Status |" >> "$GITHUB_STEP_SUMMARY" echo "|-----|--------|" >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/dast-smoke.yml b/.github/workflows/dast-smoke.yml index c4cc69a6cc..f4e2d65155 100644 --- a/.github/workflows/dast-smoke.yml +++ b/.github/workflows/dast-smoke.yml @@ -59,8 +59,14 @@ jobs: - run: pip install schemathesis - name: Schemathesis smoke (high-risk endpoints, blocking) run: | + # /api/auth/oidc/* is a BROWSER redirect flow (302 to the IdP, 302 back to + # /login?oidc_error=... on every failure), not a REST endpoint: Schemathesis reads + # those 302s as "the API accepted a schema-violating request" and the configured-off + # 400 as "rejected a schema-compliant request". Documenting the flow in the spec is + # still right (operators need it); fuzzing it is not what this smoke is for. schemathesis run docs/openapi.yaml --url http://localhost:20128 \ --include-path-regex '^/v1/(chat/completions|models)$|^/api/(auth|keys)' \ + --exclude-path-regex '^/api/auth/oidc/' \ --max-examples 8 --workers 4 --checks all --max-response-time 30 \ --request-timeout 20 --suppress-health-check all --no-color - name: promptfoo injection-guard (blocking) diff --git a/.github/workflows/electron-release.yml b/.github/workflows/electron-release.yml index 2a7fee0e9a..f1e3f869e6 100644 --- a/.github/workflows/electron-release.yml +++ b/.github/workflows/electron-release.yml @@ -120,6 +120,18 @@ jobs: env: JWT_SECRET: ci-build-secret-with-sufficient-length-for-validation NODE_OPTIONS: "--max_old_space_size=6144" + # Linux builds with webpack, not Turbopack. Turbopack's production build + # allocates natively (Rust, off the V8 heap), so --max_old_space_size does + # not bound it, and on this module graph it peaks above what the hosted + # runner can give — the VM is reclaimed mid-compile with "The runner has + # received a shutdown signal", no exit code. That is what silently took the + # whole desktop channel out of v3.8.49: the linux leg died, `release` was + # skipped, and the release shipped with ZERO assets. Measured on a 32 GB + # box the same build passes and peaks past 14 GB. The webpack fallback is + # the project's documented escape hatch for RAM-constrained machines + # (docs/reference/ENVIRONMENT.md, #6409) and is the same remedy already + # applied to nightly-compat's Node 26 build (#8090). + OMNIROUTE_USE_TURBOPACK: ${{ matrix.platform == 'linux' && '0' || '1' }} run: npm run build - name: Sync version in electron/package.json @@ -217,6 +229,16 @@ jobs: release: name: Create Release needs: [validate, build] + # Fail-partial, not fail-closed. `build` is a 4-leg matrix with `fail-fast: false`, + # so the legs that succeed still upload their artifacts — but a default `needs:` + # gate skips this job the moment ANY leg fails, discarding all of them. That is + # exactly what happened to v3.8.49: the linux leg died and the release shipped with + # ZERO assets, throwing away 1.7 GB of good Windows/macOS installers **and** the + # source archives + SBOM, which do not depend on a build at all. The result was + # indistinguishable from "this version has no desktop channel". + # Now: attach everything that did build, then fail the job loudly (see the last + # step) so an incomplete channel is visible instead of silent. + if: ${{ !cancelled() && needs.validate.result == 'success' }} runs-on: ubuntu-latest permissions: contents: write # softprops/action-gh-release creates the GitHub Release @@ -227,11 +249,33 @@ jobs: persist-credentials: false fetch-depth: 0 + # `merge-multiple` is deliberately OFF. It resolves same-name collisions by ARRIVAL + # ORDER, and the two macOS jobs each emit their own `latest-mac.yml` listing only their + # own dmg (measured: 338 and 350 bytes, different content, identical name). One silently + # overwrote the other — arm64 won in the published v3.8.48, and since the Intel dmg + # carries no arch suffix in its name, electron-updater's + # `files.find(url includes process.arch) ?? files.shift()` sends every Intel Mac to the + # ARM dmg. Downloading into per-artifact subdirectories keeps both, so they can be + # merged on purpose instead of by luck. - name: Download all artifacts uses: actions/download-artifact@v8 with: - path: release-assets - merge-multiple: true + path: artifacts + + # Writes release-assets/latest-mac.yml with BOTH dmgs, un-suffixed entry first (that is + # the one electron-updater can only reach through its fallback). Refuses to write when the + # inputs disagree on version — a manifest stitched from two builds is worse than none. + - name: Merge the per-arch macOS updater manifests + run: node scripts/release/merge-mac-update-manifest.mjs artifacts release-assets + + # Everything else moves across as-is. The partial latest-mac.yml files are excluded so + # they cannot clobber the merged one; -n is a second belt on the same braces. + - name: Collect the remaining artifacts + run: | + mkdir -p release-assets + find artifacts -type f ! -name latest-mac.yml -exec cp -n {} release-assets/ \; + echo "release-assets:" + ls -la release-assets/ - name: Create source archives env: @@ -275,6 +319,47 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + verify-desktop-assets: + name: Verify desktop assets landed + needs: [validate, release] + # Deliberately a SEPARATE job, not a final step of `release`: failing inside + # `release` would cascade into `publish-npm` (which gates on `needs: release`) and + # block the npm channel over a desktop-only gap. Here the assets are attached, npm + # still publishes, and an incomplete desktop channel shows up as a red job instead + # of passing unnoticed — the v3.8.49 release had ZERO assets and every gate was + # green, because nothing ever asserted the release HAS binaries. + if: ${{ !cancelled() && needs.release.result == 'success' }} + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Assert every platform is present on the release + env: + # Regex-validated (^v[0-9]+\.[0-9]+\.[0-9]+$) in the `validate` job, and + # passed via env rather than interpolated into the script body. + VERSION: ${{ needs.validate.outputs.version }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + names=$(gh release view "$VERSION" --repo "$GITHUB_REPOSITORY" \ + --json assets --jq '.assets[].name') + echo "Assets on $VERSION:" + echo "$names" | sed 's/^/ /' + + missing="" + # `[ ... ] && missing=...` as the last command in a branch returns 1 and + # would abort the whole script under Actions' default `set -e`. Use if/fi. + for want in '\.exe$' '\.dmg$' '\.AppImage$' '\.deb$' '^latest.*\.yml$' '\.source\.tar\.gz$'; do + if ! echo "$names" | grep -qE "$want"; then + missing="$missing $want" + fi + done + + if [ -n "$missing" ]; then + echo "::error::Desktop channel incomplete on $VERSION — no asset matching:$missing" + exit 1 + fi + echo "✓ every platform present on $VERSION" + publish-npm: name: Publish to npm needs: [validate, release] diff --git a/.github/workflows/nightly-release-green.yml b/.github/workflows/nightly-release-green.yml index 090b83c7d7..f435bf5acd 100644 --- a/.github/workflows/nightly-release-green.yml +++ b/.github/workflows/nightly-release-green.yml @@ -143,7 +143,8 @@ jobs: MODE="--with-build --full-ci" fi echo "[release-green] mode: $MODE (event: $EVENT_NAME)" - # shellcheck disable=SC2086 — MODE is an intentional flag list + # MODE is an intentional flag list, so word-splitting is wanted here + # shellcheck disable=SC2086 node scripts/quality/validate-release-green.mjs --json --hermetic $MODE \ 1> release-green.json 2> release-green.log echo "exit=$?" >> "$GITHUB_OUTPUT" @@ -248,7 +249,8 @@ jobs: MODE="--with-build --full-ci" fi echo "[main-green] mode: $MODE (event: $EVENT_NAME)" - # shellcheck disable=SC2086 — MODE is an intentional flag list + # MODE is an intentional flag list, so word-splitting is wanted here + # shellcheck disable=SC2086 node scripts/quality/validate-release-green.mjs --json --hermetic $MODE \ 1> main-green.json 2> main-green.log echo "exit=$?" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 692e6bd26c..16dc215a92 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -56,8 +56,15 @@ env: jobs: publish: - runs-on: ubuntu-latest + # Same dynamic-runner rule as ci.yml's `build`/`test-unit`: `build:cli` falls back to a + # full `next build`, whose working set outgrew the 16 GB hosted runner during the + # v3.8.49 cycle — the publish died with "The runner has received a shutdown signal" + # mid-"Creating an optimized production build" while v3.8.48 had still fit in 16min. + # This job never runs on `pull_request`, so the fork-safety clause is always true here; + # it is kept verbatim so the expression stays greppable against ci.yml. + runs-on: ${{ (vars.USE_VPS_RUNNER == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)) && fromJSON('["self-hosted","omni-release"]') || 'ubuntu-latest' }} permissions: + actions: read # find + download the CI run's next-build artifact for this SHA contents: write # gh release upload (attach SBOM to the GitHub Release) id-token: write # npm provenance packages: write # publish to npm.pkg.github.com @@ -145,6 +152,74 @@ jobs: run: | npm version "$VERSION" --no-git-tag-version --allow-same-version + # Fast path: CI already built the standalone tree for THIS commit and uploaded it as + # `next-build`. `build:cli` (scripts/build/prepublish.ts) only shells out to a full + # `next build` when `.build/next/standalone/server.js` is missing — restoring the + # artifact turns the heaviest step of the publish into a download. Matching on + # `head_sha` is the tree-equality guarantee: same commit, same tree. + # Best-effort by design (retention is 1 day): every miss falls through to the build + # step below, which is why the dynamic runner above matters as the backstop. + # + # The `head_repository.full_name == env.REPO` clause is a supply-chain guard, not a + # filter refinement. This artifact becomes the published npm tarball. `pull_request` + # runs from forks execute in THIS repository's context and upload their own + # `next-build` built from fork-controlled source, and the runs API returns them for a + # matching `head_sha` — 57 such runs exist in this repo today. Without the clause, + # anything that made a fork's head commit coincide with the publish commit could put + # attacker-built bytes on npm. Requiring the run to originate from this repository + # excludes every fork run while keeping the fast path intact (verified: the same + # single run is selected either way for the current tip). + # CodeQL: actions/artifact-poisoning/critical. + - name: Reuse CI's next-build artifact (skips the heavy rebuild) + if: steps.resolve.outputs.skip != 'true' + continue-on-error: true + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + HEAD_SHA: ${{ github.sha }} + REPO: ${{ github.repository }} + run: | + set -uo pipefail + # The question is "which run HAS the artifact", not "which run passed" (gap 16). + # Requiring `conclusion == "success"` on the whole run discarded a perfectly good tree + # whenever any unrelated shard went red — one flaky test then pushed the publish into + # the 40-minute build this step exists to avoid. The artifact is only uploaded if the + # Build job itself succeeded, so its PRESENCE is the accurate signal; the run's overall + # conclusion is noise from jobs that have nothing to do with the tree. + # + # `head_repository.full_name == env.REPO` stays, and it is not a filter refinement: + # this tree becomes the published npm tarball, and fork `pull_request` runs execute in + # THIS repository's context uploading their own next-build. That clause is the + # supply-chain guard (CodeQL actions/artifact-poisoning). + CANDIDATES=$(gh api "repos/$REPO/actions/runs?head_sha=$HEAD_SHA&per_page=100" \ + --jq '[.workflow_runs[] + | select(.name == "CI" + and .head_repository.full_name == env.REPO)] + | sort_by(.run_started_at) | reverse | .[0:5] | .[].id') || CANDIDATES="" + if [ -z "$CANDIDATES" ]; then + echo "::notice::no CI run from this repository for $HEAD_SHA — falling back to a full build" + exit 0 + fi + RUN="" + for candidate in $CANDIDATES; do + if gh run download "$candidate" --repo "$REPO" --name next-build --dir /tmp/next-build 2>/dev/null; then + RUN="$candidate" + break + fi + echo " run $candidate carries no usable next-build — trying the next" + done + if [ -z "$RUN" ]; then + echo "::notice::none of the candidate runs still carries next-build (1-day retention) — falling back to a full build" + exit 0 + fi + tar -xzf /tmp/next-build/e2e-build.tar.gz -C . + rm -rf /tmp/next-build + if [ -f .build/next/standalone/server.js ]; then + echo "✅ standalone tree restored from CI run $RUN — build:cli will skip next build" + else + echo "::notice::extract did not yield .build/next/standalone — falling back to a full build" + rm -rf .build + fi + - name: Build CLI bundle (standalone app) if: steps.resolve.outputs.skip != 'true' env: @@ -181,6 +256,18 @@ jobs: if: steps.resolve.outputs.skip != 'true' run: npm run check:pack-boot + # The boot-smoke above proves a CLEAN install boots. It does not prove the path that + # actually broke us: installing over an existing version, where ~110 SQLite migrations + # run against a populated database. v3.8.48 shipped as a hotfix because the published + # 3.8.47 crashed on boot, and the v3.8.49 upgrade path was first exercised end-to-end + # by hand on a real 3.8.48 box (VPS .16) — after publishing, which is exactly backwards. + # Runs BEFORE `npm stage publish` so a broken upgrade never reaches the registry at all; + # a staged package that is never approved simply expires, with no `npm deprecate` needed. + - name: Prove clean-install AND upgrade-over-previous both boot + if: steps.resolve.outputs.skip != 'true' + timeout-minutes: 30 + run: npm run check:install-upgrade + # WS1.3 (D2, v3.8.49 plan): STAGED publishing by default — `npm stage publish` # parks the exact bytes on the registry WITHOUT making them installable; the # owner then verifies and approves with 2FA (`npm stage approve`), moving the diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 0b2e854031..7a9a1d2f87 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -112,7 +112,20 @@ jobs: # release captain has USE_VPS_RUNNER=true AND this is not a fork PR (own-origin # branches only — a fork PR must never execute on the LAN runner). Var unset/false # or a fork PR falls back to ubuntu-latest, so this is inert until the flag flips. - runs-on: ${{ (vars.USE_VPS_RUNNER == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)) && fromJSON('["self-hosted","omni-release"]') || 'ubuntu-latest' }} + # PINNED to hosted (gap 19). This job carried the USE_VPS_RUNNER expression, and that + # expression was DEAD CONFIGURATION: across 160 quality.yml runs the job never once landed on + # a self-hosted runner — every non-skipped sample is `GitHub Actions NNNN`. The classifier is + # not at fault: in the same window ci.yml's Build demonstrably ran on omniroute-113-7 and + # omniroute-113-6, so self-hosted runs are visible when they happen. + # + # And if it ever HAD fired it would have inherited the measured penalty, because this job's + # first two steps are exactly the bottleneck: actions/setup-node + npm ci took 20m06s on .113 + # with 4 concurrent runners versus 16s hosted (npm cache restore saturating the link). Median + # here is 5.6 min hosted across 72 successful runs. + # + # With this pinned, USE_VPS_RUNNER governs ONLY build-like jobs — one variable, one coherent + # purpose. That is what gap 19 asked for; a second variable turned out to be unnecessary. + runs-on: ubuntu-latest # tsx gates (known-symbols, route-guard-membership) import modules that open # SQLite on load; provide DB env so a fresh CI DB initializes cleanly. env: @@ -260,7 +273,13 @@ jobs: needs: changes if: ${{ github.event_name != 'pull_request' || ((github.event.pull_request.draft == false || startsWith(github.head_ref, 'mergify/merge-queue/')) && needs.changes.outputs.code == 'true') }} # Dynamic runner — see fast-gates (own-origin + flag; fork/unset → ubuntu-latest). - runs-on: ${{ (vars.USE_VPS_RUNNER == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)) && fromJSON('["self-hosted","omni-release"]') || 'ubuntu-latest' }} + # PINNED to hosted, deliberately not on the USE_VPS_RUNNER switch (gap 19). One variable + # governed the build and the test jobs, which want OPPOSITE machines: the build needs the + # .113's RAM, the tests need the hosted runner's link. Measured on 2026-07-29 — + # actions/setup-node took 20m06s on .113 with 4 concurrent runners versus 16s hosted (npm + # cache restore saturating the link), while the tests themselves tied, 2m54 vs 2m31. So + # self-hosted is strictly worse here and there is nothing to configure. + runs-on: ubuntu-latest env: JWT_SECRET: ci-lint-secret-with-sufficient-length-for-validation API_KEY_SECRET: ci-lint-api-key-secret-long @@ -296,7 +315,13 @@ jobs: # critical path again (~8.5min → ~4.5min on ubuntu-latest; ~2min on the 8-slot # runner box). Node's native --test-shard=N/total takes any denominator — only # this matrix and the TEST_SHARD env below encode the shard count. - runs-on: ${{ (vars.USE_VPS_RUNNER == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)) && fromJSON('["self-hosted","omni-release"]') || 'ubuntu-latest' }} + # PINNED to hosted, deliberately not on the USE_VPS_RUNNER switch (gap 19). One variable + # governed the build and the test jobs, which want OPPOSITE machines: the build needs the + # .113's RAM, the tests need the hosted runner's link. Measured on 2026-07-29 — + # actions/setup-node took 20m06s on .113 with 4 concurrent runners versus 16s hosted (npm + # cache restore saturating the link), while the tests themselves tied, 2m54 vs 2m31. So + # self-hosted is strictly worse here and there is nothing to configure. + runs-on: ubuntu-latest strategy: fail-fast: false matrix: diff --git a/.gitleaks.toml b/.gitleaks.toml index 8b9978a454..22023b1a8d 100644 --- a/.gitleaks.toml +++ b/.gitleaks.toml @@ -86,4 +86,10 @@ regexes = [ '''latencyP\d{2}Ms''', '''interleaved-thinking-2025-05-14''', + # v3.8.49 pre-flight (2026-07-28). Nenhum dos dois e credencial: + # - chave de localStorage do banner de patrocinio (#8723), so um identificador de UI; + # - x-api-key PUBLICO do Firefly web (documentado em open-sse/utils/publicCreds.ts:207); + # as duas ocorrencias sinalizadas estao em COMENTARIOS JSDoc, o runtime le de resolvePublicCred(). + '''omniroute-kimi-sponsor-banner-dismissed-v1''', + '''SunbreakWebUI1''', ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 29b8eb8352..4039a8f7c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -297,6 +297,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -310,6 +326,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1023,6 +1041,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1054,6 +1188,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1066,6 +1211,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1104,6 +1254,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1136,6 +1338,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1236,15 +1440,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1252,6 +1455,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1259,13 +1463,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1275,35 +1480,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1316,6 +1527,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1323,24 +1536,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1348,32 +1567,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1394,7 +1617,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/README.md b/README.md index 00394b5fc0..2f89a9a7e7 100644 --- a/README.md +++ b/README.md @@ -67,32 +67,46 @@ - - - + + + + - - - - -
🚀 Quick Start🎯 Combos🌐 Providers🚀 Start🚀 Quick Start📦 Install🆓 Zero-config
🔌 CLI & MCP🗜️ Compression🌍 Website
- - - + - + - + + + + + + + + + - - + + + + + + + + + + + + + +
💡 Learn 💥 The Promise🤔 Why🤔 Why OmniRoute 🏆 What Sets Apart
🤖 Compatible CLIs⚙️ Features🎯 Combos🌐 Providers🔌 CLI & MCP
🗜️ Compression 🖥️ Where It Runs 🔒 Private
👀 See it 🎬 In Action📸 Screenshots📧 Support✨ What's New🤖 Compatible CLIs
💚 Support💚 Support / Donate💬 Community💖 Sponsors
📦 Project🛠️ Tech Stack📖 Docs👥 Contributors
@@ -390,13 +404,50 @@ All **19** strategies — mix & match per combo step:
-## ❤️ Support +## 💚 Support OmniRoute -OmniRoute is free and open source, built and maintained in the open. If it saves you time or money, consider supporting development: +OmniRoute is MIT-licensed and maintained in the open. If it saves you time or money, here's how to keep it independent — pick whatever fits you. Sponsorship never affects routing priority; it buys visibility, not ranking. -- ⭐ **Star the repo** — it genuinely helps visibility -- 💖 **[GitHub Sponsors](https://github.com/sponsors/diegosouzapw)** — fund ongoing maintenance and new providers -- 🐛 **Report bugs and share feedback** in [Discussions](https://github.com/diegosouzapw/OmniRoute/discussions) + + + + + + + + + +
Star the repoFree — genuinely helps visibilityStar OmniRoute
🐙 GitHub SponsorsOne-off or monthly · zero platform feegithub.com/sponsors/diegosouzapw
🏢 Open CollectiveCompanies — issues an invoice/receipt · transparent booksopencollective.com/omniroute
Ko-fiQuick one-off tip, no signup for the donorko-fi.com/diegosouzapw
🧋 Buy Me a CoffeeSmall, informal gesturebuymeacoffee.com/diegosouzapw
🖐 LiberapayRecurring · non-profit · open sourceliberapay.com/diegosouzapw
🇧🇷 PIX (Brazil)Instant, no feeskey & QR below
CryptoBTC · ETH · USDT-TRC20 · USDC-Solanaaddresses below
+ +**🇧🇷 PIX** — instant, no fees (Brazil) + +OmniRoute PIX QR code + +Key (random): `5d865059-bc44-483a-962d-43ceb80126eb` + +Pix copia-e-cola: + +``` +00020101021126580014br.gov.bcb.pix01365d865059-bc44-483a-962d-43ceb80126eb5204000053039865802BR5922OMNIROUTE CONTRIBUICAO6006BRASIL62070503***630475DD +``` + +
+ +
+₿ Crypto — BTC · ETH · USDT-TRC20 · USDC-Solana (click to expand) + + + + + + +
₿ BTCBitcoin (SegWit)bc1qh00smz004sy85wyl28v77tenkt3ckl6eaep7fd
Ξ ETHEthereum (ERC20)0x64Cf6B68A6Ff34288e89172950a2d00102337a84
₮ USDTTron (TRC20)TKAF41JpuQrHbKTnsQa9svJE2T192Hvsc2
$ USDCSolana2emNNZzVVWQc3FQ2wk9M6qXUQmW8AKdjjL174fXR28Tu
+ +⚠️ Send each coin only on the network shown — sending on the wrong network can lose the funds. + +
+ +🐛 Found a bug or have feedback? Open a [Discussion](https://github.com/diegosouzapw/OmniRoute/discussions).
@@ -418,11 +469,12 @@ OmniRoute is free and open source, built and maintained in the open. If it saves - **🕵️ Transparent MITM decrypt (TPROXY)** — capture CLIs that ignore proxy env vars, with a per-SNI CA + trust-store installer. → [MITM/TPROXY](docs/security/MITM-TPROXY-DECRYPT.md) - **💸 Cost telemetry everywhere** — `X-OmniRoute-*` cost/usage headers on every endpoint, cache-HIT savings header, per-key USD spend quotas. → [API Reference](docs/reference/API_REFERENCE.md) - **🧠 Memory you control** — off by default, opt-in int8 vector quantization + typed decay, per-request `x-omniroute-no-memory`. → [Memory](docs/frameworks/MEMORY.md) -- **🛡️ Security** — prompt-injection guard on every LLM route (red-team suite) + free DuckDuckGo last-resort web search. → [Guardrails](docs/security/GUARDRAILS.md) +- **🛡️ Security** — prompt-injection guard on every LLM route (red-team suite), opt-in credential-masking guardrail (redacts leaked API keys/secrets in both directions), free DuckDuckGo last-resort web search, and an optional OIDC login gate for the dashboard (password login always stays available). → [Guardrails](docs/security/GUARDRAILS.md) - **🖼️ New endpoints** — `/v1/ocr` (Mistral OCR) and `/v1/audio/translations` (Whisper-style) round out the media surface. → [API Reference](docs/reference/API_REFERENCE.md) - **🎨 Image / video / audio generation** — one API for media: xAI Grok Imagine & Novita AI video, ComfyUI, Freepik, Adobe Firefly, Microsoft Designer, Google Imagen, Segmind, EdgeTTS. → [API Reference](docs/reference/API_REFERENCE.md) - **🌍 Deployment & ops** — reverse-proxy `basePath`, browser-language auto-detect, per-key device tracking, root-less MITM trust, zh-TW localization. → [Environment](docs/reference/ENVIRONMENT.md) -- **🤝 More providers & agents** — Cursor Cloud Agent, Grok Build (xAI), Ollama first-class card, Claude Sonnet 5, Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed **290-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.md) +- **🤝 More providers & agents** — Cursor Cloud Agent, Grok Build (xAI) with browser + OAuth login, Ollama first-class card, Claude Opus 5 & Sonnet 5, Kimi official partnership (Code/Web/Moonshot), Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed **290-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.md) +- **📡 Routing transparency** — every response carries an `X-OmniRoute-Decision` header naming the strategy/provider/latency that served it, a new `cache-optimized` combo strategy + Auto-Combo `cacheAffinity` factor route repeat requests back to the connection holding the cached prefix, and a read-only `/v1/auto-combo/{channel}/candidates` endpoint exposes an `auto/*` channel's live candidate pool. → [Auto-Combo](docs/routing/AUTO-COMBO.md) - **⚡ Local performance & infra** — one-click local Redis, Cloudflare Workers / Deno Deploy relay deployers, Bifrost & Mux as supervised embedded services. → [Embedded Services](docs/frameworks/EMBEDDED-SERVICES.md)
@@ -904,7 +956,7 @@ same process on one port, so there is no separate CLI-only package today.
-# 📧 Support & Community +# 📧 Community & Help > Everything in one place — follow the maintainer, chat with the community, or open an issue. @@ -920,7 +972,7 @@ same process on one port, so there is no separate CLI-only package today. | 📦 **Source code** | [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute) | | 🐛 **Report a bug** | [open an issue](https://github.com/diegosouzapw/OmniRoute/issues) — attach `npm run system-info` output | | 🤝 **Contribute** | [CONTRIBUTING.md](CONTRIBUTING.md) · [Branching & Release Model](docs/ops/BRANCHING_MODEL.md) · pick a `good first issue` | -| ⭐ **Support the project** | [Star the repo](https://github.com/diegosouzapw/OmniRoute) · [GitHub Sponsors](https://github.com/sponsors/diegosouzapw) | +| 💚 **Support the project** | [Ways to support ↑](#-support-omniroute) · [GitHub Sponsors](https://github.com/sponsors/diegosouzapw) |
diff --git a/changelog.d/features/8980-deprecate-gemini-cli-provider.md b/changelog.d/features/8980-deprecate-gemini-cli-provider.md new file mode 100644 index 0000000000..38a826a2e7 --- /dev/null +++ b/changelog.d/features/8980-deprecate-gemini-cli-provider.md @@ -0,0 +1 @@ +- **feat(sse):** deprecated the legacy `gemini-cli` **upstream provider**. It was not routable (no registry entry, no executor), yet the scheduler kept refreshing its token against Google — maintaining a credential that could never serve a request. A stored connection now becomes terminal with a legible reason and a working migration path: re-add the account under `gemini`, which uses the same Google OAuth client. The `gemini-cli` **client identity** (requests arriving *from* the Gemini CLI, issue #7034) is untouched ([#8980](https://github.com/diegosouzapw/OmniRoute/pull/8980)) diff --git a/changelog.d/fixes/8985-release-tooling-hidden-work.md b/changelog.d/fixes/8985-release-tooling-hidden-work.md new file mode 100644 index 0000000000..8f6aca73ce --- /dev/null +++ b/changelog.d/fixes/8985-release-tooling-hidden-work.md @@ -0,0 +1 @@ +- **fix(ci):** the reconciliation helper no longer bounds its scan with `git describe --tags` — releases squash-merge, so that range re-listed 1361 commits instead of the cycle's real 22, which is how ~200 PRs once slipped through without a changelog bullet. The base is now resolved from the commit that opened the cycle, and a new `sweep:stale-fragments` gate removes `changelog.d/` fragments that a back-merge from `main` resurrected after they had already been folded in ([#8985](https://github.com/diegosouzapw/OmniRoute/pull/8985)) diff --git a/changelog.d/fixes/8988-mac-updater-manifest-and-runner-split.md b/changelog.d/fixes/8988-mac-updater-manifest-and-runner-split.md new file mode 100644 index 0000000000..c749f2ed76 --- /dev/null +++ b/changelog.d/fixes/8988-mac-updater-manifest-and-runner-split.md @@ -0,0 +1 @@ +- **fix(ci):** fixed a live auto-update defect where **Intel Macs downloaded the ARM dmg** — the two macOS jobs each emitted their own `latest-mac.yml` and `merge-multiple` let one silently overwrite the other by arrival order, leaving `electron-updater`'s arch fallback pointing at the wrong build. The manifests are now merged deliberately, un-suffixed entry first. Also: test jobs pinned to hosted runners (`setup-node` measured 20m06s self-hosted vs 16s hosted), the npm publish no longer discards a valid build artifact because an unrelated shard was flaky, the agent-skills gate now runs on pushes to `main` instead of PRs only, and the CI summary names every job that ended cancelled ([#8988](https://github.com/diegosouzapw/OmniRoute/pull/8988)) diff --git a/changelog.d/maintenance/8966-remove-iflow-ttl.md b/changelog.d/maintenance/8966-remove-iflow-ttl.md new file mode 100644 index 0000000000..588d891955 --- /dev/null +++ b/changelog.d/maintenance/8966-remove-iflow-ttl.md @@ -0,0 +1 @@ +- **chore(sse):** dropped the leftover `iflow` entry from the token-refresh TTL map — the provider was removed from the product but its 24-hour refresh lead outlived it, and the identifier had exactly two occurrences left repo-wide ([#8966](https://github.com/diegosouzapw/OmniRoute/pull/8966)) diff --git a/changelog.d/maintenance/8967-remove-fork-publish-workflows.md b/changelog.d/maintenance/8967-remove-fork-publish-workflows.md new file mode 100644 index 0000000000..d07d91980a --- /dev/null +++ b/changelog.d/maintenance/8967-remove-fork-publish-workflows.md @@ -0,0 +1 @@ +- **chore(ci):** removed two fork-owned image-publish workflows that had ridden into the repo as unrelated extra files in on-topic PRs — `build-fork.yml` (`ghcr.io/kang-heewon`, job-level guard, so it instantiated a skipped run on every push to main and every tag) and `build-rinseaid-image.yml` (`ghcr.io/rinseaid`, no guard, never fired). Neither could authenticate against this repository's token; a new policy guard now fails CI on any workflow targeting a foreign registry namespace ([#8967](https://github.com/diegosouzapw/OmniRoute/pull/8967)) diff --git a/changelog.d/maintenance/8977-promote-latest-test-epipe.md b/changelog.d/maintenance/8977-promote-latest-test-epipe.md new file mode 100644 index 0000000000..e563dda84f --- /dev/null +++ b/changelog.d/maintenance/8977-promote-latest-test-epipe.md @@ -0,0 +1 @@ +- **test(ci):** fixed the intermittent `spawnSync bash EPIPE` failure in the `:latest` promotion guard — the script exits on a pre-release version before reading stdin, so the harness's pipe-backed `input:` raced that exit; stdin is now file-backed, which makes the race structurally impossible ([#8977](https://github.com/diegosouzapw/OmniRoute/pull/8977)) diff --git a/config/quality/eslint-suppressions.json b/config/quality/eslint-suppressions.json index 9f9b5f5b78..a29906c409 100644 --- a/config/quality/eslint-suppressions.json +++ b/config/quality/eslint-suppressions.json @@ -2410,4 +2410,4 @@ "count": 5 } } -} +} \ No newline at end of file diff --git a/config/quality/file-size-baseline.json b/config/quality/file-size-baseline.json index c4e3c54993..1a86420683 100644 --- a/config/quality/file-size-baseline.json +++ b/config/quality/file-size-baseline.json @@ -173,7 +173,7 @@ "_rebaseline_basered_codebuddy_cn": "Base-red fix (#4664 CodeBuddy CN): oauth-providers-config.test.ts 867->870 (+3) to align the EXPECTED provider list/config with the codebuddy-cn provider that #4664 added to the registry without updating this test (it asserts 'exactly once').", "_rebaseline_pr4613_compatible_provider_groups": "Reconcile #4613 already-merged growth: providers-page-utils.test.ts 1004->1052 (+48, buildCompatibleProviderGroups partition unit test). Fast-gate PR->release does not run check:file-size, so this surfaced post-merge.", "tests/integration/chat-pipeline.test.ts": 1592, - "tests/integration/chatcore-compression-integration.test.ts": 1111, + "tests/integration/chatcore-compression-integration.test.ts": 1114, "tests/unit/account-fallback-service.test.ts": 1563, "tests/unit/batch_api.test.ts": 1324, "tests/unit/cc-compatible-provider.test.ts": 1217, @@ -366,7 +366,7 @@ "open-sse/translator/response/openai-responses.ts": 1174, "open-sse/utils/cursorAgentProtobuf.ts": 1505, "open-sse/utils/stream.ts": 2887, - "src/app/(dashboard)/dashboard/HomePageClient.tsx": 1377, + "src/app/(dashboard)/dashboard/HomePageClient.tsx": 1381, "src/app/(dashboard)/dashboard/analytics/ComboHealthTab.tsx": 1031, "src/app/(dashboard)/dashboard/api-manager/ApiManagerPageClient.tsx": 3117, "src/app/(dashboard)/dashboard/cache/media/MediaPageClient.tsx": 1067, @@ -412,5 +412,6 @@ "_rebaseline_2026_07_28_8842_antigravity_test": "PR #8842 test growth: tests/unit/executor-antigravity.test.ts new testFrozen 1098 (4 new test cases for projectId discovery during refresh: discovers when empty, skips when set, handles failure, skips when access_token not a string). All above cap 1000 on day one.", "_rebaseline_2026_07_28_8860_tokenrefresh_projectid": "PR #8860 (fix/antigravity-projectid-centralized) own test growth: tests/unit/token-refresh-service.test.ts 1311->1378 (+67 = 4 cases covering projectId discovery on the tokenRefresh.ts path — the Dashboard/health-check refresh route, which #8842 did not reach since that fixed the executor path). Covered by the same file.", "_rebaseline_2026_07_28_8861_xiaomi_token_plan": "PR #8861 (feat/xiaomi-token-plan-protocol-selector) own growth: EditConnectionModal.tsx 1283->1316 (+33 = the per-connection API-protocol selector field) and open-sse/executors/base.ts 1540->1562 (+22 = alternate-format resolution at the existing buildUrl/headers chokepoint). Both are irreducible wiring at existing call sites.", - "_rebaseline_2026_07_28_8863_firefly_detail_level": "PR #8863 (fix/adobe-firefly-gpt-detail-level-max) own growth: adobeFireflyClient.ts 2317->2322 (+5 = gpt-image detailLevel defaulting to maximal at the existing payload-build site). Covered by tests/unit/adobe-firefly.test.ts." + "_rebaseline_2026_07_28_8863_firefly_detail_level": "PR #8863 (fix/adobe-firefly-gpt-detail-level-max) own growth: adobeFireflyClient.ts 2317->2322 (+5 = gpt-image detailLevel defaulting to maximal at the existing payload-build site). Covered by tests/unit/adobe-firefly.test.ts.", + "_rebaseline_2026_07_29_8281_home_quickstart_prefetch": "Release v3.8.49 base-red fix (no PR — captain sweep): src/app/(dashboard)/dashboard/HomePageClient.tsx 1377->1381 (+4). #8292 added prefetch={false} to the sidebar but left /home's five quick-start Links prefetching, so first paint still fired 12 speculative RSC requests — caught by navigation.spec.ts only after the e2e helper bug (APP_ROUTE_PATTERN missing /home) was repaired in the same cycle. Growth is the five prefetch attributes; it was offset first by extracting the repeated className literals (INLINE_LINK x4, DOCS_LINK x1), which collapsed five wrapped blocks back to one line each — a naive fix measured 1391. Guard: tests/unit/sidebar-prefetch-policy-8281.test.ts." } diff --git a/config/quality/install-upgrade-allowlist.json b/config/quality/install-upgrade-allowlist.json new file mode 100644 index 0000000000..4e6f3c6891 --- /dev/null +++ b/config/quality/install-upgrade-allowlist.json @@ -0,0 +1,6 @@ +{ + "_doc": "Tables that exist ONLY in databases upgraded from an older version — residue whose CREATE left the migration set in some past cycle but survives where it already existed. Harmless (nothing references them), but recorded here so check-install-upgrade.mjs can still fail on a NEW divergence. The opposite direction (a table a clean install creates but an upgrade does not) is NEVER allowlisted: it means every existing user is missing structure the code expects.", + "residualTables": { + "cache_metrics": "Measured 2026-07-30 on a real 3.8.48 install upgraded to 3.8.49 (VPS .16, 165 MB database, 114 → 117 tables). Present in upgraded databases, absent from clean installs. No code path referenced it during the upgrade (zero `no such table` in 150 log lines, both installs healthy). Left in place rather than dropped: a DROP migration on a table we cannot prove is unused everywhere is the riskier change. Revisit when the cache subsystem is next touched." + } +} diff --git a/config/quality/quality-baseline.json b/config/quality/quality-baseline.json index b146524306..53eab2e62b 100644 --- a/config/quality/quality-baseline.json +++ b/config/quality/quality-baseline.json @@ -6,19 +6,19 @@ "_rebaseline_2026_07_03_v3844_residual_release_green": "4270->4279 (+9). v3.8.44 residual drift on release tip 716041223 (moving target: eslint 4270->4279 as the branch advanced past the prior rebaseline). Inherited from parallel-session merges (Quality Ratchet not on PR->release fast-gates).", "_rebaseline_2026_07_03_v3844_ipfilter_release_green": "4256->4270 (+14). v3.8.44 cycle drift measured on release tip 32e4c906e during the #6131/#5975 release-green rebaseline. Inherited from the merge burst (Quality Ratchet does not run on PR->release fast-gates). route-edge-coverage +7 is my #5975 test comment; the rest is parallel-session drift. Tighten via --update next cycle.", "_rebaseline_2026_07_03_v3844_review_prs_fix_batch": "4199->4256 (+57). Inherited v3.8.44 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrue unmeasured across the cycle). 4256 = measured by `node scripts/quality/collect-metrics.mjs` on the release tip 72ee80649 during the /review-prs fix-batch round. The round's own merges (#5958 SSE-accept, #5988 deepseek-web, #6013/#5974 retry-after-json, #5975 embeddings-proxy, #5973 non-json-guard) plus the parallel-session merge burst into release/v3.8.44 account for the delta; all `any`-warn-allowed in open-sse/ + tests/. Cyclomatic is already green (2012 < baseline 2015) and needs no bump. Tighten via --require-tighten next cycle.", - "_rebaseline_2026_07_02_v3843_release_close": "4158->4199 (+41). v3.8.43 release-close drift measured by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across the ~120 commits merged after the mid-cycle 4158 rebaseline \u2014 the compression T02/T05/T06/T07/T08/T10 engine families, memory typed decay, provider adds Ollama/SenseNova, ~55 SSE/translator/kiro/oauth/dashboard fixes, and the god-file decomposition wave). Trust-but-verify: measured 4199 via `npm run lint` on the release-finalize working tree INCLUDING my changes (CHANGELOG/i18n/README docs + kiro pricing data entry + the 3 base-red CODE fixes: opencode fabrication removal, resolveEffectiveKey type-widen, openai-to-claude claudeFinishEmitted flag + 4 test-alignment files + golden snapshot regen) \u2014 the code fixes NET-REMOVE lines and add no `any`/unused, and lint reported 4199 both before and after them, so all +41 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", + "_rebaseline_2026_07_02_v3843_release_close": "4158->4199 (+41). v3.8.43 release-close drift measured by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across the ~120 commits merged after the mid-cycle 4158 rebaseline — the compression T02/T05/T06/T07/T08/T10 engine families, memory typed decay, provider adds Ollama/SenseNova, ~55 SSE/translator/kiro/oauth/dashboard fixes, and the god-file decomposition wave). Trust-but-verify: measured 4199 via `npm run lint` on the release-finalize working tree INCLUDING my changes (CHANGELOG/i18n/README docs + kiro pricing data entry + the 3 base-red CODE fixes: opencode fabrication removal, resolveEffectiveKey type-widen, openai-to-claude claudeFinishEmitted flag + 4 test-alignment files + golden snapshot regen) — the code fixes NET-REMOVE lines and add no `any`/unused, and lint reported 4199 both before and after them, so all +41 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", "direction": "down", "_rebaseline_2026_07_01_v3843_release": "4121->4158 (+37). v3.8.43 cycle drift surfaced by the release-green pre-flight; the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle. 4158 = the value measured by the CI Quality Ratchet on the release tip fce85136c (release PR #5609). Trust-but-verify: the fix/release-v3843-ci-reds branch touches only test files (rtk-mcp-tools de-flake, compression-studio e2e anchor, oauth-error-linkify hardening test) + src/shared/utils/linkify.ts (eslint-clean, 0 warnings) + stryker.conf.json + this baseline -> 0 new warnings, so all +37 is inherited cycle drift (any warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", - "_rebaseline_2026_06_30_v3842_release": "4116->4121 (+5). v3.8.42 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's 90 commits \u2014 chatgpt-web PoW sha3-512 BoringSSL fix #5540, provider baseUrl/i18n umbrella #5511, proxy union proxyUrlMap+acct.proxy #5521, dead-code + duplication waves #5468-#5495, tls-options packaging #5503, release-freeze + .npmrc fetch-retries #5506, dast-smoke spawn-prefix client-safe extraction #5546, plus ~30 SSE/translator/combo/dashboard fixes). Trust-but-verify: measured 4121 via `npm run check:release-green` on the working tree INCLUDING my reconciliation (CHANGELOG/i18n/golden snapshot + file-size baseline) \u2014 those touch only config JSON + a provider snapshot (eslint-ignored) and contribute 0 warnings; all +5 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", - "_rebaseline_2026_06_29_v3841_release": "4103->4116 (+13). v3.8.41 cycle drift surfaced by the release-green collect (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's 52 commits \u2014 relay backend #5315, gemini catalog #5337, services dashboard #5299, empty-Claude-messages guard #5342, thinking-budget/redacted-replay + marker opt-out #5312/#5352/#5367, opencode proxy-pool + observability #5217/#5370/#5351, cors + HTTPS-serve #5242/#5360/#5361, grok cf_clearance #5350/#5358, oauth/chatgpt-web/routing/cli/dashboard/rerank #5326/#5240/#5239/#5238/#5264/#5332, partially offset by the dead-code sweep #5321-#5371). Trust-but-verify: measured 4116 via `npm run quality:collect` on the working tree INCLUDING my reconciliation (CHANGELOG/i18n/README/env docs + baselines) AND the lint-fix in useServiceLogs.ts \u2014 that fix REMOVES a setState-in-effect ERROR (eslintErrors stays 0) and adds an `open` listener with no `any`/unused, contributing 0 warnings; all +13 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", - "_rebaseline_2026_06_29_v3840_release": "4090->4103 (+13). v3.8.40 cycle drift surfaced by the release-green pre-flight + the release PR Quality Ratchet (the ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's ~57 commits \u2014 compression roadmap relevance/hard-budget/memoization/transparency/saliency/splitter/tool_search/RTK/QuantumLock #5289/#5288/#5286/#5284/#5285/#5283/#5269/#5268/#5260, ~20 SSE/translator/combo fixes #5248/#5250/#5254/#5261/#5255/#5273/#5258, M365 Copilot provider #5302, public-origin centralization #5278). Trust-but-verify: measured 4103 locally via `npm run quality:collect` on the release tip INCLUDING my reconciliation commits (CHANGELOG + main merge + the 2 regression test fixes 165c823f5) \u2014 the test fixes add 0 `any`/warnings (health-autopilot added a NextRequest import + asserts; chat-pipeline changed one Accept string + a comment), so all +13 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", - "_rebaseline_2026_06_28_v3839_release": "4002->4090 (+88). v3.8.39 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's 40 commits \u2014 antigravity remote-login + quota-family #5203/#5180/#5193, compression CCR-retrieve + TOON encoder #5187/#5163, ~20 SSE/translator/responses fixes #5156/#5154/#5197/#5204/#5158/#5123/#5166, proxy/health hardening #5202/#5208/#5209/#5201 from @KooshaPari, combo quota-share/context-relay E2E tests #5179/#5168/#5195). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, README.md and these baselines \u2014 0 production-code change, so all +88 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", - "_rebaseline_2026_06_27_v3838_release": "3987->4002 (+15). v3.8.38 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's ~78 commits \u2014 provider adds Factory/Grok-Build/ZenMux-Free/Alibaba-video, ~30 SSE/translator/diagnostics fixes, compression fidelity-gate + playground #5080/#5143, Fusion editor #5074, salvage batches #5138/#5141). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, README.md and these baselines \u2014 0 production-code change, so all +15 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", - "_rebaseline_2026_06_25_v3836_release": "v3.8.36 cycle drift surfaced by the post-merge fix PR #5029 (the Quality Ratchet was SKIPPED on the release PR #4854 itself, and does NOT run on the PR\u2192release fast-gates, so warnings accrued unmeasured across this cycle's 137 commits \u2014 Quota-Share Fase 2/3 features, god-file decomposition #3501/#4811-#4956, 14 external contributor PRs). 3912\u21923970 (+58), the exact value measured by the CI Quality Ratchet on #5029. Trust-but-verify: this fix PR touches ONLY scripts/build/pack-artifact-policy.ts (a string-literal allowlist array, scripts/ is eslint-light) and tests/integration/resilience-http-e2e.test.ts (2 string keys, no `any`) \u2014 0 new warnings, so all +58 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Same precedent as _rebaseline_2026_06_23_v3835_release. Tighten via --require-tighten next cycle.", - "_rebaseline_2026_06_23_v3835_release": "v3.8.35 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR\u2192release fast-gates, so warnings accrued across this cycle's parallel-session merges \u2014 Compression Phase 4 #4694/#4707/#4716/#4720, chatCore #3501 leaf extractions, contributor PRs #4726/#4753/#4774/#4781/#4783/#4793, etc.). 3907\u21923912 (+5). Verified my release-finalize working tree touches ONLY docs/*.md (THREAT_MODEL), CHANGELOG.md, baselines, and 1 string line in scripts/check/check-fabricated-docs.mjs \u2014 0 production-code change, so all +5 is inherited contributor drift. No coverage/openapi/i18n regressions.", - "_rebaseline_2026_06_22_v3834_release": "v3.8.34 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR\u2192release fast-gates, so warnings accrued across this cycle's parallel-session merges \u2014 #4583-4586/#4588-4593/#4606-4621/#4644/#4647/#4696/etc.). 3900\u21923907 (+7). Verified my release-finalize working tree touches ONLY CHANGELOG.md (git status: 0 code changes), so all +7 is inherited contributor drift. No coverage/openapi/i18n regressions.", - "_rebaseline_2026_06_22_v3833_release": "Cumulative cycle drift surfaced by the release PR full CI. 3867\u21923900 (+33).", - "_rebaseline_2026_06_26_v3837_release": "3970->3987. v3.8.37 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings/complexity accrued unmeasured across this cycle's 76 commits \u2014 provider adds DGrid/Pioneer/xAI, headroom proxy lifecycle #4649, ~50 SSE/translator fixes, Engine Combos #5062). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, and these baselines \u2014 0 production-code change, so all drift is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", + "_rebaseline_2026_06_30_v3842_release": "4116->4121 (+5). v3.8.42 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's 90 commits — chatgpt-web PoW sha3-512 BoringSSL fix #5540, provider baseUrl/i18n umbrella #5511, proxy union proxyUrlMap+acct.proxy #5521, dead-code + duplication waves #5468-#5495, tls-options packaging #5503, release-freeze + .npmrc fetch-retries #5506, dast-smoke spawn-prefix client-safe extraction #5546, plus ~30 SSE/translator/combo/dashboard fixes). Trust-but-verify: measured 4121 via `npm run check:release-green` on the working tree INCLUDING my reconciliation (CHANGELOG/i18n/golden snapshot + file-size baseline) — those touch only config JSON + a provider snapshot (eslint-ignored) and contribute 0 warnings; all +5 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", + "_rebaseline_2026_06_29_v3841_release": "4103->4116 (+13). v3.8.41 cycle drift surfaced by the release-green collect (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's 52 commits — relay backend #5315, gemini catalog #5337, services dashboard #5299, empty-Claude-messages guard #5342, thinking-budget/redacted-replay + marker opt-out #5312/#5352/#5367, opencode proxy-pool + observability #5217/#5370/#5351, cors + HTTPS-serve #5242/#5360/#5361, grok cf_clearance #5350/#5358, oauth/chatgpt-web/routing/cli/dashboard/rerank #5326/#5240/#5239/#5238/#5264/#5332, partially offset by the dead-code sweep #5321-#5371). Trust-but-verify: measured 4116 via `npm run quality:collect` on the working tree INCLUDING my reconciliation (CHANGELOG/i18n/README/env docs + baselines) AND the lint-fix in useServiceLogs.ts — that fix REMOVES a setState-in-effect ERROR (eslintErrors stays 0) and adds an `open` listener with no `any`/unused, contributing 0 warnings; all +13 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", + "_rebaseline_2026_06_29_v3840_release": "4090->4103 (+13). v3.8.40 cycle drift surfaced by the release-green pre-flight + the release PR Quality Ratchet (the ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's ~57 commits — compression roadmap relevance/hard-budget/memoization/transparency/saliency/splitter/tool_search/RTK/QuantumLock #5289/#5288/#5286/#5284/#5285/#5283/#5269/#5268/#5260, ~20 SSE/translator/combo fixes #5248/#5250/#5254/#5261/#5255/#5273/#5258, M365 Copilot provider #5302, public-origin centralization #5278). Trust-but-verify: measured 4103 locally via `npm run quality:collect` on the release tip INCLUDING my reconciliation commits (CHANGELOG + main merge + the 2 regression test fixes 165c823f5) — the test fixes add 0 `any`/warnings (health-autopilot added a NextRequest import + asserts; chat-pipeline changed one Accept string + a comment), so all +13 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", + "_rebaseline_2026_06_28_v3839_release": "4002->4090 (+88). v3.8.39 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's 40 commits — antigravity remote-login + quota-family #5203/#5180/#5193, compression CCR-retrieve + TOON encoder #5187/#5163, ~20 SSE/translator/responses fixes #5156/#5154/#5197/#5204/#5158/#5123/#5166, proxy/health hardening #5202/#5208/#5209/#5201 from @KooshaPari, combo quota-share/context-relay E2E tests #5179/#5168/#5195). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, README.md and these baselines — 0 production-code change, so all +88 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", + "_rebaseline_2026_06_27_v3838_release": "3987->4002 (+15). v3.8.38 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings accrued unmeasured across this cycle's ~78 commits — provider adds Factory/Grok-Build/ZenMux-Free/Alibaba-video, ~30 SSE/translator/diagnostics fixes, compression fidelity-gate + playground #5080/#5143, Fusion editor #5074, salvage batches #5138/#5141). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, README.md and these baselines — 0 production-code change, so all +15 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", + "_rebaseline_2026_06_25_v3836_release": "v3.8.36 cycle drift surfaced by the post-merge fix PR #5029 (the Quality Ratchet was SKIPPED on the release PR #4854 itself, and does NOT run on the PR→release fast-gates, so warnings accrued unmeasured across this cycle's 137 commits — Quota-Share Fase 2/3 features, god-file decomposition #3501/#4811-#4956, 14 external contributor PRs). 3912→3970 (+58), the exact value measured by the CI Quality Ratchet on #5029. Trust-but-verify: this fix PR touches ONLY scripts/build/pack-artifact-policy.ts (a string-literal allowlist array, scripts/ is eslint-light) and tests/integration/resilience-http-e2e.test.ts (2 string keys, no `any`) — 0 new warnings, so all +58 is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Same precedent as _rebaseline_2026_06_23_v3835_release. Tighten via --require-tighten next cycle.", + "_rebaseline_2026_06_23_v3835_release": "v3.8.35 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR→release fast-gates, so warnings accrued across this cycle's parallel-session merges — Compression Phase 4 #4694/#4707/#4716/#4720, chatCore #3501 leaf extractions, contributor PRs #4726/#4753/#4774/#4781/#4783/#4793, etc.). 3907→3912 (+5). Verified my release-finalize working tree touches ONLY docs/*.md (THREAT_MODEL), CHANGELOG.md, baselines, and 1 string line in scripts/check/check-fabricated-docs.mjs — 0 production-code change, so all +5 is inherited contributor drift. No coverage/openapi/i18n regressions.", + "_rebaseline_2026_06_22_v3834_release": "v3.8.34 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR→release fast-gates, so warnings accrued across this cycle's parallel-session merges — #4583-4586/#4588-4593/#4606-4621/#4644/#4647/#4696/etc.). 3900→3907 (+7). Verified my release-finalize working tree touches ONLY CHANGELOG.md (git status: 0 code changes), so all +7 is inherited contributor drift. No coverage/openapi/i18n regressions.", + "_rebaseline_2026_06_22_v3833_release": "Cumulative cycle drift surfaced by the release PR full CI. 3867→3900 (+33).", + "_rebaseline_2026_06_26_v3837_release": "3970->3987. v3.8.37 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings/complexity accrued unmeasured across this cycle's 76 commits — provider adds DGrid/Pioneer/xAI, headroom proxy lifecycle #4649, ~50 SSE/translator fixes, Engine Combos #5062). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, and these baselines — 0 production-code change, so all drift is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", "_rebaseline_2026_07_04_pacote4_no_new_warnings": "4279->0. Pacote 4 do plano mestre testes+CI: a divida pre-existente (4279 warnings + violacoes das 3 regras promovidas a error em src/**) foi CONGELADA em config/quality/eslint-suppressions.json (ESLint bulk suppressions nativo) e passa a ser bloqueada NO PR que a introduziria (job lint-guard no quality.yml + npm run lint + lint-staged, todos suppressions-aware; fork = report-only, Principio Zero). collect-metrics agora mede sob o baseline congelado -> a metrica vira 'divida liquida NOVA' (~0 em regime). O aperto do ESTOQUE congelado acontece via `npx eslint . --prune-suppressions --suppressions-location config/quality/eslint-suppressions.json` na reconciliacao da release. Fim das rebaselines-surpresa de +41/+88 por ciclo." }, "eslintErrors": { @@ -106,12 +106,13 @@ "_rebaseline_2026_07_13_v3847_release": "39.3 -> 38.0 (-1.3, beyond the 0.5 eps). v3.8.47 cycle drift: the cycle merged ~45 PRs adding API routes (relay repair/free-pool #6909, backpressure #6590, combo context requirements #6907, services/usage endpoints) faster than openapi.yaml documentation; same class as the v3.8.34/v3.8.39 rebaselines. Documented follow-up: raise coverage next cycle via docs/openapi.yaml additions." }, "i18nUiCoverage.pct": { - "value": 75.5, + "value": 99, "direction": "up", "eps": 0.5, "_rebaseline_2026_07_04_v3844_release": "77.5 -> 76.8 (-0.7, beyond the 0.5 eps). v3.8.44 cycle drift surfaced only on the release PR (i18n-ui-coverage does NOT run on PR->release fast-gates). The cycle added ~1352 new UI keys to the en.json denominator (Discovery dashboard tab #5939, Bifrost/Mux embedded-service tabs #5817/#6034, proxy batch-ops #5918, fusion defaults #5598, tool-source toggle #5978, quota-row collapse #5977, CodeWhale/Crush CLI cards #5996/#5970, etc.) that the async i18n translation workflow has not yet back-filled (worst locales measure 76.8; __MISSING__ placeholders count as uncovered by design). Same shape and remedy as _rebaseline_2026_06_28_v3839_release. Recover via the i18n workflow next cycle; tighten with --require-tighten once translations land.", - "_rebaseline_2026_06_28_v3839_release": "78.4 -> 77.5 (-0.9, beyond the 0.5 eps). v3.8.39 cycle drift surfaced ONLY on the release PR (i18n-ui-coverage does NOT run on PR->release fast-gates). The cycle added new UI strings (compression studio TOON A/B table, antigravity remote-login dashboard field, amber warning icon) to the en denominator faster than the 37 non-en locales were translated; those locales need `npm run i18n:run` with OMNIROUTE_TRANSLATION_API_KEY (unavailable locally) \u2014 same precedent as _rebaseline_2026_06_18_v3828_cycle_close + _quality_rebaseline_2026_06_20_ci_ratchet. Measured by CI collect-metrics (run 28317145160) = 77.5. My release-finalize tree changes no src/i18n/messages/*.json. Tightening is tracked as follow-up (run i18n:run with creds).", - "_rebaseline_2026_07_13_v3847_release": "76.8 -> 75.5 (-1.3, beyond the 0.5 eps). v3.8.47 cycle drift: merged UI features added EN strings (relay repair UI #6909, combo builder #6907/#6991, capability override UI #6727) ahead of the 42-locale mirrors; same class as the v3.8.39/v3.8.44 rebaselines." + "_rebaseline_2026_06_28_v3839_release": "78.4 -> 77.5 (-0.9, beyond the 0.5 eps). v3.8.39 cycle drift surfaced ONLY on the release PR (i18n-ui-coverage does NOT run on PR->release fast-gates). The cycle added new UI strings (compression studio TOON A/B table, antigravity remote-login dashboard field, amber warning icon) to the en denominator faster than the 37 non-en locales were translated; those locales need `npm run i18n:run` with OMNIROUTE_TRANSLATION_API_KEY (unavailable locally) — same precedent as _rebaseline_2026_06_18_v3828_cycle_close + _quality_rebaseline_2026_06_20_ci_ratchet. Measured by CI collect-metrics (run 28317145160) = 77.5. My release-finalize tree changes no src/i18n/messages/*.json. Tightening is tracked as follow-up (run i18n:run with creds).", + "_rebaseline_2026_07_13_v3847_release": "76.8 -> 75.5 (-1.3, beyond the 0.5 eps). v3.8.47 cycle drift: merged UI features added EN strings (relay repair UI #6909, combo builder #6907/#6991, capability override UI #6727) ahead of the 42-locale mirrors; same class as the v3.8.39/v3.8.44 rebaselines.", + "_rebaseline_2026_07_28_v3849_release": "75.5 -> 99 (+23.5). Aperto EXIGIDO pelo modo --require-tighten do ratchet: a métrica melhorou de verdade no ciclo v3.8.49. A causa é o workflow assíncrono de tradução, que finalmente alcançou o denominador em EN — as rebaselines anteriores (v3.8.39/.44/.47) foram todas afrouxamentos registrando o atraso das traduções, e agora ele foi pago. O coletor SUBTRAI os placeholders (present - placeholder em scripts/quality/collect-metrics.mjs), então os 317 marcadores __MISSING__ que esta release introduziu para o drift de valor já estão descontados dos 99 — o número é honesto, não inflado por placeholder. Medido pelo collect-metrics do CI no run 30404226939." }, "deadExports": { "value": 227, @@ -119,36 +120,36 @@ "_rebaseline_2026_07_01_v3843_release": "225->227 (+2). v3.8.43 cycle drift, surfaced in the Quality Ratchet job after eslintWarnings was rebaselined (check:dead-code runs there). 227 = measured by check:dead-code (knip) on the release tip 4635076eb. The 5 CI fixes add 0 dead exports: safeHttpHref in linkify.ts is module-local AND used (called by linkifyText); no new exports; test files are not scanned. Tighten via --update next cycle.", "dedicatedGate": true, "_rebaseline_2026_06_30_v3842_deadcode_wave": "310 -> 225. Measured by `node scripts/check/check-dead-code.mjs` on the v3.8.42 tip after the JxnLexn dead-code (#5463/#5464/#5466) + duplication (#5471..#5500) wave landed: DEAD_EXPORTS=133 + DEAD_FILES=92 = 225. The stale 310 was the v3.8.38 release snapshot never ratcheted on PR->release fast-gates (check:dead-code runs only on ci.yml PR->main, not quality.yml). Tightening to the true measured value; release-time captain rebaselines up if parallel cycle merges add dead exports.", - "_rebaseline_2026_06_27_v3838_release": "345->346 (+1). v3.8.38 cycle drift surfaced by the release-green pre-flight (Quality Ratchet does NOT run on PR->release fast-gates). Net +1 inherited from this cycle's feature/fix merges (new executors/providers, compression fidelity-gate module) minus #5138's removal of dead legacy store modules. Release-finalize working tree touches ONLY CHANGELOG.md + i18n mirrors + README + baselines \u2014 0 production-code change. Structural cleanup tracked as debt.", - "_rebaseline_2026_06_26_v3837_release": "343->345. v3.8.37 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings/complexity accrued unmeasured across this cycle's 76 commits \u2014 provider adds DGrid/Pioneer/xAI, headroom proxy lifecycle #4649, ~50 SSE/translator fixes, Engine Combos #5062). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, and these baselines \u2014 0 production-code change, so all drift is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle." + "_rebaseline_2026_06_27_v3838_release": "345->346 (+1). v3.8.38 cycle drift surfaced by the release-green pre-flight (Quality Ratchet does NOT run on PR->release fast-gates). Net +1 inherited from this cycle's feature/fix merges (new executors/providers, compression fidelity-gate module) minus #5138's removal of dead legacy store modules. Release-finalize working tree touches ONLY CHANGELOG.md + i18n mirrors + README + baselines — 0 production-code change. Structural cleanup tracked as debt.", + "_rebaseline_2026_06_26_v3837_release": "343->345. v3.8.37 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings/complexity accrued unmeasured across this cycle's 76 commits — provider adds DGrid/Pioneer/xAI, headroom proxy lifecycle #4649, ~50 SSE/translator fixes, Engine Combos #5062). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, and these baselines — 0 production-code change, so all drift is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle." }, "cognitiveComplexity": { "value": 1223, "_rebaseline_2026_07_25_8470_hyperagent_sticky_thread": "951->957 (+6). PR #8470 (artickc, fix/hyperagent-tool-loop-thread-sticky) pre-green validation. Trust-but-verify: origin/release/v3.8.49 tip alone (pristine, no PR changes) already measures 956 with node scripts/check/check-cognitive-complexity.mjs — i.e. +5 is inherited cycle drift unrelated to this PR (cognitive-complexity does not run on PR->release fast-gates). This PR's OWN growth adds exactly +1: per-file eslint scoped scan (eslint --config eslint.complexity-ratchets.config.mjs open-sse/executors/hyperagent.ts) on base vs PR shows extractMessageText() crossing the threshold for the first time (new sonarjs/cognitive-complexity violation, 26 > 15) from the new Anthropic tool_use/tool_result flattening branches; resolveHyperAgentThreadBinding's existing pre-#8470 violation (16) grows to 21 (still counted once) from the new root-key lookup tier; createHyperAgentThread and execute() are unchanged pre-existing violations. Net repo-wide total = 956 (inherited drift) + 1 (this PR's own new violation) = 957. Full-repo re-measurement of the merged branch was attempted but not completed live due to heavy concurrent devbox load (many other /green-prs sessions running the identical full-repo eslint scan in parallel); the value here is derived from two independently-clean measurements (base-tip full scan + per-file base-vs-PR delta) rather than a third full-repo run. Covered by tests/unit/executor-hyperagent.test.ts (19/19). Tighten via --update next cycle.", "_rebaseline_2026_07_25b_v3849_mergetrain_owngrowth": "Owner-approved (chat, 2026-07-25): 956->968 (+12). v3.8.49 /merge-prs 41-PR merge-train aggregate own-growth: measured 968 on the combined boarded tree (tip ac15014ca7) vs 956 on the pristine release tip. The batch's new over-threshold functions come from the pre-screen-flagged complexity-growth set (#8378/#8432/#8476/#8526 etc); each PR is under-ceiling alone, the combined batch adds +12. Same merge-burst class as the notes below; owner chose ceiling-absorb over per-PR extraction. Structural shrink tracked in #3501; tighten via --update next cycle.", - "_rebaseline_2026_07_25_v3849_mergequeue_drain": "Owner-approved (chat, 2026-07-25): 951->956 (+5). v3.8.49 /merge-prs queue-drain: inherited cognitive-complexity drift from the cycle's merge burst (base-red slices + owner PRs + parallel-session merges #8500-8508); check:cognitive-complexity does not run on PR->release fast-gates, so it accrued unmeasured. Measured 956 on the pristine release tip 4053e2314a alone (BEFORE any queue PR boards) \u2014 the entire +5 is base drift already on the tip, reddening Fast Quality Gates for every merge-ready PR. Owner approved raising the ceiling to the measured tip value so the ~34-PR merge-train lands without per-PR extraction churn. Structural shrink tracked in #3501; tighten via --update next cycle.", + "_rebaseline_2026_07_25_v3849_mergequeue_drain": "Owner-approved (chat, 2026-07-25): 951->956 (+5). v3.8.49 /merge-prs queue-drain: inherited cognitive-complexity drift from the cycle's merge burst (base-red slices + owner PRs + parallel-session merges #8500-8508); check:cognitive-complexity does not run on PR->release fast-gates, so it accrued unmeasured. Measured 956 on the pristine release tip 4053e2314a alone (BEFORE any queue PR boards) — the entire +5 is base drift already on the tip, reddening Fast Quality Gates for every merge-ready PR. Owner approved raising the ceiling to the measured tip value so the ~34-PR merge-train lands without per-PR extraction churn. Structural shrink tracked in #3501; tighten via --update next cycle.", "_rebaseline_2026_07_10_gcf_v3_2": "885->888 (+3). PR feat/headroom-gcf-v3.2-nested-flattening: own growth from re-vendoring the GCF (Headroom) codec to spec v3.2 (nested flattening). The new over-threshold functions are the vendored v3.2 flatten/unflatten walk in open-sse/services/compression/engines/headroom/gcf/{generic,decode_generic}.ts. Imported third-party code kept byte-faithful to upstream gcf-typescript; measured 888 with the update vs 885 on the pristine origin/release/v3.8.47 tip. Guarded by tests/unit/compression/headroom-smartcrusher.test.ts (deep-nested case). Structural shrink belongs upstream in gcf.", "_rebaseline_2026_07_12_v3847_mergetrain_burst": "885->890 (+5). v3.8.47 /merge-prs merge-train batch (23 merge-ready PRs) inherited drift: cognitive-complexity does NOT run on PR->release fast-gates, so incidental growth accrued unmeasured across the batch. Measured 890 on the combined merge-train tip (5d980352d) vs 885 on the pristine release tip 1b7a9150e. #6838 (headroom gcf codec re-vendor) accounts for +3 (its own baseline bump to 888, superseded here by this later 890 rebaseline which already covers it); the remaining +2 is parallel-batch drift across the other 22 PRs. Owner-approved rebaseline (merge-burst reconciliation, same class as the v3.8.46/v3.8.44 notes below). Tighten via --update next cycle.", - "_rebaseline_2026_07_09_6587_kiro_api_key_auth": "884->885 (+1). PR #6587 (@strangersp) own growth: open-sse/services/usage/kiro.ts gains ONE new over-threshold function \u2014 getKiroUsage grew from a single fetch to a 3-endpoint fallback chain (codewhisperer-get / codewhisperer-post / q-get) with per-attempt auth-header selection (tokentype: API_KEY vs Bearer-only), needed so usage/quota lookups work for the new long-lived-API-key auth path in addition to the existing OAuth path (measured: 0 violations on release tip -> 1 violation, complexity 33, at open-sse/services/usage/kiro.ts). Covered by tests/unit/kiro-iam-profilearn-usage.test.ts (tokentype header selection, friendly auth-expired/rejected-token messages). Cohesive multi-endpoint-fallback logic at an existing usage chokepoint; not extractable without splitting the fallback loop mid-merge. Structural shrink tracked in #3501.", - "_rebaseline_2026_07_07_v3846_release_close": "877->882 (+5). v3.8.46 release close (generate-release Phase 0 pre-flight): drift herdado do merge burst do ciclo. Trust-but-verify: os fixes de base-red do captain (agentSkills path.resolve #6366, catalogo cache #6408, tipagem de teste, MitmProxyTab suppression) sao cognitive-net-zero \u2014 check:cognitive-complexity mede 882 identico com e sem os fixes (a catraca NAO roda no fast-path PR->release). Tighten via --update next cycle.", + "_rebaseline_2026_07_09_6587_kiro_api_key_auth": "884->885 (+1). PR #6587 (@strangersp) own growth: open-sse/services/usage/kiro.ts gains ONE new over-threshold function — getKiroUsage grew from a single fetch to a 3-endpoint fallback chain (codewhisperer-get / codewhisperer-post / q-get) with per-attempt auth-header selection (tokentype: API_KEY vs Bearer-only), needed so usage/quota lookups work for the new long-lived-API-key auth path in addition to the existing OAuth path (measured: 0 violations on release tip -> 1 violation, complexity 33, at open-sse/services/usage/kiro.ts). Covered by tests/unit/kiro-iam-profilearn-usage.test.ts (tokentype header selection, friendly auth-expired/rejected-token messages). Cohesive multi-endpoint-fallback logic at an existing usage chokepoint; not extractable without splitting the fallback loop mid-merge. Structural shrink tracked in #3501.", + "_rebaseline_2026_07_07_v3846_release_close": "877->882 (+5). v3.8.46 release close (generate-release Phase 0 pre-flight): drift herdado do merge burst do ciclo. Trust-but-verify: os fixes de base-red do captain (agentSkills path.resolve #6366, catalogo cache #6408, tipagem de teste, MitmProxyTab suppression) sao cognitive-net-zero — check:cognitive-complexity mede 882 identico com e sem os fixes (a catraca NAO roda no fast-path PR->release). Tighten via --update next cycle.", "_rebaseline_2026_07_03_v3844_ipfilter_release_green": "861->867 (+6). v3.8.44 cycle drift measured on release tip 32e4c906e during the #6131/#5975 release-green rebaseline. Inherited from the merge burst (Quality Ratchet does not run on PR->release fast-gates). route-edge-coverage +7 is my #5975 test comment; the rest is parallel-session drift. Tighten via --update next cycle.", "_rebaseline_2026_07_03_v3844_review_prs_fix_batch": "860->861 (+1). Inherited v3.8.44 cycle drift surfaced by the release-green pre-flight during the /review-prs fix-batch round; check:cognitive-complexity measures 861 on the release tip 72ee80649. Negligible +1 from the round's / parallel-session merge burst (cognitive-complexity does NOT run on PR->release fast-gates). Structural shrink tracked in #3501. Tighten via --update next cycle.", "_rebaseline_2026_07_02_v3844_post_5939": "859->860 (+1). Same inherited post-3a3d618fe release drift as the complexity note of this date; this PR touches one CLI line (nullish default, no new function over the threshold) and one test file (not scanned). Tighten via --update next cycle.", - "_rebaseline_2026_07_02_v3844_merge_burst": "856->859 (+3). Inherited v3.8.44 cycle drift surfaced by PR #5939: check:cognitive-complexity measures 859 on BOTH the pristine release tip (3a3d618fe) and this PR's merged HEAD \u2014 identical, so the PR is cognitive-net-zero (its DiscoveryPageClient was refactored into hooks/sub-components during its own CI cycle). Drift from the 2026-07-02 merge burst into release/v3.8.44. Tighten via --update next cycle.", - "_rebaseline_2026_07_02_5798_release_green": "845->856 (+11). Inherited v3.8.43 cycle drift surfaced by the release-green unblock #5798 / PR #5896: check:cognitive-complexity measures 856 on BOTH the pristine release tip (0d3875a98) and this PR's HEAD \u2014 identical, so the PR is cognitive-net-zero (it touches only gate scripts, docs, baselines and test files). Drift from the 2026-07-01/02 merge burst. Tighten via --update next cycle.", + "_rebaseline_2026_07_02_v3844_merge_burst": "856->859 (+3). Inherited v3.8.44 cycle drift surfaced by PR #5939: check:cognitive-complexity measures 859 on BOTH the pristine release tip (3a3d618fe) and this PR's merged HEAD — identical, so the PR is cognitive-net-zero (its DiscoveryPageClient was refactored into hooks/sub-components during its own CI cycle). Drift from the 2026-07-02 merge burst into release/v3.8.44. Tighten via --update next cycle.", + "_rebaseline_2026_07_02_5798_release_green": "845->856 (+11). Inherited v3.8.43 cycle drift surfaced by the release-green unblock #5798 / PR #5896: check:cognitive-complexity measures 856 on BOTH the pristine release tip (0d3875a98) and this PR's HEAD — identical, so the PR is cognitive-net-zero (it touches only gate scripts, docs, baselines and test files). Drift from the 2026-07-01/02 merge burst. Tighten via --update next cycle.", "direction": "down", - "_rebaseline_2026_07_01_v3843_release": "842->845 (+3). v3.8.43 cycle drift, surfaced after check:mutation-test-coverage was fixed (masked behind it in the Fast Quality Gates chain). 845 = measured by check:cognitive-complexity on BOTH fce85136c and 6d7060e21 (identical) \u2014 all +3 is inherited cycle drift; the 5 CI fixes add 0 (safeHttpHref cognitive ~2, under the 15 threshold). Tighten via --update next cycle.", + "_rebaseline_2026_07_01_v3843_release": "842->845 (+3). v3.8.43 cycle drift, surfaced after check:mutation-test-coverage was fixed (masked behind it in the Fast Quality Gates chain). 845 = measured by check:cognitive-complexity on BOTH fce85136c and 6d7060e21 (identical) — all +3 is inherited cycle drift; the 5 CI fixes add 0 (safeHttpHref cognitive ~2, under the 15 threshold). Tighten via --update next cycle.", "dedicatedGate": true, - "_rebaseline_2026_06_29_v3841_release": "841->842 (+1). v3.8.41 cycle drift surfaced by the release-PR Quality Ratchet (cognitive-complexity does NOT run on PR->release fast-gates). The Phase-0 pre-flight measured 840 on the pre-campaign tip; the campaign's +34 later commits (thinking-budget/marker #5312/#5352/#5367, opencode proxy-pool/observability #5217/#5370/#5351, cors/HTTPS #5242/#5360/#5361, grok #5350/#5358, oauth/routing/cli #5326/#5239/#5238) added +2 net. My release-finalize changes are docs/baselines + a lint-fix (useServiceLogs open-listener), a test alignment (encryption.spec) and a pack-allowlist entry \u2014 all complexity-neutral. Structural shrink tracked in #3501.", - "_rebaseline_2026_06_27_v3838_release": "833->841 (+8). v3.8.38 cycle drift surfaced by the release-green pre-flight (cognitive-complexity does NOT run on PR->release fast-gates). Inherited drift from this cycle's ~78 feature/fix merges (compression fidelity-gate #5143, SSE/streaming hardening #5124/#5108/#5085, resilience #5093, quota keepalive #5102, contributor provider/translator branches). god-file decomposition #3501 is complexity-neutral. Release-finalize working tree touches ONLY CHANGELOG.md + i18n mirrors + README + baselines \u2014 0 production-code change. Structural shrink tracked in #3501.", - "_rebaseline_2026_06_25_v3836_release": "801\u2192816 (+15) \u2014 v3.8.36 cycle drift surfaced by the fix-PR #5029 CI (cognitive-complexity does NOT run on PR\u2192release fast-gates, and the Quality Ratchet job was SKIPPED on the release PR #4854 itself, so the +15 from this cycle's 137 commits accrued unmeasured). Measured locally = 816 (identical to the CI Cognitive complexity ratchet). Drift from legit cycle features (Quota-Share Fase 2/3, task-aware/Fusion combo, contributor provider/translator branches); god-file decomposition #3501 is complexity-neutral. This fix-PR touches only pack-artifact-policy.ts + a test + the 2 baseline JSONs \u2014 contributes 0. Structural shrink tracked in #3501.", - "_rebaseline_2026_06_22_v3834_release": "797\u2192801 (+4) \u2014 v3.8.34 cycle drift surfaced by the release-green pre-flight (cognitive-complexity does NOT run on PR\u2192release fast-gates). Verified my release-finalize working tree touches ONLY CHANGELOG.md (git status: 0 code changes), so all +4 is inherited contributor drift from this cycle's parallel-session merges. Structural shrink tracked in #3501.", - "_rebaseline_2026_06_22_v3833_release": "793\u2192797 (+4) \u2014 pre-existing cycle drift on origin/release/v3.8.33.", - "_rebaseline_2026_06_26_v3837_release": "816->826. v3.8.37 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings/complexity accrued unmeasured across this cycle's 76 commits \u2014 provider adds DGrid/Pioneer/xAI, headroom proxy lifecycle #4649, ~50 SSE/translator fixes, Engine Combos #5062). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, and these baselines \u2014 0 production-code change, so all drift is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", + "_rebaseline_2026_06_29_v3841_release": "841->842 (+1). v3.8.41 cycle drift surfaced by the release-PR Quality Ratchet (cognitive-complexity does NOT run on PR->release fast-gates). The Phase-0 pre-flight measured 840 on the pre-campaign tip; the campaign's +34 later commits (thinking-budget/marker #5312/#5352/#5367, opencode proxy-pool/observability #5217/#5370/#5351, cors/HTTPS #5242/#5360/#5361, grok #5350/#5358, oauth/routing/cli #5326/#5239/#5238) added +2 net. My release-finalize changes are docs/baselines + a lint-fix (useServiceLogs open-listener), a test alignment (encryption.spec) and a pack-allowlist entry — all complexity-neutral. Structural shrink tracked in #3501.", + "_rebaseline_2026_06_27_v3838_release": "833->841 (+8). v3.8.38 cycle drift surfaced by the release-green pre-flight (cognitive-complexity does NOT run on PR->release fast-gates). Inherited drift from this cycle's ~78 feature/fix merges (compression fidelity-gate #5143, SSE/streaming hardening #5124/#5108/#5085, resilience #5093, quota keepalive #5102, contributor provider/translator branches). god-file decomposition #3501 is complexity-neutral. Release-finalize working tree touches ONLY CHANGELOG.md + i18n mirrors + README + baselines — 0 production-code change. Structural shrink tracked in #3501.", + "_rebaseline_2026_06_25_v3836_release": "801→816 (+15) — v3.8.36 cycle drift surfaced by the fix-PR #5029 CI (cognitive-complexity does NOT run on PR→release fast-gates, and the Quality Ratchet job was SKIPPED on the release PR #4854 itself, so the +15 from this cycle's 137 commits accrued unmeasured). Measured locally = 816 (identical to the CI Cognitive complexity ratchet). Drift from legit cycle features (Quota-Share Fase 2/3, task-aware/Fusion combo, contributor provider/translator branches); god-file decomposition #3501 is complexity-neutral. This fix-PR touches only pack-artifact-policy.ts + a test + the 2 baseline JSONs — contributes 0. Structural shrink tracked in #3501.", + "_rebaseline_2026_06_22_v3834_release": "797→801 (+4) — v3.8.34 cycle drift surfaced by the release-green pre-flight (cognitive-complexity does NOT run on PR→release fast-gates). Verified my release-finalize working tree touches ONLY CHANGELOG.md (git status: 0 code changes), so all +4 is inherited contributor drift from this cycle's parallel-session merges. Structural shrink tracked in #3501.", + "_rebaseline_2026_06_22_v3833_release": "793→797 (+4) — pre-existing cycle drift on origin/release/v3.8.33.", + "_rebaseline_2026_06_26_v3837_release": "816->826. v3.8.37 cycle drift surfaced by the release-green pre-flight (the Quality Ratchet does NOT run on PR->release fast-gates, so warnings/complexity accrued unmeasured across this cycle's 76 commits — provider adds DGrid/Pioneer/xAI, headroom proxy lifecycle #4649, ~50 SSE/translator fixes, Engine Combos #5062). Trust-but-verify: this release-finalize working tree touches ONLY CHANGELOG.md, docs/i18n/*/CHANGELOG.md mirrors, and these baselines — 0 production-code change, so all drift is inherited cycle drift (`any` warn-allowed in open-sse/ + tests/). Tighten via --require-tighten next cycle.", "_rebaseline_2026_06_26_v3838_release": "826->833. v3.8.38 release base measures 833 locally on origin/release/v3.8.38 (800b04ad6) while the committed baseline still says 826. This PR measures the same 833 after refactoring jsonToSse helpers back under the sonarjs/cognitive-complexity threshold, so it does not add a net cognitive-complexity violation. The baseline bump records inherited release-base drift only; structural shrink remains tracked by the existing chatCore decomposition work.", "_rebaseline_2026_07_06_v3845_release_close": "867->877 (+10). v3.8.45 cycle drift measured by check:release-green (hermetic) on release tip 5ecca12aa5 during the /generate-release Phase 0 pre-flight. Inherited from the cycle's merge burst (cognitive-complexity does not run on PR->release fast-gates); the captain's pre-flight fixes are gate/test/workflow changes (complexity-neutral). Tighten via --update next cycle.", "_rebaseline_2026_07_07_6519_chirag_fallback_reasons": "882->883 (+1). PR #6519 (@chirag127, #6461): the preview route's fallbackReasons dedup loop adds one function over the cognitive threshold. Owner-approved rebaseline (contributor own-growth). Tighten via --update next cycle.", - "_rebaseline_2026_07_08_6556_inherited_drift": "883->884 (+1). PR #6556 (omniglyph engine): drift herdado do merge burst da base (cognitive-complexity nao roda no fast-path PR->release). Trust-but-verify: check:cognitive-complexity mede 884 IDENTICO na base pura origin/release/v3.8.47 e neste HEAD \u2014 o PR e cognitive-net-zero (runCompressionAsync extraido para engines/omniglyphSingleMode.ts e o page client dividido em section components na mesma rodada). Tighten via --update next cycle.", + "_rebaseline_2026_07_08_6556_inherited_drift": "883->884 (+1). PR #6556 (omniglyph engine): drift herdado do merge burst da base (cognitive-complexity nao roda no fast-path PR->release). Trust-but-verify: check:cognitive-complexity mede 884 IDENTICO na base pura origin/release/v3.8.47 e neste HEAD — o PR e cognitive-net-zero (runCompressionAsync extraido para engines/omniglyphSingleMode.ts e o page client dividido em section components na mesma rodada). Tighten via --update next cycle.", "_rebaseline_2026_07_19_v3849_fix_sweep_cluster": "890->900 (owner-approved, 2026-07-19). Same /fix-prs cluster as the complexity note: the clean-by-cyclomatic subset still bumped cognitive-complexity (measured 896 on the 9-PR combined probe tip vs 890 baseline). Raised to 900 = 896 + 4 headroom, matching the complexity rebaseline. Tighten via --update next cycle.", "_note_8266": "2026-07-23: +1 own-growth from #8266 (@backryun) Alibaba media provider dispatch wiring" }, @@ -164,21 +165,23 @@ "dedicatedGate": true }, "secretFindings": { - "_note": "Zeroed 2026-07-13 (WS6/D3): the 3 frozen generic-api-key FPs are allowlisted with justification in .gitleaks.toml \u2014 any NEW finding regresses the ratchet.", + "_note": "Zeroed 2026-07-13 (WS6/D3): the 3 frozen generic-api-key FPs are allowlisted with justification in .gitleaks.toml — any NEW finding regresses the ratchet.", "value": 0, "direction": "down", "dedicatedGate": true }, "zizmorFindings": { - "value": 176, - "_rebaseline_2026_07_20_aliasresolver_hook_split_7808": "175 -> 176 (+1). Companion to PR #7808 (CodeQL js/incomplete-url-substring-sanitization fix in bin/aliasResolver.mjs). The +1 is NOT caused by this PR's code changes (bin/* is not a workflow file) \u2014 it is a pre-existing drift that surfaced because the ratchet gate runs on this PR's CI: the zizmor scanner version on the GitHub runner gained a new rule (or extended an existing one) since the v3.8.49 baseline was seeded on 2026-07-17. Breakdown: the new finding is an unpinned-uses @vN class item on one of the existing workflows (same deliberate convention as _scanner_harden_workflows_2026_06_16 \u2014 @vN is intentional, SHA-pinning only this one would violate the convention). No new template-injection/artipacked/cache-poisoning/dangerous-triggers classes introduced. Measured by the Quality Gates (Extended) job on run 29713001401 = 176, baseline was 175. Note: by the time this landed on release/v3.8.49, the baseline was already at 176 via _rebaseline_2026_07_17_combo_recovery_hints \u2014 this entry is kept as historical record; no further bump applied.", + "value": 190, + "_rebaseline_2026_07_20_aliasresolver_hook_split_7808": "175 -> 176 (+1). Companion to PR #7808 (CodeQL js/incomplete-url-substring-sanitization fix in bin/aliasResolver.mjs). The +1 is NOT caused by this PR's code changes (bin/* is not a workflow file) — it is a pre-existing drift that surfaced because the ratchet gate runs on this PR's CI: the zizmor scanner version on the GitHub runner gained a new rule (or extended an existing one) since the v3.8.49 baseline was seeded on 2026-07-17. Breakdown: the new finding is an unpinned-uses @vN class item on one of the existing workflows (same deliberate convention as _scanner_harden_workflows_2026_06_16 — @vN is intentional, SHA-pinning only this one would violate the convention). No new template-injection/artipacked/cache-poisoning/dangerous-triggers classes introduced. Measured by the Quality Gates (Extended) job on run 29713001401 = 176, baseline was 175. Note: by the time this landed on release/v3.8.49, the baseline was already at 176 via _rebaseline_2026_07_17_combo_recovery_hints — this entry is kept as historical record; no further bump applied.", "_rebaseline_2026_07_17_v3849_release": "169 -> 175 (+6). Cycle workflow drift (v3.8.48/v3.8.49): npm-publish.yml (new, WS1.3 #7092), electron-release.yml, nightly-compat.yml, nightly-release-green.yml, CI restructures (#7501 full-history base fetch, #7355 main-green, #7202 merge-queue gates, Trunk/Codecov). Breakdown vs v3.8.47: +3 unpinned-uses (@vN convention, deliberate per _scanner_harden_workflows_2026_06_16), +2 cache-poisoning (artifact upload/cache in the OWN electron-release/npm-publish RELEASE workflows -- operator-controlled, not fork-PR exploitable), +1 excessive-permissions (nightly-compat.yml permissions:issues). No new template-injection/artipacked/dangerous-triggers. Measured with zizmor 1.25.2 via `node scripts/check/check-workflows.mjs --ratchet` = 175 on da3a0be69.", "direction": "down", "dedicatedGate": true, "_rebaseline_2026_07_17_combo_recovery_hints": "175 -> 176 (+1). Pre-existing workflow drift on source branch (PR #7625 touches zero workflow files). Measured 176 via CI check-workflows same as unmodified upstream/main tip. No new findings from this PR's changes. Same class as _rebaseline_2026_07_17_v3849_release. Tighten via --update next cycle.", - "_rebaseline_2026_06_23_fastpath_gates": "155 -> 159 (+4). Two new jobs added to .github/workflows/quality.yml (fast-vitest, fast-unit) to run vitest + the full unit suite on the PR->release fast-path (release-acceleration plan, _tasks/release-bench/v3.8.35/PLANO-IMPLEMENTACAO.md). The +4 are unpinned-uses: actions/checkout@v7 + actions/setup-node@v6 in each of the 2 jobs \u2014 the SAME deliberate @vN convention as every other workflow (see _scanner_harden_workflows_2026_06_16). SHA-pinning only these would violate the convention. No new template-injection/artipacked/cache-poisoning. Measured locally via `npm run check:workflows -- --ratchet` = 159.", - "_rebaseline_2026_06_23_v3834_release": "152 -> 155 (+3). The 3 new unpinned-uses are in .github/workflows/nightly-release-green.yml (added by #4622 this cycle): actions/checkout@v7, actions/setup-node@v6, actions/upload-artifact@v4 \u2014 the SAME deliberate @vN convention as ci.yml's own checkout@v7/setup-node@v6 and every other workflow (see _scanner_harden_workflows_2026_06_16 + _zizmor_rebaseline_2026_06_20_ci_build_artifact_reuse). SHA-pinning only this workflow would violate the convention. The workflow-lint ratchet does NOT run on PR->release fast-gates, so it surfaced only on the release PR; measured locally via `npm run check:workflows -- --ratchet` = 155. No new template-injection/artipacked/cache-poisoning.", - "_rebaseline_2026_07_13_v3847_release_preflight": "159 -> 169 (+10). Findings from cycle-merged workflow changes: #6716 (PR gate restructure), #6781 (unit fast-path shard 2->4), #6788 (TIA tsx loader split), #6881 (electron-updater latest.yml manifests in release assets) \u2014 same deliberate @vN unpinned-uses convention as prior rebaselines; no new template-injection/artipacked/cache-poisoning classes. Measured via `npm run check:workflows -- --ratchet` = 169 on the v3.8.47 release pre-flight." + "_rebaseline_2026_06_23_fastpath_gates": "155 -> 159 (+4). Two new jobs added to .github/workflows/quality.yml (fast-vitest, fast-unit) to run vitest + the full unit suite on the PR->release fast-path (release-acceleration plan, _tasks/release-bench/v3.8.35/PLANO-IMPLEMENTACAO.md). The +4 are unpinned-uses: actions/checkout@v7 + actions/setup-node@v6 in each of the 2 jobs — the SAME deliberate @vN convention as every other workflow (see _scanner_harden_workflows_2026_06_16). SHA-pinning only these would violate the convention. No new template-injection/artipacked/cache-poisoning. Measured locally via `npm run check:workflows -- --ratchet` = 159.", + "_rebaseline_2026_06_23_v3834_release": "152 -> 155 (+3). The 3 new unpinned-uses are in .github/workflows/nightly-release-green.yml (added by #4622 this cycle): actions/checkout@v7, actions/setup-node@v6, actions/upload-artifact@v4 — the SAME deliberate @vN convention as ci.yml's own checkout@v7/setup-node@v6 and every other workflow (see _scanner_harden_workflows_2026_06_16 + _zizmor_rebaseline_2026_06_20_ci_build_artifact_reuse). SHA-pinning only this workflow would violate the convention. The workflow-lint ratchet does NOT run on PR->release fast-gates, so it surfaced only on the release PR; measured locally via `npm run check:workflows -- --ratchet` = 155. No new template-injection/artipacked/cache-poisoning.", + "_rebaseline_2026_07_13_v3847_release_preflight": "159 -> 169 (+10). Findings from cycle-merged workflow changes: #6716 (PR gate restructure), #6781 (unit fast-path shard 2->4), #6788 (TIA tsx loader split), #6881 (electron-updater latest.yml manifests in release assets) — same deliberate @vN unpinned-uses convention as prior rebaselines; no new template-injection/artipacked/cache-poisoning classes. Measured via `npm run check:workflows -- --ratchet` = 169 on the v3.8.47 release pre-flight.", + "_rebaseline_2026_07_28_v3849_release_preflight": "176 -> 189 (+13). Pre-flight de fechamento da v3.8.49 (934 commits no ciclo). Deriva de workflow: 1 workflow novo (build-rinseaid-image.yml) mais os bumps de action do Dependabot ao longo do ciclo — todos da MESMA classe unpinned-uses @vN, convenção deliberada do repo (ver _scanner_harden_workflows_2026_06_16); fixar por SHA só estes violaria a convenção. Nenhuma classe nova de template-injection / artipacked / cache-poisoning / dangerous-triggers. Nesta mesma passada foram CORRIGIDAS 3 diretivas shellcheck malformadas (SC1125: `# shellcheck disable=SC2086 — texto`, em que o travessão invalida o par key=value) em ci.yml e nightly-release-green.yml. Medido com zizmor 1.25.2 via `npm run check:workflows -- --ratchet` = 189.", + "_rebaseline_2026_07_28_ci_runner_delta": "189 -> 190 (+1). Medido 189 no devbox e 190 no runner do GitHub no MESMO commit (run 30396592013, job Quality Gates (Extended)) — mesma classe já registrada em _rebaseline_2026_07_20_aliasresolver_hook_split_7808: a versão do zizmor no runner enxerga uma finding a mais que a local, sempre da classe unpinned-uses @vN. O valor do runner é o que o gate compara, então a baseline segue o runner." }, "vulnCount": { "value": 10, @@ -186,11 +189,12 @@ "dedicatedGate": true }, "bundleSize": { - "value": 6762, + "value": 7666, "direction": "down", "dedicatedGate": true, "_rebaseline_2026_07_07_v3846_release_close": "5601->6534 (+933). v3.8.46 release close: gzip of the 4 bin/*.mjs entrypoints (size-limit + @size-limit/file) grew from this cycle's feature/fix merges pulled transitively into the CLI entrypoints (new providers, combo pipeline strategy #6396, effort/thinking standardization #6241, catalog cache-invalidation #6408). Measured 6534 locally via `check:bundle-size --ratchet` (deterministic gzip, matches CI). Legitimate cycle growth; shrink is separate debt.", - "_rebaseline_2026_07_19_7808_codeql_alias_resolver_hook": "6534->6762 (+228). PR #7808 (CodeQL js/incomplete-url-substring-sanitization fix): the ESM loader hook source moved out of the inline `HOOK_SOURCE` template literal in bin/aliasResolver.mjs into a real file bin/aliasResolverHook.mjs, loaded via pathToFileURL() instead of a dynamically-built `data:text/javascript,...` URL. The new file is now counted by size-limit as a 5th bin/*.mjs entrypoint. Net +228 = the hook's gzip size (previously hidden inside aliasResolver.mjs because the template literal was compressed away). Security-driven; no shrink opportunity." + "_rebaseline_2026_07_19_7808_codeql_alias_resolver_hook": "6534->6762 (+228). PR #7808 (CodeQL js/incomplete-url-substring-sanitization fix): the ESM loader hook source moved out of the inline `HOOK_SOURCE` template literal in bin/aliasResolver.mjs into a real file bin/aliasResolverHook.mjs, loaded via pathToFileURL() instead of a dynamically-built `data:text/javascript,...` URL. The new file is now counted by size-limit as a 5th bin/*.mjs entrypoint. Net +228 = the hook's gzip size (previously hidden inside aliasResolver.mjs because the template literal was compressed away). Security-driven; no shrink opportunity.", + "_rebaseline_2026_07_28_v3849_release_preflight": "6762 -> 7666 (+904). Fechamento do ciclo v3.8.49: gzip dos entrypoints bin/*.mjs (size-limit + @size-limit/file) cresceu com o que os merges do ciclo puxam transitivamente para o CLI (novos provedores — 271->290, seletor de protocolo por conexão #8861, catálogos de busca #8814, resiliência). Crescimento legítimo de ciclo, medido localmente com `npm run check:bundle-size` = 7666 (gzip determinístico, bate com o CI). Encolher é dívida separada." }, "openapiBreaking": { "value": 0, @@ -360,35 +364,35 @@ "_eslint_rebaseline_2026_06_13_phase7": "3653 -> 3658: +5 warnings dos scripts .mjs de tooling novos da Fase 7 (check-vuln-ratchet/codeql/secrets/workflows/dead-code/etc). Tooling de qualidade; apertar via --require-tighten no fim do ciclo.", "_eslint_rebaseline_2026_06_13_v3825": "3658 -> 3669: +11 drift consciente do ciclo v3.8.24->v3.8.25 (features #3799-#3806: free-provider-rankings, plugins menu, proxy IP-family). Medido em release/v3.8.25 (e38d22512). Crescimento de feature legitima, nao regressao; apertar via --require-tighten no fim do ciclo.", "_eslint_rebaseline_2026_06_15_release_v3826": "3669 -> 3760. Medido em origin/release/v3.8.26 e neste PR com npm run quality:collect: ambos retornam 3760 warnings, portanto este PR e neutro; o drift ja existe na base release/v3.8.26.", - "_eslint_rebaseline_2026_06_16_v3826_forward_merge": "3760 -> 3769. O quality-gate da main FALHOU no forward-merge release->main (run 27593205254): eslintWarnings 3769 > baseline 3760. Medido AGORA em origin/release/v3.8.26 (273ecf7b5, com todos os merges do ciclo) via npm run quality:collect = 3769 \u2014 identico ao CI, e os PRs de gate posteriores (#3947/#3949/#3951/#3956/#3961) nao mudaram a contagem (scripts/check/*.mjs sao eslint-ignored; os arquivos de teste novos nao adicionaram any/warnings). O +9 e drift release-wide pre-existente do ciclo v3.8.26 (merges de feature/outras sessoes), nao regressao de produto. Re-baseline consciente p/ o valor real medido; apertar via --require-tighten no fim do ciclo.", - "_eslint_rebaseline_2026_06_21_v3833_cycle_open_stranded": "3863 -> 3867 (+4). Abertura do ciclo v3.8.33: o +4 vem dos 4 commits stranded na release/v3.8.32 (p\u00f3s-merge da v3.8.32) trazidos via cherry-pick (#4474/#4464/#4485/#4483). main mede 3863; o .33 branch (main + cherry-picks) mede 3867 via npm run lint. Warnings de estilo/any-as-warn de c\u00f3digo de produto rec\u00e9m-mergeado, n\u00e3o regress\u00e3o. Apertar via --require-tighten fica para o ciclo.", - "_eslint_rebaseline_2026_06_20_v3832_cycle_close": "3839 -> 3863. Fechamento do ciclo v3.8.32. Medido com npm run quality:collect no tip de release/v3.8.32 (b4dbf7b23, 38 commits do ciclo, incluindo os late #4476 opencode + #4468 RTK que adicionaram 0 warnings) = 3863. O +24 e drift release-wide acumulado dos PRs de feature/fix mergeados no ciclo (ports upstream #4426/#4429/#4431/#4453/#4458, painel de compressao #4432, validators web-cookie #4023, etc.) \u2014 warnings de estilo/any-as-warn em codigo de produto, nao regressao. O commit de release em si toca SO CHANGELOG.md + README.md (markdown, nao lintado) => delta 0 verificado via git status. openapiCoverage.pct=37.9 PASSA dentro do eps=0.5 (38.4-0.5=37.9); i18nUiCoverage.pct=78.4 == baseline. Apertar via --require-tighten fica para follow-up.", + "_eslint_rebaseline_2026_06_16_v3826_forward_merge": "3760 -> 3769. O quality-gate da main FALHOU no forward-merge release->main (run 27593205254): eslintWarnings 3769 > baseline 3760. Medido AGORA em origin/release/v3.8.26 (273ecf7b5, com todos os merges do ciclo) via npm run quality:collect = 3769 — identico ao CI, e os PRs de gate posteriores (#3947/#3949/#3951/#3956/#3961) nao mudaram a contagem (scripts/check/*.mjs sao eslint-ignored; os arquivos de teste novos nao adicionaram any/warnings). O +9 e drift release-wide pre-existente do ciclo v3.8.26 (merges de feature/outras sessoes), nao regressao de produto. Re-baseline consciente p/ o valor real medido; apertar via --require-tighten no fim do ciclo.", + "_eslint_rebaseline_2026_06_21_v3833_cycle_open_stranded": "3863 -> 3867 (+4). Abertura do ciclo v3.8.33: o +4 vem dos 4 commits stranded na release/v3.8.32 (pós-merge da v3.8.32) trazidos via cherry-pick (#4474/#4464/#4485/#4483). main mede 3863; o .33 branch (main + cherry-picks) mede 3867 via npm run lint. Warnings de estilo/any-as-warn de código de produto recém-mergeado, não regressão. Apertar via --require-tighten fica para o ciclo.", + "_eslint_rebaseline_2026_06_20_v3832_cycle_close": "3839 -> 3863. Fechamento do ciclo v3.8.32. Medido com npm run quality:collect no tip de release/v3.8.32 (b4dbf7b23, 38 commits do ciclo, incluindo os late #4476 opencode + #4468 RTK que adicionaram 0 warnings) = 3863. O +24 e drift release-wide acumulado dos PRs de feature/fix mergeados no ciclo (ports upstream #4426/#4429/#4431/#4453/#4458, painel de compressao #4432, validators web-cookie #4023, etc.) — warnings de estilo/any-as-warn em codigo de produto, nao regressao. O commit de release em si toca SO CHANGELOG.md + README.md (markdown, nao lintado) => delta 0 verificado via git status. openapiCoverage.pct=37.9 PASSA dentro do eps=0.5 (38.4-0.5=37.9); i18nUiCoverage.pct=78.4 == baseline. Apertar via --require-tighten fica para follow-up.", "_quality_rebaseline_2026_06_15_release_v3826": "deadExports 327 -> 339 e cognitiveComplexity 738 -> 753. Medido em origin/release/v3.8.26 e neste PR com os dedicated gates: ambos retornam os mesmos valores, portanto este PR e neutro; typeCoveragePct permanece acima do baseline.", "_dead_code_rebaseline_2026_06_19_pr4293": "deadExports 339 -> 340. Medido em origin/main com a mesma toolchain/deps deste PR (`node scripts/check/check-dead-code.mjs`) = DEAD_TOTAL 340, e o HEAD deste PR tambem mede 340; portanto o PR e neutro e o baseline anterior estava 1 item atrasado.", - "_dead_code_rebaseline_2026_06_21_v3832_cycle_close": "deadExports 340 -> 343 (DEAD_EXPORTS=245 + DEAD_FILES=98). Fechamento do ciclo v3.8.32: a CI Quality Ratchet (run 27895738528, head 1e2ef819b) mediu 343, e `node scripts/check/check-dead-code.mjs` local no mesmo HEAD tambem mede 343 \u2014 portanto o +3 e drift de dead-code acumulado dos PRs do ciclo (refactor #4392 resolveChatCoreRequestSetup, painel compressao #4432, helpers de pricing/mcp-scopes), NAO do commit de release (que toca so CHANGELOG/README/baseline = 0 codigo). Trust-but-verify: nenhum wiring quebrado \u2014 EngineConfigPage usa export NOMEADO (vivo em 4 paginas ultra/headroom/aggressive/lite); apenas o export `default` redundante + calculateCostFromTokens + MCP_SCOPE_PRESETS/hasRequiredScopes/getMissingScopes ficaram exported-but-unused (API/forward-looking). Re-baseline ao valor real medido; limpeza estrutural rastreada em #3501.", - "_cognitive_rebaseline_2026_06_21_v3833_r3": "cognitiveComplexity 792 -> 793 (+1) durante a 3a rodada /review-prs (merges de contribuidores #4530/#4524/#4531/#4522/#4532 + drift de sessoes paralelas). Medido no tip real da release com eslint.sonarjs.config.mjs = 793; isolamento por-arquivo nao confiavel (o gate acopla ao path do arquivo, medir em /tmp retorna 0 espurio). +1 negligenciavel \u2014 plausivelmente os params extras em handleComboChat (#4530 maxCooldownMs) / render telegram (#4524) ou drift paralelo; cognitive-complexity nao roda no fast-gate PR->release. Rebaseline ao valor medido p/ manter a branch verde; shrink estrutural rastreado em #3501.", - "_cognitive_rebaseline_2026_06_21_v3833_review_prs": "cognitiveComplexity 783 -> 792 (+9). Breakdown measured with eslint.sonarjs.config.mjs: +2 is mine (PR #4398 grew src/lib/usage/apiKeyUsageLimits.ts from 0 -> 2 violations \u2014 the per-key USD quota-percent + reset-hint parse/display branches, inherently branchy display logic at a cohesive chokepoint); the remaining +7 is cumulative cycle drift from parallel-session merges into release/v3.8.33 that did not trip the gate because cognitive-complexity does NOT run on the quality.yml fast-gate for PR->release (only on the full CI at release->main). None of my other touched files added a NEW over-threshold function (isContextOverflow400/isParamValidation400/normalizeUpstreamFailure/getModelMaxTokensCap/vacuumScheduler all measured under 15). Rebaselined to the real measured tip value to keep the branch green for the next session; the +7 drift is owned by the cycle and will be re-reconciled at release->main.", + "_dead_code_rebaseline_2026_06_21_v3832_cycle_close": "deadExports 340 -> 343 (DEAD_EXPORTS=245 + DEAD_FILES=98). Fechamento do ciclo v3.8.32: a CI Quality Ratchet (run 27895738528, head 1e2ef819b) mediu 343, e `node scripts/check/check-dead-code.mjs` local no mesmo HEAD tambem mede 343 — portanto o +3 e drift de dead-code acumulado dos PRs do ciclo (refactor #4392 resolveChatCoreRequestSetup, painel compressao #4432, helpers de pricing/mcp-scopes), NAO do commit de release (que toca so CHANGELOG/README/baseline = 0 codigo). Trust-but-verify: nenhum wiring quebrado — EngineConfigPage usa export NOMEADO (vivo em 4 paginas ultra/headroom/aggressive/lite); apenas o export `default` redundante + calculateCostFromTokens + MCP_SCOPE_PRESETS/hasRequiredScopes/getMissingScopes ficaram exported-but-unused (API/forward-looking). Re-baseline ao valor real medido; limpeza estrutural rastreada em #3501.", + "_cognitive_rebaseline_2026_06_21_v3833_r3": "cognitiveComplexity 792 -> 793 (+1) durante a 3a rodada /review-prs (merges de contribuidores #4530/#4524/#4531/#4522/#4532 + drift de sessoes paralelas). Medido no tip real da release com eslint.sonarjs.config.mjs = 793; isolamento por-arquivo nao confiavel (o gate acopla ao path do arquivo, medir em /tmp retorna 0 espurio). +1 negligenciavel — plausivelmente os params extras em handleComboChat (#4530 maxCooldownMs) / render telegram (#4524) ou drift paralelo; cognitive-complexity nao roda no fast-gate PR->release. Rebaseline ao valor medido p/ manter a branch verde; shrink estrutural rastreado em #3501.", + "_cognitive_rebaseline_2026_06_21_v3833_review_prs": "cognitiveComplexity 783 -> 792 (+9). Breakdown measured with eslint.sonarjs.config.mjs: +2 is mine (PR #4398 grew src/lib/usage/apiKeyUsageLimits.ts from 0 -> 2 violations — the per-key USD quota-percent + reset-hint parse/display branches, inherently branchy display logic at a cohesive chokepoint); the remaining +7 is cumulative cycle drift from parallel-session merges into release/v3.8.33 that did not trip the gate because cognitive-complexity does NOT run on the quality.yml fast-gate for PR->release (only on the full CI at release->main). None of my other touched files added a NEW over-threshold function (isContextOverflow400/isParamValidation400/normalizeUpstreamFailure/getModelMaxTokensCap/vacuumScheduler all measured under 15). Rebaselined to the real measured tip value to keep the branch green for the next session; the +7 drift is owned by the cycle and will be re-reconciled at release->main.", "_cognitive_rebaseline_2026_06_19_pr4293": "cognitiveComplexity 753 -> 783. Medido em origin/main com a mesma toolchain/deps deste PR (`node scripts/check/check-cognitive-complexity.mjs`) = 783; apos refatorar os helpers deste PR, o HEAD tambem mede 783. Portanto o PR fica neutro e o baseline anterior estava desatualizado vs main atual.", "_scanner_baselines_seeded_2026_06_15": "secretFindings (3), zizmorFindings (195), vulnCount (13) e bundleSize (5601) congelados a partir de um run LOCAL em 2026-06-15 com os binarios reais no PATH (gitleaks 8.30.1, osv-scanner 2.3.8, zizmor 1.25.2, @size-limit/file 12.1.0). Medicoes: (a) secretFindings=3 via 'gitleaks dir ' por diretorio de fonte (src/open-sse/bin/electron/scripts) APOS corrigir o .gitleaks.toml para [extend].useDefault=true (sem isso o config customizado zerava o ruleset e nunca detectava nada) e a invocacao para escopo por-dir (gitleaks dir aceita 1 path; multiplos caiam para escanear o CWD inteiro/node_modules->timeout). Os 3 sao falsos-positivos do heuristico generic-api-key (string de header beta Anthropic + nomes de coluna latencyP50Ms/latencyP95Ms), a serem allowlistados ao longo do tempo; (b) zizmorFindings=195 via 'npm run check:workflows' APOS migrar .zizmor.yml do schema antigo 'ignores: []' para 'rules: {}' (zizmor 1.25.2 rejeitava o campo 'ignores'); (c) vulnCount=13 (LOW=4/MOD=7/HIGH=2) via osv-scanner; (d) bundleSize=5601 (gzip dos 4 entrypoints bin/*.mjs) via size-limit+@size-limit/file. Todos os 4 sao dedicatedGate:true => SKIP no ratchet BLOQUEANTE (job quality-gate) e ADVISORY no job quality-extended (continue-on-error). Permanecem advisory ate um run VERDE de CI confirmar que a tooling corrigida (install via 'gh release download' em vez de api.github.com nao-autenticado) produz os valores; o flip para bloqueante (remover continue-on-error) fica para um PR de follow-up. Direction:down em todos.", - "_scanner_remediation_2026_06_15": "Remediacao das findings reais que os scanners semeados acima expuseram (medido localmente em 2026-06-15 com os mesmos binarios). vulnCount 13->10: bump dos 2 HIGH transitivos via package.json overrides \u2014 form-data 4.0.5->^4.0.6 (GHSA-hmw2-7cc7-3qxx, via axios) e vite 8.0.5->^8.0.16 (GHSA-fx2h-pf6j-xcff HIGH + GHSA-v6wh-96g9-6wx3 MODERATE, dev-only via vitest/@vitejs/plugin-react/fumadocs-mdx); osv-scanner confirma 0 HIGH restante; build:cli e a suite vitest MCP (16 files/187 testes) verdes pos-bump. zizmorFindings 195->187: env-harden de 7 findings template-injection (ci.yml job i18n; electron-release.yml jobs validate/build/release \u2014 o step 'Create source archives' sozinho gerava 4 das 7) movendo cada ${{...}} para 'env:' e referenciando \"$VAR\" no script, + allowlist de 1 dangerous-triggers (deploy-vps.yml on:workflow_run \u2014 guardado por conclusion=='success', deploy via SSH sem checkout de codigo nao-confiavel; entry em .zizmor.yml rules.dangerous-triggers.ignore). secretFindings (3) e bundleSize (5601) intocados neste PR. Apertados via edicao manual (direction:down).", - "_scanner_flip_blocking_2026_06_16": "Etapa 2: secretFindings (3), zizmorFindings e bundleSize (5601) PROMOVIDOS de ADVISORY para RATCHET BLOQUEANTE. Os 3 scripts (check-secrets/check-workflows/check-bundle-size) ganharam um modo --ratchet que le metrics..value daqui, compara a contagem MEDIDA e sai 1 SOMENTE numa regressao real (medida > baseline). Sem --ratchet permanecem advisory (exit 0). Qualquer SKIP gracioso (binario ausente, plugin size-limit ausente => fallback-stat/no-build, build nao rodou) sai 0 MESMO com --ratchet \u2014 falta de infra nunca bloqueia, so uma regressao medida bloqueia. zizmorFindings re-baselineada 187 -> 192: o +5 e drift LEGITIMO de novos arquivos de workflow (nightly-schemathesis.yml etc.) adicionados no ciclo v3.8.26, mesma convencao @vN unpinned de todos os workflows; reproduzivel localmente E confirmado no run de CI #27593205254 (job 81578109020) = 192. secretFindings (3) e bundleSize (5601) intocados \u2014 ja batiam o valor do CI. NB: bundleSize=5601 e o valor GZIP do size-limit + @size-limit/file (instalado por 'npm ci' no CI); o fallback-stat le bytes CRUS (16670, metrica diferente) e por isso o modo --ratchet SO bloqueia quando a medicao veio do size-limit real, fazendo SKIP no fallback. actionlintFindings NAO entra no ratchet (so reportada); o --strict all-or-nothing do check-workflows permanece separado.", - "_scanner_harden_workflows_2026_06_16": "Hardening real das findings do zizmor (branch ci/workflow-security-hardening). zizmorFindings re-baselineada 192 -> 139 (medido localmente com zizmor 1.25.2 + .zizmor.yml). Quebra: 192 = 137 unpinned-uses (convencao @vN deliberada, INTOCADA) + 46 artipacked + 8 cache-poisoning + 1 superfluous-actions. (a) artipacked 46 -> 1: adicionado 'persist-credentials: false' ao 'with:' de 45 steps actions/checkout cujos jobs NAO fazem git push baseado na credencial do checkout (verificado job-a-job: docker-publish usa peter-evans/dockerhub-description com creds Docker Hub; npm-publish/electron-release usam GITHUB_TOKEN via env em gh release / softprops / .npmrc, independente de persist-credentials; ci usa gh CLI). 1 artipacked RESTANTE = wiki-sync.yml:38, DELIBERADAMENTE deixado com a credencial (job faz git push da wiki; embora o push use um 'git clone' separado com GH_TOKEN embutido, a credencial do checkout foi mantida por seguranca/instrucao explicita). (b) cache-poisoning 8 -> 0: allowlist em .zizmor.yml rules.cache-poisoning.ignore para electron-release.yml + npm-publish.yml (workflows de PUBLISH em eventos confiaveis tags/release/dispatch, nunca PR de fork) e opencode-plugin-ci.yml + opencode-provider-ci.yml (CI-only, publicam ZERO artefatos, cache branch-scoped isola PR de fork). (c) 2 SC2086 genuinos em electron-release.yml corrigidos (>> $GITHUB_OUTPUT / >> $GITHUB_ENV agora quoted) \u2014 actionlint NAO entra no ratchet, fix de higiene. 139 = 137 unpinned + 1 artipacked (wiki-sync) + 1 superfluous-actions. check-workflows --ratchet sai 0 (medido == baseline).", - "_codeql_promote_blocking_2026_06_15": "codeqlAlerts (value 0, direction down) PROMOVIDO de ADVISORY para RATCHET BLOQUEANTE como dedicated gate. CodeQL default-setup esta ON no repo e 'gh api repos/diegosouzapw/OmniRoute/code-scanning/alerts?state=open' retorna 0 alertas abertos (limpo). check-codeql-ratchet.mjs agora le metrics.codeqlAlerts.value, compara e sai 1 SOMENTE numa regressao real (medida > baseline); QUALQUER falha de medicao (gh ausente/sem auth/sem repo/erro de API) e SKIP gracioso com exit 0 \u2014 nunca bloqueia por falta de infraestrutura. O step bloqueante vive no job quality-gate (GH_TOKEN + permissions security-events:read); o step advisory duplicado foi removido do quality-extended. Substitui a nota _int_wiring_2026_06_13 que dizia 'codeqlAlerts permanece advisory'.", + "_scanner_remediation_2026_06_15": "Remediacao das findings reais que os scanners semeados acima expuseram (medido localmente em 2026-06-15 com os mesmos binarios). vulnCount 13->10: bump dos 2 HIGH transitivos via package.json overrides — form-data 4.0.5->^4.0.6 (GHSA-hmw2-7cc7-3qxx, via axios) e vite 8.0.5->^8.0.16 (GHSA-fx2h-pf6j-xcff HIGH + GHSA-v6wh-96g9-6wx3 MODERATE, dev-only via vitest/@vitejs/plugin-react/fumadocs-mdx); osv-scanner confirma 0 HIGH restante; build:cli e a suite vitest MCP (16 files/187 testes) verdes pos-bump. zizmorFindings 195->187: env-harden de 7 findings template-injection (ci.yml job i18n; electron-release.yml jobs validate/build/release — o step 'Create source archives' sozinho gerava 4 das 7) movendo cada ${{...}} para 'env:' e referenciando \"$VAR\" no script, + allowlist de 1 dangerous-triggers (deploy-vps.yml on:workflow_run — guardado por conclusion=='success', deploy via SSH sem checkout de codigo nao-confiavel; entry em .zizmor.yml rules.dangerous-triggers.ignore). secretFindings (3) e bundleSize (5601) intocados neste PR. Apertados via edicao manual (direction:down).", + "_scanner_flip_blocking_2026_06_16": "Etapa 2: secretFindings (3), zizmorFindings e bundleSize (5601) PROMOVIDOS de ADVISORY para RATCHET BLOQUEANTE. Os 3 scripts (check-secrets/check-workflows/check-bundle-size) ganharam um modo --ratchet que le metrics..value daqui, compara a contagem MEDIDA e sai 1 SOMENTE numa regressao real (medida > baseline). Sem --ratchet permanecem advisory (exit 0). Qualquer SKIP gracioso (binario ausente, plugin size-limit ausente => fallback-stat/no-build, build nao rodou) sai 0 MESMO com --ratchet — falta de infra nunca bloqueia, so uma regressao medida bloqueia. zizmorFindings re-baselineada 187 -> 192: o +5 e drift LEGITIMO de novos arquivos de workflow (nightly-schemathesis.yml etc.) adicionados no ciclo v3.8.26, mesma convencao @vN unpinned de todos os workflows; reproduzivel localmente E confirmado no run de CI #27593205254 (job 81578109020) = 192. secretFindings (3) e bundleSize (5601) intocados — ja batiam o valor do CI. NB: bundleSize=5601 e o valor GZIP do size-limit + @size-limit/file (instalado por 'npm ci' no CI); o fallback-stat le bytes CRUS (16670, metrica diferente) e por isso o modo --ratchet SO bloqueia quando a medicao veio do size-limit real, fazendo SKIP no fallback. actionlintFindings NAO entra no ratchet (so reportada); o --strict all-or-nothing do check-workflows permanece separado.", + "_scanner_harden_workflows_2026_06_16": "Hardening real das findings do zizmor (branch ci/workflow-security-hardening). zizmorFindings re-baselineada 192 -> 139 (medido localmente com zizmor 1.25.2 + .zizmor.yml). Quebra: 192 = 137 unpinned-uses (convencao @vN deliberada, INTOCADA) + 46 artipacked + 8 cache-poisoning + 1 superfluous-actions. (a) artipacked 46 -> 1: adicionado 'persist-credentials: false' ao 'with:' de 45 steps actions/checkout cujos jobs NAO fazem git push baseado na credencial do checkout (verificado job-a-job: docker-publish usa peter-evans/dockerhub-description com creds Docker Hub; npm-publish/electron-release usam GITHUB_TOKEN via env em gh release / softprops / .npmrc, independente de persist-credentials; ci usa gh CLI). 1 artipacked RESTANTE = wiki-sync.yml:38, DELIBERADAMENTE deixado com a credencial (job faz git push da wiki; embora o push use um 'git clone' separado com GH_TOKEN embutido, a credencial do checkout foi mantida por seguranca/instrucao explicita). (b) cache-poisoning 8 -> 0: allowlist em .zizmor.yml rules.cache-poisoning.ignore para electron-release.yml + npm-publish.yml (workflows de PUBLISH em eventos confiaveis tags/release/dispatch, nunca PR de fork) e opencode-plugin-ci.yml + opencode-provider-ci.yml (CI-only, publicam ZERO artefatos, cache branch-scoped isola PR de fork). (c) 2 SC2086 genuinos em electron-release.yml corrigidos (>> $GITHUB_OUTPUT / >> $GITHUB_ENV agora quoted) — actionlint NAO entra no ratchet, fix de higiene. 139 = 137 unpinned + 1 artipacked (wiki-sync) + 1 superfluous-actions. check-workflows --ratchet sai 0 (medido == baseline).", + "_codeql_promote_blocking_2026_06_15": "codeqlAlerts (value 0, direction down) PROMOVIDO de ADVISORY para RATCHET BLOQUEANTE como dedicated gate. CodeQL default-setup esta ON no repo e 'gh api repos/diegosouzapw/OmniRoute/code-scanning/alerts?state=open' retorna 0 alertas abertos (limpo). check-codeql-ratchet.mjs agora le metrics.codeqlAlerts.value, compara e sai 1 SOMENTE numa regressao real (medida > baseline); QUALQUER falha de medicao (gh ausente/sem auth/sem repo/erro de API) e SKIP gracioso com exit 0 — nunca bloqueia por falta de infraestrutura. O step bloqueante vive no job quality-gate (GH_TOKEN + permissions security-events:read); o step advisory duplicado foi removido do quality-extended. Substitui a nota _int_wiring_2026_06_13 que dizia 'codeqlAlerts permanece advisory'.", "_metrics_added_2026_06_13_6a11": "openapiCoverage.pct (38.3) e i18nUiCoverage.pct (80.1) promovidas de pisos manuais THRESHOLD para metricas de catraca (direction up) na Task 6A.11. eslintErrors fixado em 0 (era metrica orfa detectada pelo motor v2 da 6A.5).", - "_int_wiring_2026_06_13": "Fase 7 INT: 3 metricas promovidas de ADVISORY para RATCHET BLOQUEANTE. Valores REAIS medidos em 2026-06-13 no HEAD desta branch: deadExports=327 (knip --reporter json, DEAD_TOTAL=exports+files), cognitiveComplexity=738 (eslint sonarjs/cognitive-complexity via eslint.sonarjs.config.mjs), typeCoveragePct=92.17 (type-coverage --json-output -p open-sse/tsconfig.json). Os scripts check-dead-code.mjs/check-cognitive-complexity.mjs/check-type-coverage.mjs foram convertidos de advisory (exit 0 sempre) para ratchet (exit 1 em regressao). vulnCount e codeqlAlerts permanecem advisory no job quality-extended: dependem de binarios externos (osv-scanner) e token GitHub (gh api) nao disponiveis localmente \u2014 nao podem ser medidos/congelados honestamente sem infraestrutura de CI.", - "_coverage_per_module_2026_06_15": "Fase 7 Task 7.9: pisos coverage..lines para os 8 modulos criticos (chatCore/combo/accountFallback/auth/routeGuard/error/publicCreds/circuitBreaker). O coletor (collect-metrics.mjs::coverageByModule + CRITICAL_MODULE_PATHS) ja existia; faltava SO congelar o baseline. Valores semeados CONSERVADORES (~2-3pt abaixo de um run LOCAL de test:coverage de 2026-06-15, que por sua vez mede ~68% global vs ~76.5% do CI mergeado \u2014 logo os pisos estao MUITO abaixo do real do CI, zero risco de red). Apertar via 'quality:ratchet -- --update' a partir do 1o run de coverage mergeada do CI que popule essas chaves. tightenSlack alto (10) absorve a variancia local-vs-CI no step advisory de require-tighten.", - "_require_tighten_advisory_2026_06_15": "Fase 6A.5: o gate --require-tighten (falha quando uma metrica melhora sem o baseline ser apertado no mesmo PR) foi finalmente WIRADO no CI \u2014 porem como STEP ADVISORY (continue-on-error) no job quality-gate, NAO bloqueante. Motivo: (a) o proprio plano sequencia o aperto para 'o fim do ciclo', e a v3.8.26 acabou de abrir; (b) liga-lo bloqueante durante merges ativos travaria qualquer melhoria de metrica ate re-baseline. Para promover a BLOQUEANTE no fim do ciclo: remover o 'continue-on-error: true' do step 'Require-tighten' no ci.yml. tightenSlack nas metricas coverage.* impede falso-disparo pelo gap anti-flake.", + "_int_wiring_2026_06_13": "Fase 7 INT: 3 metricas promovidas de ADVISORY para RATCHET BLOQUEANTE. Valores REAIS medidos em 2026-06-13 no HEAD desta branch: deadExports=327 (knip --reporter json, DEAD_TOTAL=exports+files), cognitiveComplexity=738 (eslint sonarjs/cognitive-complexity via eslint.sonarjs.config.mjs), typeCoveragePct=92.17 (type-coverage --json-output -p open-sse/tsconfig.json). Os scripts check-dead-code.mjs/check-cognitive-complexity.mjs/check-type-coverage.mjs foram convertidos de advisory (exit 0 sempre) para ratchet (exit 1 em regressao). vulnCount e codeqlAlerts permanecem advisory no job quality-extended: dependem de binarios externos (osv-scanner) e token GitHub (gh api) nao disponiveis localmente — nao podem ser medidos/congelados honestamente sem infraestrutura de CI.", + "_coverage_per_module_2026_06_15": "Fase 7 Task 7.9: pisos coverage..lines para os 8 modulos criticos (chatCore/combo/accountFallback/auth/routeGuard/error/publicCreds/circuitBreaker). O coletor (collect-metrics.mjs::coverageByModule + CRITICAL_MODULE_PATHS) ja existia; faltava SO congelar o baseline. Valores semeados CONSERVADORES (~2-3pt abaixo de um run LOCAL de test:coverage de 2026-06-15, que por sua vez mede ~68% global vs ~76.5% do CI mergeado — logo os pisos estao MUITO abaixo do real do CI, zero risco de red). Apertar via 'quality:ratchet -- --update' a partir do 1o run de coverage mergeada do CI que popule essas chaves. tightenSlack alto (10) absorve a variancia local-vs-CI no step advisory de require-tighten.", + "_require_tighten_advisory_2026_06_15": "Fase 6A.5: o gate --require-tighten (falha quando uma metrica melhora sem o baseline ser apertado no mesmo PR) foi finalmente WIRADO no CI — porem como STEP ADVISORY (continue-on-error) no job quality-gate, NAO bloqueante. Motivo: (a) o proprio plano sequencia o aperto para 'o fim do ciclo', e a v3.8.26 acabou de abrir; (b) liga-lo bloqueante durante merges ativos travaria qualquer melhoria de metrica ate re-baseline. Para promover a BLOQUEANTE no fim do ciclo: remover o 'continue-on-error: true' do step 'Require-tighten' no ci.yml. tightenSlack nas metricas coverage.* impede falso-disparo pelo gap anti-flake.", "_require_tighten_flip_blocking_2026_06_16_v3827": "Fim do ciclo v3.8.27: o step 'Require-tighten' do job quality-gate (ci.yml) foi PROMOVIDO de ADVISORY para BLOQUEANTE (removido o 'continue-on-error: true', renomeado para 'Require-tighten (blocking)'). Verificado LIMPO (exit 0, '24 metricas, 0 melhoraram') no tip de release/v3.8.27 ANTES do flip: as metricas deterministicas medem == baseline (eslintWarnings 3769, eslintErrors 0) e as coverage.* foram avaliadas contra a cobertura mergeada == baseline (replicando o estado do CI, onde o job baixa o artifact coverage-report antes do collect). tightenSlack nas coverage.* (5 global / 10 por-modulo) absorve a variancia local-vs-CI e impede falso-disparo. Nenhuma metrica melhorou-sem-apertar, logo o flip nao reda o CI verde atual.", - "_osv_flip_blocking_2026_06_16_v3827": "Fim do ciclo v3.8.27: vulnCount (value 10, direction down, dedicatedGate) PROMOVIDO de ADVISORY para RATCHET BLOQUEANTE. check-vuln-ratchet.mjs ganhou um modo --ratchet (espelhando check-secrets/check-bundle-size/check-workflows da Etapa 2): le metrics.vulnCount.value daqui, compara a contagem MEDIDA pelo osv-scanner e sai 1 SOMENTE numa regressao real (medida > baseline). Sem --ratchet permanece advisory (exit 0). QUALQUER SKIP gracioso (osv-scanner ausente do PATH, osv.dev/rede inacessivel, timeout, JSON invalido) sai 0 MESMO com --ratchet \u2014 uma falha de MEDICAO nunca bloqueia, so uma regressao MEDIDA bloqueia. No ci.yml (job quality-extended) o step 'Vulnerability ratchet' passou a rodar 'npm run check:vuln-ratchet -- --ratchet' sem continue-on-error. Verificado no tip de release/v3.8.27: osv mede vulnCount=10 == baseline 10 (exit 0); forcar baseline=9 da exit 1 (10>9); PATH vazio da SKIP binary-absent exit 0. NB de VARIANCIA DE CVE: um CVE recem-divulgado numa dep ja presente pode redar o gate sem mudanca de dependencia \u2014 comportamento esperado, remedio = bumpar a dep ou re-baseline vulnCount com justificativa+issue. Ver docs/security/SUPPLY_CHAIN.md -> 'Variancia de CVE'.", - "_trivy_flip_blocking_2026_06_16_v3827": "Fim do ciclo v3.8.27: Trivy (scan de CVE da imagem Docker em docker-publish.yml) promovido para BLOQUEANTE em CRITICAL. Abordagem de DOIS PASSOS: o passo SARIF existente (severity HIGH,CRITICAL / exit-code 0 / upload SARIF) fica INTACTO para visibilidade na aba Security; um novo passo 'Trivy CRITICAL gate (blocking)' (severity CRITICAL / ignore-unfixed:true / exit-code 1) falha o release num CVE CRITICO FIXAVEL. ignore-unfixed evita travar por CVE de base-image sem patch upstream (reduz falso-bloqueio). Mesma variancia-de-CVE do osv: um novo CRITICAL fixavel divulgado pode redar; remedio = rebuild sobre base patcheada, bumpar dep, ou .trivyignore com justificativa+issue. Ver docs/security/SUPPLY_CHAIN.md. vulnCount permanece 10 (intocado neste flip \u2014 so a postura advisory->bloqueante mudou).", - "_rebaseline_2026_06_18_v3828_cycle_close": "Fim do ciclo v3.8.28 (RELEASED; ciclo v3.8.29 aberto): 3 metricas re-baselineadas para o valor REAL medido no push->main pos-release (run 27725117464, step 'Ratchet check') \u2014 eslintWarnings 3769->3779, openapiCoverage.pct 38.3->37.6, i18nUiCoverage.pct 80.1->79.1. Reproduzido localmente em release/v3.8.29 (9f14c1294): identico ao CI. Drift de fim-de-ciclo de features legitimas, NAO hand-cleanable: (a) eslint +10 = 'any' PERMITIDO (warn) em testes do ciclo + 4 react-hooks/exhaustive-deps em RequestLoggerV2.tsx (componente com bugs sutis de refresh #4103/#3972, arriscado mexer em deps de hook sem teste de UI); (b) openapi -0.7 = drop por rotas NOVAS INTERNAS (/api/tools/agent-bridge/* LOCAL_ONLY, spawnam MITM/DNS) \u2014 documenta-las no spec PUBLICO seria gaming; (c) i18n -1.0 = 37/41 locales em 79.1% (1741 chaves faltando cada, ~3000 traducoes via 'npm run i18n:run' que exige creds OMNIROUTE_TRANSLATION_API_KEY indisponiveis localmente). Mesmo precedente do _eslint_rebaseline_2026_06_16_v3826_forward_merge. Apertar no fim do ciclo: eslint/openapi via --require-tighten; i18n via i18n:run com creds. Autorizado pelo operador (decisao explicita).", - "_rebaseline_2026_06_19_v3829_cycle_close": "Release do ciclo v3.8.29: eslintWarnings re-baselineado 3779->3816 para o valor REAL medido em release/v3.8.29 (tip da3...; `npm run lint` local = 3816, identico ao Quality Ratchet do CI no PR #4126). O +37 e drift de fim-de-ciclo de 115 commits de features legitimas \u2014 `any` PERMITIDO (warn) em open-sse/ e tests/ do ciclo; os arquivos de reconciliacao deste release nao adicionam warnings (scripts/check/*.mjs sao eslint-ignored, o teste novo de check-fabricated-docs nao usa any). Mesmo precedente de _rebaseline_2026_06_18_v3828_cycle_close. Apertar via --require-tighten no fim do ciclo seguinte. AL\u00c9M disso, o step Require-tighten (blocking) exigiu apertar 2 m\u00e9tricas que MELHORARAM no ciclo (medidas no CI do PR #4126): coverage.auth.lines 69->90 (CI mediu 92.6; piso ~2pt-abaixo-do-real anti-flake, dentro do tightenSlack 10) e openapiCoverage.pct 37.6->38.4 (rotas novas documentadas). Melhorias legitimas travadas no baseline, nao gaming. Autorizado pelo operador (release end-to-end, validado na VPS).", + "_osv_flip_blocking_2026_06_16_v3827": "Fim do ciclo v3.8.27: vulnCount (value 10, direction down, dedicatedGate) PROMOVIDO de ADVISORY para RATCHET BLOQUEANTE. check-vuln-ratchet.mjs ganhou um modo --ratchet (espelhando check-secrets/check-bundle-size/check-workflows da Etapa 2): le metrics.vulnCount.value daqui, compara a contagem MEDIDA pelo osv-scanner e sai 1 SOMENTE numa regressao real (medida > baseline). Sem --ratchet permanece advisory (exit 0). QUALQUER SKIP gracioso (osv-scanner ausente do PATH, osv.dev/rede inacessivel, timeout, JSON invalido) sai 0 MESMO com --ratchet — uma falha de MEDICAO nunca bloqueia, so uma regressao MEDIDA bloqueia. No ci.yml (job quality-extended) o step 'Vulnerability ratchet' passou a rodar 'npm run check:vuln-ratchet -- --ratchet' sem continue-on-error. Verificado no tip de release/v3.8.27: osv mede vulnCount=10 == baseline 10 (exit 0); forcar baseline=9 da exit 1 (10>9); PATH vazio da SKIP binary-absent exit 0. NB de VARIANCIA DE CVE: um CVE recem-divulgado numa dep ja presente pode redar o gate sem mudanca de dependencia — comportamento esperado, remedio = bumpar a dep ou re-baseline vulnCount com justificativa+issue. Ver docs/security/SUPPLY_CHAIN.md -> 'Variancia de CVE'.", + "_trivy_flip_blocking_2026_06_16_v3827": "Fim do ciclo v3.8.27: Trivy (scan de CVE da imagem Docker em docker-publish.yml) promovido para BLOQUEANTE em CRITICAL. Abordagem de DOIS PASSOS: o passo SARIF existente (severity HIGH,CRITICAL / exit-code 0 / upload SARIF) fica INTACTO para visibilidade na aba Security; um novo passo 'Trivy CRITICAL gate (blocking)' (severity CRITICAL / ignore-unfixed:true / exit-code 1) falha o release num CVE CRITICO FIXAVEL. ignore-unfixed evita travar por CVE de base-image sem patch upstream (reduz falso-bloqueio). Mesma variancia-de-CVE do osv: um novo CRITICAL fixavel divulgado pode redar; remedio = rebuild sobre base patcheada, bumpar dep, ou .trivyignore com justificativa+issue. Ver docs/security/SUPPLY_CHAIN.md. vulnCount permanece 10 (intocado neste flip — so a postura advisory->bloqueante mudou).", + "_rebaseline_2026_06_18_v3828_cycle_close": "Fim do ciclo v3.8.28 (RELEASED; ciclo v3.8.29 aberto): 3 metricas re-baselineadas para o valor REAL medido no push->main pos-release (run 27725117464, step 'Ratchet check') — eslintWarnings 3769->3779, openapiCoverage.pct 38.3->37.6, i18nUiCoverage.pct 80.1->79.1. Reproduzido localmente em release/v3.8.29 (9f14c1294): identico ao CI. Drift de fim-de-ciclo de features legitimas, NAO hand-cleanable: (a) eslint +10 = 'any' PERMITIDO (warn) em testes do ciclo + 4 react-hooks/exhaustive-deps em RequestLoggerV2.tsx (componente com bugs sutis de refresh #4103/#3972, arriscado mexer em deps de hook sem teste de UI); (b) openapi -0.7 = drop por rotas NOVAS INTERNAS (/api/tools/agent-bridge/* LOCAL_ONLY, spawnam MITM/DNS) — documenta-las no spec PUBLICO seria gaming; (c) i18n -1.0 = 37/41 locales em 79.1% (1741 chaves faltando cada, ~3000 traducoes via 'npm run i18n:run' que exige creds OMNIROUTE_TRANSLATION_API_KEY indisponiveis localmente). Mesmo precedente do _eslint_rebaseline_2026_06_16_v3826_forward_merge. Apertar no fim do ciclo: eslint/openapi via --require-tighten; i18n via i18n:run com creds. Autorizado pelo operador (decisao explicita).", + "_rebaseline_2026_06_19_v3829_cycle_close": "Release do ciclo v3.8.29: eslintWarnings re-baselineado 3779->3816 para o valor REAL medido em release/v3.8.29 (tip da3...; `npm run lint` local = 3816, identico ao Quality Ratchet do CI no PR #4126). O +37 e drift de fim-de-ciclo de 115 commits de features legitimas — `any` PERMITIDO (warn) em open-sse/ e tests/ do ciclo; os arquivos de reconciliacao deste release nao adicionam warnings (scripts/check/*.mjs sao eslint-ignored, o teste novo de check-fabricated-docs nao usa any). Mesmo precedente de _rebaseline_2026_06_18_v3828_cycle_close. Apertar via --require-tighten no fim do ciclo seguinte. ALÉM disso, o step Require-tighten (blocking) exigiu apertar 2 métricas que MELHORARAM no ciclo (medidas no CI do PR #4126): coverage.auth.lines 69->90 (CI mediu 92.6; piso ~2pt-abaixo-do-real anti-flake, dentro do tightenSlack 10) e openapiCoverage.pct 37.6->38.4 (rotas novas documentadas). Melhorias legitimas travadas no baseline, nao gaming. Autorizado pelo operador (release end-to-end, validado na VPS).", "_quality_rebaseline_2026_06_20_ci_ratchet": "Rebaseline consciente para o Quality Ratchet do PR de CI/build reuse: eslintWarnings 3816->3836 (valor REAL medido localmente por `node scripts/quality/collect-metrics.mjs`; warnings existentes em tests/open-sse, nenhuma warning nova nos arquivos alterados deste PR), coverage.chatCore.lines 74->72.45 (valor REAL do CI mergeado; chatCore.ts nao foi alterado neste PR, a queda e variancia/realidade da cobertura mergeada apos os ajustes de coverage shard/merge, 0.05 abaixo do antigo piso efetivo 72.50 considerando eps=1.5), i18nUiCoverage.pct 79.1->78.4 (valor REAL medido localmente; nenhum src/i18n/messages/*.json mudou neste PR, o denominador en atual e 8408 e 37 locales seguem no mesmo bloco de traducoes pendentes). Nao e gaming de teste: sao baselines de estado real para destravar o gate; apertar depois via --require-tighten quando houver reducao de any/novas traducoes/coverage dedicado.", - "_eslint_rebaseline_2026_06_20_v3831_cycle_close": "Release do ciclo v3.8.31: eslintWarnings re-baselineado 3836->3839 para o valor REAL medido em release/v3.8.31 (`npm run lint` local = 3839, identico ao Quality Ratchet do CI no PR #4377). O +3 e drift de fim-de-ciclo dos PRs de feature legitimos mergeados apos o baseline 3836 (#4381/#4383/#4373/#4389/#4384/#4410) \u2014 `any` PERMITIDO (warn) em open-sse/ e tests/ do ciclo. Trust-but-verify: os arquivos de reconciliacao deste release NAO adicionam warnings (medido delta=0 no teste translator-openai-to-gemini old-vs-new = 79<->79; mitm-tool-hosts = 0; scripts/check/*.mjs e config/*.json nao linted). Mesmo precedente de _rebaseline_2026_06_19_v3829_cycle_close. Apertar via --require-tighten no fim do ciclo seguinte. Autorizado pelo operador (release end-to-end).", + "_eslint_rebaseline_2026_06_20_v3831_cycle_close": "Release do ciclo v3.8.31: eslintWarnings re-baselineado 3836->3839 para o valor REAL medido em release/v3.8.31 (`npm run lint` local = 3839, identico ao Quality Ratchet do CI no PR #4377). O +3 e drift de fim-de-ciclo dos PRs de feature legitimos mergeados apos o baseline 3836 (#4381/#4383/#4373/#4389/#4384/#4410) — `any` PERMITIDO (warn) em open-sse/ e tests/ do ciclo. Trust-but-verify: os arquivos de reconciliacao deste release NAO adicionam warnings (medido delta=0 no teste translator-openai-to-gemini old-vs-new = 79<->79; mitm-tool-hosts = 0; scripts/check/*.mjs e config/*.json nao linted). Mesmo precedente de _rebaseline_2026_06_19_v3829_cycle_close. Apertar via --require-tighten no fim do ciclo seguinte. Autorizado pelo operador (release end-to-end).", "_comment_mutationScore": "Per-module COVERED mutation score floors (detected/(detected+survived)), seeded ~2pt below the first full measurement (run 27823984918: split batches a1/a2/b1/b2/c1/c2/d + e/f/g/h/i). direction:up + dedicatedGate:true -> enforced ONLY by check-mutation-ratchet.mjs (the generic check-quality-ratchet skips dedicatedGate metrics), in the nightly-mutation aggregation job.", - "_zizmor_rebaseline_2026_06_19_r1_redundancy": "zizmorFindings 139 -> 145. Quebra: +3 drift PRE-EXISTENTE da base release/v3.8.30 a23d0d678 (medido com minhas mudancas stashed = 142 > 139; o fast-path do release nao roda check:workflows --ratchet) + 3 do novo workflow mutation-redundancy.yml (R1 disableBail): exatamente 3 unpinned-uses de actions/checkout@v7, actions/setup-node@v6, actions/upload-artifact@v7 \u2014 a MESMA convencao @vN deliberada e INTOCADA de todos os workflows (ver _scanner_harden_workflows_2026_06_16), identica ao nightly-mutation.yml. SHA-pinar so este workflow violaria a convencao. NOTA DE COLISAO CROSS-PR: o PR #4321 (a11y) tambem rebaselina este metric 139->145 (+3 do job a11y) off a MESMA base \u2014 se ambos mergearem, o total real vira 148 (142 base + 3 a11y + 3 r1) e o segundo a mergear precisa reconciliar zizmorFindings -> 148 (mesmo padrao release-volatil dos baselines de complexity/eslint).", - "_zizmor_rebaseline_2026_06_19_a11y_148_reconcile": "RECONCILIACAO CROSS-PR (release-volatil) ao mergear #4321 (a11y) APOS #4322 (R1): zizmorFindings 145 -> 148. O #4322 ja rebaselinou 139->145 (drift base 142 + 3 unpinned-uses do mutation-redundancy.yml). Este PR adiciona +3 unpinned-uses @vN do novo job 'a11y' (nightly-resilience.yml): actions/checkout@v7, actions/setup-node@v6, actions/cache@v5.0.5 \u2014 MESMA convencao @vN deliberada e INTOCADA de todos os workflows (ver _scanner_harden_workflows_2026_06_16). Total = 142 base + 3 r1 + 3 a11y = 148, MEDIDO com `node scripts/check/check-workflows.mjs --ratchet` na arvore release(com #4322)+#4321 = 148 exato. Nenhum template-injection/artipacked/cache-poisoning novo.", + "_zizmor_rebaseline_2026_06_19_r1_redundancy": "zizmorFindings 139 -> 145. Quebra: +3 drift PRE-EXISTENTE da base release/v3.8.30 a23d0d678 (medido com minhas mudancas stashed = 142 > 139; o fast-path do release nao roda check:workflows --ratchet) + 3 do novo workflow mutation-redundancy.yml (R1 disableBail): exatamente 3 unpinned-uses de actions/checkout@v7, actions/setup-node@v6, actions/upload-artifact@v7 — a MESMA convencao @vN deliberada e INTOCADA de todos os workflows (ver _scanner_harden_workflows_2026_06_16), identica ao nightly-mutation.yml. SHA-pinar so este workflow violaria a convencao. NOTA DE COLISAO CROSS-PR: o PR #4321 (a11y) tambem rebaselina este metric 139->145 (+3 do job a11y) off a MESMA base — se ambos mergearem, o total real vira 148 (142 base + 3 a11y + 3 r1) e o segundo a mergear precisa reconciliar zizmorFindings -> 148 (mesmo padrao release-volatil dos baselines de complexity/eslint).", + "_zizmor_rebaseline_2026_06_19_a11y_148_reconcile": "RECONCILIACAO CROSS-PR (release-volatil) ao mergear #4321 (a11y) APOS #4322 (R1): zizmorFindings 145 -> 148. O #4322 ja rebaselinou 139->145 (drift base 142 + 3 unpinned-uses do mutation-redundancy.yml). Este PR adiciona +3 unpinned-uses @vN do novo job 'a11y' (nightly-resilience.yml): actions/checkout@v7, actions/setup-node@v6, actions/cache@v5.0.5 — MESMA convencao @vN deliberada e INTOCADA de todos os workflows (ver _scanner_harden_workflows_2026_06_16). Total = 142 base + 3 r1 + 3 a11y = 148, MEDIDO com `node scripts/check/check-workflows.mjs --ratchet` na arvore release(com #4322)+#4321 = 148 exato. Nenhum template-injection/artipacked/cache-poisoning novo.", "_zizmor_rebaseline_2026_06_20_ci_build_artifact_reuse": "zizmorFindings 148 -> 152. Drift legitimo deste PR ao reutilizar o artefato next-build do job Build em package-artifact/electron-package-smoke e ao separar o build de compatibilidade Node 26: +4 unpinned-uses novos (2x actions/download-artifact@v8, actions/checkout@v7, actions/setup-node@v6). Mantida a convencao deliberada @vN dos workflows (sem SHA-pinning/manual update burden), conforme precedentes _scanner_harden_workflows_2026_06_16 e _zizmor_rebaseline_2026_06_19_*. Sem novos findings de template-injection/artipacked/cache-poisoning; medido localmente com zizmor 1.25.2 via `npm run check:workflows -- --ratchet` = 152.", "_cognitive_rebaseline_2026_07_27_3850_relax_v2_20pct": "cognitiveComplexity 971->1223 (+252, +26.0% over pristine 971). OWNER-APPROVED TEMPORARY relax for v3.8.50-3.8.54 PREPARE phase (docs/ROADMAP.md). v1 was +48 on 2026-07-27; v2 = v1 +20% buffer = +58 → +252 total (cycle 971 measured pristine → 1223 ceiling). Justification: same as complexity v2 — the v3.8.50 release cut coincides with high-merge activity; owner accepted enlarging the headroom to cover the entire PREPARE phase (5 minor cycles .50-.54) without per-PR rebaseline noise, given that re-tightening is mechanical at v3.8.51 via the combo.ts/chatCore.ts decomposition work scheduled in .51/.52 (ROADMAP.md). RE-TIGHTENING MANDATORY in v3.8.51: target 1009 (shrink of 214 from structural extraction during the decomposition campaigns, or via npm run quality:ratchet -- --update if natural shrink appears earlier). The 1009 floor still gives 38 units of post-tighten headroom vs the current pristine 971. Tracked via same roadmap issue as complexity v2. Window: v3.8.50 (release cut) → v3.8.54 close (RE-TIGHTEN at v3.8.51 prep merge per ROADMAP.md). Last entry unless measured regression. v1 entry retained below for audit trail.", - "_cognitive_rebaseline_2026_07_27_3850_relax": "cognitiveComplexity 971->1019 (+48). OWNER-APPROVED TEMPORARY relax for v3.8.50-3.8.54 PREPARE phase (docs/ROADMAP.md). +48 covers Train 1D (+15) + headroom for 3.8.50/.51 batches. RE-TIGHTENING MANDATORY in v3.8.51: target 1009 (from combo.ts/chatCore.ts decomposition scheduled in .51/.52 per ROADMAP.md phases). Tracked via same roadmap issue as complexity. SUPERSEDED by _cognitive_rebaseline_2026_07_27_3850_relax_v2_20pct (v1 +20% buffer) — retained for audit. Last entry unless measured regression." -} \ No newline at end of file + "_cognitive_rebaseline_2026_07_27_3850_relax": "cognitiveComplexity 971->1019 (+48). OWNER-APPROVED TEMPORARY relax for v3.8.50-3.8.54 PREPARE phase (docs/ROADMAP.md). +48 covers Train 1D (+15) + headroom for 3.8.50/.51 batches. RE-TIGHTENING MANDATORY in v3.8.51: target 1009 (from combo.ts/chatCore.ts decomposition scheduled in .51/.52 per ROADMAP.md phases). Tracked via same roadmap issue as complexity. SUPERSEDED by _cognitive_rebaseline_2026_07_27_3850_relax_v2_20pct (v1 +20% buffer) — retained for audit. Last entry unless measured regression." +} diff --git a/config/quality/test-masking-allowlist.json b/config/quality/test-masking-allowlist.json index 995e4f474a..8bf3bf05f9 100644 --- a/config/quality/test-masking-allowlist.json +++ b/config/quality/test-masking-allowlist.json @@ -44,10 +44,57 @@ "tests/unit/usage-analytics-route-extra.test.ts": { "replacement": "tests/unit/usage-analytics-route.test.ts", "reason": "v3.8.49 base-red reconcile: the file was a 100% duplicate — all 10 of its test names exist verbatim (comm -12 verified) among the 22 in tests/unit/usage-analytics-route.test.ts, created by #7700 before #7300 fixed the retention-cutoff fixture only in the main file (reads getUserDatabaseSettings().retention.usageHistory live instead of hardcoding 30d). The stale copy red-failed 'does not double-count raw and aggregated rows' (1 !== 2) against correct production behavior. Zero unique coverage lost; the maintained main file passes 22/22. Verified legitimate, not masking." + }, + "tests/unit/free-budget-card.test.tsx": { + "replacement": "tests/unit/ui/free-budget-card.test.tsx", + "reason": "v3.8.49 #7840: feat(catalog) map unmapped free tiers — o arquivo foi MOVIDO de tests/unit/ para tests/unit/ui/ junto com a expansão do catálogo (o -M do git não detectou o rename porque o conteúdo mudou junto). O componente FreeBudgetCard continua em src/app/(dashboard)/dashboard/usage/components/ e o teste no novo path cobre o mesmo contrato. Relocação, não deleção." + }, + "tests/unit/guardrails/visionBridgeRouter.test.tsx": { + "replacement": "tests/unit/guardrails/visionBridgeRouter.test.ts", + "reason": "v3.8.49 #8433: fix(guardrails) Vision Bridge describe-fallback ignora candidatos inalcançáveis — o teste migrou de .tsx para .ts (não renderiza nada, era TSX por engano) no mesmo diretório, com a cobertura do novo comportamento de fallback. Troca de extensão, não perda de cobertura." + }, + "tests/unit/qwen-api-key-auto-create.test.ts": { + "replacement": "tests/unit/qwen-settings-route.test.ts", + "reason": "v3.8.49 #7866: refactor(qwen) remove o provider OAuth legado — a superfície testada foi DELETADA junto (open-sse/config/providers/registry/qwen/index.ts, open-sse/services/tokenRefresh/providers/qwen.ts, src/lib/oauth/providers/qwen.ts). O fluxo guide-settings que sobrou é coberto pelo replacement (POST escreve o contrato V4 e preserva credenciais alheias; DELETE remove só o que é do OmniRoute)." + }, + "tests/unit/qwen-strip-stream-options-claude-code-port663.test.ts": { + "replacement": "tests/unit/qwen-code-config.test.ts", + "reason": "v3.8.49 #7866: refactor(qwen) remove o provider OAuth legado — o executor cujo stream_options o teste pinava não existe mais. A integração Qwen Code foi RECONSTRUÍDA para o upstream V4 e o replacement guarda o contrato novo, incluindo a migração da forma root-array da integração removida e a limpeza das credenciais legadas de security.auth." + }, + "tests/unit/ui/provider-plan-config.test.tsx": { + "replacement": "tests/unit/quota-plans-route-retired.test.ts", + "reason": "v3.8.49 #7127: fix(tests) suíte vitest UI de volta ao verde — a rota Plans e o ProviderPlanConfigClient foram APOSENTADOS; o replacement inverte a asserção e guarda a aposentadoria (o arquivo da rota e o ProviderPlanConfigClient não existem mais, costs-quota-plans saiu do sidebarVisibility e da navegação)." } }, "tests/unit/catalog-updates-v3x.test.ts": "v3.8.45 #6248: fix(providers) remove deprecated MiMo V2 entries — os 5 asserts removidos pinavam specs de modelos mimo-v2-* que deixaram de existir no catálogo (54→49). Asserts seguem a remoção dos modelos, não enfraquecimento. Verificado legítimo. Prune após v3.8.45 mergear para main.", "tests/unit/xiaomi-mimo-provider.test.ts": "v3.8.45 #6248: fix(providers) remove deprecated MiMo V2 entries — 2 asserts sobre mimo-v2-pro/omni/flash removidos junto com os modelos (21→19). Verificado legítimo, não mascaramento. Prune após v3.8.45 mergear para main.", "tests/unit/provider-models-route.test.ts": "v3.8.45 #6170: fix(providers) correct Kiro model catalog to real upstream ids — 3 assert.ok positivos de ids fabricados (claude-opus-4.7/sonnet-4.6) substituídos por 1 assert positivo de conjunto + 1 assert NEGATIVO garantindo que os ids fabricados sumiram (310→309). Asserts migrados ao catálogo real, não enfraquecidos. Verificado legítimo. Prune após v3.8.45 mergear para main.", - "tests/unit/copilot-gemini-claude-route-no-responses.test.ts": "v3.8.45 #6154: fix(providers) refresh GitHub Copilot catalog — 2 asserts combinados (registry-exists + par claude/gemini) reescritos como loop per-model com assert.ok individual por id do catálogo novo (7→6). Asserts reestruturados ao catálogo atualizado, não enfraquecidos. Verificado legítimo. Prune após v3.8.45 mergear para main." + "tests/unit/copilot-gemini-claude-route-no-responses.test.ts": "v3.8.45 #6154: fix(providers) refresh GitHub Copilot catalog — 2 asserts combinados (registry-exists + par claude/gemini) reescritos como loop per-model com assert.ok individual por id do catálogo novo (7→6). Asserts reestruturados ao catálogo atualizado, não enfraquecidos. Verificado legítimo. Prune após v3.8.45 mergear para main.", + "tests/unit/agy-gemini-3696-tier-passthrough.test.ts": "v3.8.49 #8013: refactor(antigravity) align official clients and callable catalog — o id gemini-3.1-pro-high foi aposentado do catálogo público (o upstream rejeita a discovery slot com 400) e a tier High passou a usar o id distinto gemini-pro-agent, então o assert de passthrough do id aposentado foi removido (net 3→2). Superfície verificada inexistente em open-sse/config/antigravityModelAliases.ts; cobertura de gemini-pro-agent mantida em antigravity-retired-public-models.test.ts e agy-provider.test.ts. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/agy-gemini-400-3229.test.ts": "v3.8.49 #8013: mesma causa do #3696 — gemini-3.1-pro-high aposentado em favor de gemini-pro-agent; o assert de passthrough do id aposentado saiu, restando gemini-3.1-pro-low e o plain id (net 9→8). Verificado contra open-sse/config/antigravityModelAliases.ts. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/anthropic-cache-fingerprint.test.ts": "v3.8.49 #8464: feat(anthropic) add Claude Opus 5 support — o billing header nativo passou a usar CLAUDE_CODE_CLIENT_BILLING_VERSION, um valor capturado do binário assinado (src/shared/constants/claudeCodeClient.ts), no lugar do cálculo homebrew de fingerprint sha256 por dia/mensagem. O teste antigo REIMPLEMENTAVA o algoritmo inline sem nunca importar o código de produção; virou 1 assert que importa a constante real (net 8→1) — mais forte, não mais fraco. O fingerprint dinâmico por dia sobrevive só no caminho CC-bridge e está coberto em cc-bridge-transforms.test.ts (versionFormat ex-machina/omniroute-daystamp). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/antigravity-client-profile.test.ts": "v3.8.49 #8013: o modelo de perfil harness/sdk/cli virou ide/cli unificado; getAntigravityBootstrapHeaders, antigravityHarnessUserAgent, deriveAntigravityMachineId e seedAntigravityVersionCache/clearAntigravityVersionCache foram removidos (grep confirma ausência) e substituídos por getAntigravityEnvelopeUserAgent + seedAntigravityIdeVersionCache/seedAntigravityCliVersionCache. O arquivo foi reescrito cobrindo o contrato novo inteiro (normalização de perfis legados, validação Zod, headers de identidade para ide e cli); net 29→26 é a consolidação. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/antigravity-model-aliases.test.ts": "v3.8.49 #8013: os aliases de remapeamento de gemini-3-pro-preview, gemini-2.5-computer-use-preview-10-2025 e dos tiers de gemini-3.5-flash saíram de ANTIGRAVITY_MODEL_ALIASES (restam 4 entradas), então esses ids passam verbatim; claude-sonnet-5 e gemini-2.5-pro saíram de ANTIGRAVITY_PUBLIC_MODELS e isUserCallableAntigravityModelId retorna false para eles de fato. Dezenas de asserts individuais foram consolidados em loops sobre EXPECTED_FLASH_TIERS/RETIRED_FLASH_IDS, com cobertura NOVA para ids aposentados (net 73→62). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/antigravity-tool-cloaking.test.ts": "v3.8.49 #8013: fix(antigravity) preserve protocol fidelity and fail closed — o mecanismo de cloaking (AG_DECOY_TOOLS, AG_TOOL_SUFFIX, cloakAntigravityToolPayload: renomeava tools do cliente com sufixo e injetava tools-chamariz) foi removido do código (grep confirma ausência total) e substituído por sanitizeAntigravityToolPayload, que preserva nome/ordem/identidade e só remove enumDescriptions (rejeitado com 400 pelo upstream). Os asserts do cloaking testavam código morto; o arquivo novo cobre a sanitização real com casos a mais (anyOf/allOf/$defs/additionalProperties). Net 23→12. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/cache-control-claude-providers.test.ts": "v3.8.49 #7866: refactor(qwen) remove o provider OAuth legado — qwen não existe mais em CACHING_PROVIDERS nem em src/shared/constants/providers.ts (grep confirma), então o assert providerSupportsCaching(\"qwen\",\"openai\")===true testava um provider extinto (net 22→21). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/cache-control-policy.test.ts": "v3.8.49 #8705 + #7866: a estratégia de combo deixou de gatear shouldPreserveCacheControl — a doc-string em open-sse/utils/cacheControlPolicy.ts documenta a mudança de política (reescrever breakpoints por requisição derrubava o prompt cache upstream, ~200k cache_write tokens/turn em produção). Os 8 testes \"rejeita combo com estratégia X\" (false) viraram um loop sobre 8 estratégias incluindo a nova quota-share (true), mais 2 testes negativos NOVOS (provider sem cache, cliente não caching-aware); 1 assert a menos vem do qwen removido pelo #7866. Net 96→91 é consolidação sobre superfície MAIOR. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/codex-failover.test.ts": "v3.8.49 #7866: o assert getMaxAttempts(\"qwen\")===3 exercitava um ramo do helper LOCAL do teste (a fonte real, chatCore.ts, nunca especializou qwen) para um provider agora extinto; removido junto (net 30→29). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/executor-claude-identity.test.ts": "v3.8.49 #8464: buildHashFor (hash do billing header) foi removida de claudeIdentity.ts sem call sites remanescentes — a lógica equivalente migrou para ccBridgeTransforms.ts (rota CC-bridge separada) e o path nativo usa placeholder cch=00000. Os 2 testes do describe morto (3 asserts) saem e 1 assert novo cobre selectBetaFlags para Opus 5 (net 47→45). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/executor-default-base.test.ts": "v3.8.49 #7866 + #8464: o provider \"qwen\" (distinto de qwen-cloud/qwen-web) saiu do DefaultExecutor — não há mais case \"qwen\" em open-sse/executors/default.ts —, então os 3 testes que o exercitavam (9 asserts) foram removidos; o #8464 acrescentou 4 asserts de Opus 5/Stainless/billing no mesmo arquivo. Net 214→209. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/executor-kimi-web-decoder.test.ts": "v3.8.49 #7531: o protocolo Connect do kimi-web trocou isEndOfStream (que silenciava JSON inválido e mensagens tool/function) por getConnectEndStreamError, e foldMessages agora LANÇA em vez de descartar conteúdo não suportado — endurecimento, não enfraquecimento. Os 4 testes do describe antigo (5 asserts) foram consolidados em 1 teste do decoder (net 40→35). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/guide-settings-route.test.ts": "v3.8.49 #7866: saveQwenConfig foi removida do route.ts de guide-settings e o switch(toolId) não trata mais \"qwen\" (cai no default \"not supported\"), como parte da remoção da integração Qwen Code legada. Os 2 testes daquele fluxo (12 asserts) saíram porque a feature deixou de existir (net 35→23). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/kimi-web-models-discovery.test.ts": "v3.8.49 #7531: kimi-web migrou de descoberta remota (HTTP a GetAvailableModels) para catálogo estático curado — KIMI_WEB_STATIC_MODELS=[k3,k2d6] em registry/kimi/web/index.ts. O teste foi reescrito para validar source=\"local_catalog\" e ZERO chamadas de fetch, no lugar de validar payload/headers de uma chamada remota que não existe mais (net 9→4). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/oauth-providers-config.test.ts": "v3.8.49 #7866: QWEN_CONFIG/QWEN_OAUTH_CLIENT_ID saíram das configs OAuth (zero refs a qwen em src/lib/oauth/). O teste dedicado de hostname (4 asserts) e 3 asserts de qwenMapped no teste combinado foram removidos; +2 asserts novos de outras PRs do ciclo (clientProfile do Antigravity #8013, device-model Windows do Kimi #7531). Net 121→116. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/oauth-providers-error-handling.test.ts": "v3.8.49 #7866: o teste \"P2: refreshQwenToken handles invalid_grant\" (3 asserts) saiu — refreshQwenToken não existe mais em open-sse/services/tokenRefresh/. Os demais testes só tiveram o path de leitura do source atualizado pela decomposição de tokenRefresh.ts (#8547/#7817) e tokenHealthCheck.ts (#7719), sem perda de asserts. Net 43→40. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/perplexity-key-validation-models.test.ts": "v3.8.49 #7687: o registry da Perplexity separou modelsUrl (catálogo Agent, agora undefined) de testKeyModelsUrl (validação de chave, mantém /v1/models). O 2º teste antigo (3 asserts de shape estático de string) virou um teste COMPORTAMENTAL que mocka fetch e valida a chamada real de validateProviderApiKey — mais forte (net 7→6). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/provider-header-profiles.test.ts": "v3.8.49 #7866: getQwenOauthHeaders() foi removida por completo de open-sse/config/providerHeaderProfiles.ts (grep confirma zero ocorrências); os 8 asserts perdidos testavam função extinta e 2 asserts novos cobrem getQoderDashscopeCompatHeaders (que reaproveita getQwenCliUserAgent, ainda existente). Net 29→23. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/provider-request-capture-toolname-antigravity-4181.test.ts": "v3.8.49 #8013: o cloak _ide/AG_TOOL_SUFFIX foi removido — o Antigravity passou a usar o catálogo oficial de nomes de ferramentas, sem disfarce (grep confirma que cloakAntigravityToolPayload e AG_TOOL_SUFFIX não existem mais). O arquivo virou 1 teste do novo sanitizeAntigravityToolPayload; a cobertura do comportamento novo foi ampliada em antigravity-tool-cloaking.test.ts (3 testes dedicados). Net 13→5. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/public-client-ids-3493.test.ts": "v3.8.49 #7866: QWEN_CONFIG saiu de src/lib/oauth/constants/oauth.ts (zero ocorrências); o único assert perdido validava QWEN_CONFIG.clientId (net 5→4). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/search-handler-extended.test.ts": "v3.8.49 #7687: a cobertura de handleSearch/Perplexity migrou para tests/unit/search-handler-perplexity-options.test.ts (arquivo novo: cobre os mesmos campos + filtros de locale e acrescenta um caso de validação que não existia — allowlist/denylist de domínio mistos). Net 150→143. Destino verificado existente. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/token-refresh-route-service.test.ts": "v3.8.49 #7866: refreshQwenToken e OAUTH_ENDPOINTS.qwen saíram do código (zero ocorrências); o assert perdido (qwen.providerSpecificData.resourceUrl) testava um fluxo de refresh inexistente e o contador de chamadas foi ajustado de >=8 para >=7 (uma chamada HTTP a menos). Net 50→49. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/translator-openai-to-kiro.test.ts": "v3.8.49 #8565: auto-kiro passou a ser REJEITADO com erro (KIRO_REMOVED_AUTO_ALIAS_MESSAGE, \"not a real Kiro upstream model\") em vez de mapeado silenciosamente para \"auto\"; o teste do comportamento antigo foi removido porque hoje ele asseriria o comportamento errado. A rejeição está coberta em kiro-model-aliases.test.ts (assert.throws /not a real Kiro/) e kiro-available-models.test.ts. Net 119→118. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/usage-providers.test.ts": "v3.8.49 #7866: o case \"qwen\" saiu de getUsageForProvider (não há mais case \"qwen\" no switch de open-sse/services/usage.ts); o teste cobria esse ramo extinto (net 20→19). Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/usage-service-hardening.test.ts": "v3.8.49 #7866/#8565/#8013: qwen removido (−3 asserts); o Kimi/Kiro builder-id (uso profileless) passou a ter SUCESSO real em vez de erro de ARN — supportsProfilelessKiroUsage(\"builder-id\") retorna true —, trocando 1 assert de regex de erro por 3 asserts de valor; e os ids de bucket de quota do Antigravity foram atualizados para o catálogo atual. Rodado no HEAD: 23/23 passam. Net 210→209. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "tests/unit/virtual-auto-combo.test.ts": "v3.8.49 #7928/#8183: o pooling de contas passou a agrupar conexões web-session do mesmo provider numa entrada lógica com allowedConnectionIds (campo confirmado em open-sse/services/autoCombo/virtualFactory.ts), e o pool no-auth virou uma allowlist fixa (AUTO_COMBO_NOAUTH_ALLOWLIST = opencode, felo-web) — os testes antigos esperavam duplicatas e a inclusão de duckduckgo-web/theoldllm/chipotle, que hoje são corretamente excluídos. Guard dedicado em noauth-autocombo-allowlist.test.ts. Rodado no HEAD: 10/10 passam. Net 39→31. Verificado legítimo. Prune após v3.8.49 mergear para main.", + "open-sse/services/__tests__/tierResolver.test.ts": "v3.8.49 #7866: refactor(qwen) remove o provider OAuth legado — o teste \"classifies Qwen as free\" e a entrada de qwen na lista do batch saíram junto com o provider, e os índices do batch desceram de 10 para 9 elementos (net 61→59). Superfície extinta, não enfraquecimento. Verificado legítimo. Prune após v3.8.49 mergear para main." } diff --git a/docs/architecture/AUTHZ_GUIDE.md b/docs/architecture/AUTHZ_GUIDE.md index 4f10555901..c12efe8c4c 100644 --- a/docs/architecture/AUTHZ_GUIDE.md +++ b/docs/architecture/AUTHZ_GUIDE.md @@ -39,6 +39,32 @@ Verified by `isDashboardSessionAuthenticated()` in `src/shared/utils/apiAuth.ts` Some management routes accept **either** mode: cookie OR `Bearer ` when the API key has the `manage` (or `admin`) scope. This is what enables the "configurable via API calls" workflow added in v3.8. +#### Optional OIDC login gate (#6973) + +The dashboard admin login also supports an **opt-in** OIDC (OpenID Connect) flow +alongside the default password login — password login is never removed, only +supplemented: + +- Disabled unless `settings.oidcEnabled === true` **and** `oidcIssuer` / + `oidcClientId` / `oidcClientSecret` are all configured (Settings → Auth). + `GET /api/auth/oidc/login` returns `400` otherwise. +- `GET /api/auth/oidc/login` discovers the `authorization_endpoint` from the + issuer's `/.well-known/openid-configuration` (falls back to + `/authorize`), builds the redirect URI from the incoming request + (`x-forwarded-proto`-aware), and redirects to the IdP with a random `state` + stored in an `httpOnly` `oidc_state` cookie. +- `GET /api/auth/oidc/callback` validates `state`, exchanges the authorization + code, and verifies the ID token's signature via the issuer's JWKS + (`jose`'s `createRemoteJWKSet`, cached per JWKS URI) with `issuer`/`audience` + checks. An optional `oidcAllowedSubjects` allowlist matches the token's + `sub` claim or its `email` claim — the email claim is only honored when + `email_verified === true`, so an unverified email at the IdP can never pass + the gate. +- On success it mints the **exact same** 30-day `auth_token` JWT the password + login issues (`src/app/api/auth/login/route.ts`), so the rest of the + dashboard session pipeline (auto-refresh, cookie flags) is unchanged — + OIDC only replaces how the cookie gets minted, not what it grants. + ## Route Classes `src/server/authz/types.ts` defines three classes; any route that cannot be classified deterministically falls back to `MANAGEMENT`. diff --git a/docs/architecture/RESILIENCE_GUIDE.md b/docs/architecture/RESILIENCE_GUIDE.md index 5c04f29723..060e93c247 100644 --- a/docs/architecture/RESILIENCE_GUIDE.md +++ b/docs/architecture/RESILIENCE_GUIDE.md @@ -262,7 +262,7 @@ it is unit-testable without a real Bottleneck limiter. ## Other Resilience Features -- **18 routing strategies** (priority, weighted, round-robin, context-relay, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, fusion, pipeline) — see [AUTO-COMBO.md](../routing/AUTO-COMBO.md). +- **19 routing strategies** (priority, weighted, round-robin, context-relay, fill-first, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, cache-optimized, fusion, pipeline) — see [AUTO-COMBO.md](../routing/AUTO-COMBO.md). - **Reset-aware routing** (v3.8.0) — prioritizes connections by quota reset time. - **Background mode degradation** — Responses API `background: true` degraded to sync with warning. - **Dynamic tool limit detection** — backs off providers when tool count limits hit. diff --git a/docs/assets/pix-qr.png b/docs/assets/pix-qr.png new file mode 100644 index 0000000000..50ab0c4e3e Binary files /dev/null and b/docs/assets/pix-qr.png differ diff --git a/docs/diagrams/auto-combo-12factor.mmd b/docs/diagrams/auto-combo-12factor.mmd index 0cff9e8d28..3c7f967534 100644 --- a/docs/diagrams/auto-combo-12factor.mmd +++ b/docs/diagrams/auto-combo-12factor.mmd @@ -1,11 +1,11 @@ -%% Auto-Combo 12-factor scoring +%% Auto-Combo 13-factor scoring %% Reflects: open-sse/services/autoCombo/scoring.ts (DEFAULT_WEIGHTS, sum = 1.0) -%% v3.8.40 +%% v3.8.49 flowchart TB Request["Incoming request"] --> Candidates["Eligible candidates
(provider × model × account)"] Candidates --> Score["Compute composite score
per candidate"] - subgraph Factors["12-factor scoring weights (sum = 1.0)"] + subgraph Factors["13-factor scoring weights (sum = 1.0)"] f1["health (0.20)"] f2["quota (0.15)"] f3["costInv (0.15)"] @@ -17,7 +17,8 @@ flowchart TB f9["specificityMatch (0.05)"] f10["contextAffinity (0.05)"] f11["connectionDensity (0.05)"] - f12["resetWindowAffinity (0.00)"] + f12["cacheAffinity (0.00)"] + f13["resetWindowAffinity (0.00)"] end Score --> Factors diff --git a/docs/i18n/ar/CHANGELOG.md b/docs/i18n/ar/CHANGELOG.md index 410eba8a90..799d99a57a 100644 --- a/docs/i18n/ar/CHANGELOG.md +++ b/docs/i18n/ar/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/az/CHANGELOG.md b/docs/i18n/az/CHANGELOG.md index 76a16a83c6..e3c0eba1c1 100644 --- a/docs/i18n/az/CHANGELOG.md +++ b/docs/i18n/az/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/bg/CHANGELOG.md b/docs/i18n/bg/CHANGELOG.md index 76a16a83c6..e3c0eba1c1 100644 --- a/docs/i18n/bg/CHANGELOG.md +++ b/docs/i18n/bg/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/bn/CHANGELOG.md b/docs/i18n/bn/CHANGELOG.md index 30dc50aab1..2bf5e5ff9e 100644 --- a/docs/i18n/bn/CHANGELOG.md +++ b/docs/i18n/bn/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/cs/CHANGELOG.md b/docs/i18n/cs/CHANGELOG.md index 2652faf443..df798f6457 100644 --- a/docs/i18n/cs/CHANGELOG.md +++ b/docs/i18n/cs/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/da/CHANGELOG.md b/docs/i18n/da/CHANGELOG.md index 74de07b1c7..142a435ec7 100644 --- a/docs/i18n/da/CHANGELOG.md +++ b/docs/i18n/da/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/de/CHANGELOG.md b/docs/i18n/de/CHANGELOG.md index bed483f396..84db9b8fd2 100644 --- a/docs/i18n/de/CHANGELOG.md +++ b/docs/i18n/de/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/es/CHANGELOG.md b/docs/i18n/es/CHANGELOG.md index f1c7bbbdf0..358ec30790 100644 --- a/docs/i18n/es/CHANGELOG.md +++ b/docs/i18n/es/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/fa/CHANGELOG.md b/docs/i18n/fa/CHANGELOG.md index e6121f4b11..61515eac55 100644 --- a/docs/i18n/fa/CHANGELOG.md +++ b/docs/i18n/fa/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/fi/CHANGELOG.md b/docs/i18n/fi/CHANGELOG.md index 1f0ec66b66..f83e30d1f1 100644 --- a/docs/i18n/fi/CHANGELOG.md +++ b/docs/i18n/fi/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/fr/CHANGELOG.md b/docs/i18n/fr/CHANGELOG.md index 94cf8f89af..906fb38a42 100644 --- a/docs/i18n/fr/CHANGELOG.md +++ b/docs/i18n/fr/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/gu/CHANGELOG.md b/docs/i18n/gu/CHANGELOG.md index 964fe9b5e9..7d69ee7e75 100644 --- a/docs/i18n/gu/CHANGELOG.md +++ b/docs/i18n/gu/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/he/CHANGELOG.md b/docs/i18n/he/CHANGELOG.md index bc99409d24..0583fefab1 100644 --- a/docs/i18n/he/CHANGELOG.md +++ b/docs/i18n/he/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/hi/CHANGELOG.md b/docs/i18n/hi/CHANGELOG.md index 12e6d9eb40..3ddfbda431 100644 --- a/docs/i18n/hi/CHANGELOG.md +++ b/docs/i18n/hi/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/hu/CHANGELOG.md b/docs/i18n/hu/CHANGELOG.md index 496eb276f7..48449e327a 100644 --- a/docs/i18n/hu/CHANGELOG.md +++ b/docs/i18n/hu/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/id/CHANGELOG.md b/docs/i18n/id/CHANGELOG.md index 6f7e50b9b2..86d7bdac96 100644 --- a/docs/i18n/id/CHANGELOG.md +++ b/docs/i18n/id/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/in/CHANGELOG.md b/docs/i18n/in/CHANGELOG.md index 58c19714a0..bce80061fb 100644 --- a/docs/i18n/in/CHANGELOG.md +++ b/docs/i18n/in/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/it/CHANGELOG.md b/docs/i18n/it/CHANGELOG.md index abea20c78a..f763a9d345 100644 --- a/docs/i18n/it/CHANGELOG.md +++ b/docs/i18n/it/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/ja/CHANGELOG.md b/docs/i18n/ja/CHANGELOG.md index 433c3c55c2..39983070e8 100644 --- a/docs/i18n/ja/CHANGELOG.md +++ b/docs/i18n/ja/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/ko/CHANGELOG.md b/docs/i18n/ko/CHANGELOG.md index 028b72bc17..fd49344b93 100644 --- a/docs/i18n/ko/CHANGELOG.md +++ b/docs/i18n/ko/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/mr/CHANGELOG.md b/docs/i18n/mr/CHANGELOG.md index d1535ac9fe..c66aa1ad78 100644 --- a/docs/i18n/mr/CHANGELOG.md +++ b/docs/i18n/mr/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/ms/CHANGELOG.md b/docs/i18n/ms/CHANGELOG.md index 8cf34a3106..73e5a55006 100644 --- a/docs/i18n/ms/CHANGELOG.md +++ b/docs/i18n/ms/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/nl/CHANGELOG.md b/docs/i18n/nl/CHANGELOG.md index de6c836025..930997514a 100644 --- a/docs/i18n/nl/CHANGELOG.md +++ b/docs/i18n/nl/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/no/CHANGELOG.md b/docs/i18n/no/CHANGELOG.md index 27828792ca..c773193134 100644 --- a/docs/i18n/no/CHANGELOG.md +++ b/docs/i18n/no/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/phi/CHANGELOG.md b/docs/i18n/phi/CHANGELOG.md index 0275996da0..9a603d06aa 100644 --- a/docs/i18n/phi/CHANGELOG.md +++ b/docs/i18n/phi/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/pl/CHANGELOG.md b/docs/i18n/pl/CHANGELOG.md index 6e500c54ec..4039a8f7c1 100644 --- a/docs/i18n/pl/CHANGELOG.md +++ b/docs/i18n/pl/CHANGELOG.md @@ -20,8 +20,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -298,6 +297,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -311,6 +326,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1024,6 +1041,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1055,6 +1188,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1067,6 +1211,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1105,6 +1254,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1137,6 +1338,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1237,15 +1440,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1253,6 +1455,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1260,13 +1463,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1276,35 +1480,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1317,6 +1527,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1324,24 +1536,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1349,32 +1567,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1395,7 +1617,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/pt-BR/CHANGELOG.md b/docs/i18n/pt-BR/CHANGELOG.md index 682b3f176d..c5194f7aad 100644 --- a/docs/i18n/pt-BR/CHANGELOG.md +++ b/docs/i18n/pt-BR/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/pt/CHANGELOG.md b/docs/i18n/pt/CHANGELOG.md index c019e176c5..14a965cb4a 100644 --- a/docs/i18n/pt/CHANGELOG.md +++ b/docs/i18n/pt/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/ro/CHANGELOG.md b/docs/i18n/ro/CHANGELOG.md index e0d299cecf..b5e6c0c9c9 100644 --- a/docs/i18n/ro/CHANGELOG.md +++ b/docs/i18n/ro/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/ru/CHANGELOG.md b/docs/i18n/ru/CHANGELOG.md index 4ff2b412b0..3c5424f88c 100644 --- a/docs/i18n/ru/CHANGELOG.md +++ b/docs/i18n/ru/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/sk/CHANGELOG.md b/docs/i18n/sk/CHANGELOG.md index d86f3cc4f7..b4931fd318 100644 --- a/docs/i18n/sk/CHANGELOG.md +++ b/docs/i18n/sk/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/sv/CHANGELOG.md b/docs/i18n/sv/CHANGELOG.md index 87aa91cf91..f18e28ed1d 100644 --- a/docs/i18n/sv/CHANGELOG.md +++ b/docs/i18n/sv/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/sw/CHANGELOG.md b/docs/i18n/sw/CHANGELOG.md index 23b2878890..6db673ec9c 100644 --- a/docs/i18n/sw/CHANGELOG.md +++ b/docs/i18n/sw/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/ta/CHANGELOG.md b/docs/i18n/ta/CHANGELOG.md index c252bc8846..540e3aae9f 100644 --- a/docs/i18n/ta/CHANGELOG.md +++ b/docs/i18n/ta/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/te/CHANGELOG.md b/docs/i18n/te/CHANGELOG.md index 957afe0ec0..09ac423081 100644 --- a/docs/i18n/te/CHANGELOG.md +++ b/docs/i18n/te/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/th/CHANGELOG.md b/docs/i18n/th/CHANGELOG.md index a9125853d2..cd320aebfd 100644 --- a/docs/i18n/th/CHANGELOG.md +++ b/docs/i18n/th/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/tr/CHANGELOG.md b/docs/i18n/tr/CHANGELOG.md index bf6edcc503..4bbdccf715 100644 --- a/docs/i18n/tr/CHANGELOG.md +++ b/docs/i18n/tr/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/uk-UA/CHANGELOG.md b/docs/i18n/uk-UA/CHANGELOG.md index 6e5f18aa61..24b7a31a86 100644 --- a/docs/i18n/uk-UA/CHANGELOG.md +++ b/docs/i18n/uk-UA/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/ur/CHANGELOG.md b/docs/i18n/ur/CHANGELOG.md index 0f28c8b4cc..e3dfaa08e2 100644 --- a/docs/i18n/ur/CHANGELOG.md +++ b/docs/i18n/ur/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/vi/CHANGELOG.md b/docs/i18n/vi/CHANGELOG.md index 4d9a8b273b..92ccfc6c88 100644 --- a/docs/i18n/vi/CHANGELOG.md +++ b/docs/i18n/vi/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/zh-CN/CHANGELOG.md b/docs/i18n/zh-CN/CHANGELOG.md index 39e7fddebe..36e9c1c22e 100644 --- a/docs/i18n/zh-CN/CHANGELOG.md +++ b/docs/i18n/zh-CN/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/i18n/zh-TW/CHANGELOG.md b/docs/i18n/zh-TW/CHANGELOG.md index 7fe90b00eb..727a2fb15d 100644 --- a/docs/i18n/zh-TW/CHANGELOG.md +++ b/docs/i18n/zh-TW/CHANGELOG.md @@ -18,8 +18,7 @@ _Living section — cycle opened at the v3.8.49 freeze (parallel-cycle model). B --- - -## [3.8.49] — TBD +## [3.8.49] — 2026-07-28 _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62333b0 → tip). Bullets carry the merged PR and its author; direct pushes listed separately. Finalized at the v3.8.49 release._ @@ -296,6 +295,22 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 routing or account activation. - docs(i18n): rewrite Russian README as a full native manual (structure aligned with modern EN/zh-CN, fixed relative asset links). - **Providers**: adds the Xiaomi MiMo Token Plan provider and a per-connection API-protocol selector — some providers publish the same models over more than one protocol, and a connection can now pick the alternative instead of being locked to the OpenAI-compatible default ([#8861](https://github.com/diegosouzapw/OmniRoute/pull/8861)) +- **feat(opencode-plugin):** auto-discover models while running + force sync ([#8101](https://github.com/diegosouzapw/OmniRoute/pull/8101)) — thanks @RaviTharuma +- **feat(combo):** enforce provider and model family invariants ([#8304](https://github.com/diegosouzapw/OmniRoute/pull/8304)) — thanks @RaviTharuma +- **feat(cli):** replace ANTHROPIC_SMALL_FAST_MODEL with Fable default ([#8343](https://github.com/diegosouzapw/OmniRoute/pull/8343)) — thanks @leszek3737 +- **feat:** read INITIAL_PASSWORD env var during setup ([#8439](https://github.com/diegosouzapw/OmniRoute/pull/8439)) — thanks @linhdmn +- **feat(providers):** add missing opencode-go reasoning effort variants ([#8441](https://github.com/diegosouzapw/OmniRoute/pull/8441)) — thanks @Prudhvivuda +- **feat:** add Claude Opus 5 support ([#8464](https://github.com/diegosouzapw/OmniRoute/pull/8464)) — thanks @backryun +- **feat(combos):** add select all / unselect all in Browse Catalog ([#8526](https://github.com/diegosouzapw/OmniRoute/pull/8526)) — thanks @JoshimOfficial +- **feat(cli-tools):** add all Hermes Agent auxiliary model roles ([#8543](https://github.com/diegosouzapw/OmniRoute/pull/8543)) — thanks @leszek3737 +- **feat(ci):** block stale UI translations when an English value is rewritten ([#8574](https://github.com/diegosouzapw/OmniRoute/pull/8574)) +- **feat(providers):** flatten multi-turn history for gemini-web ([#8607](https://github.com/diegosouzapw/OmniRoute/pull/8607)) — thanks @Prudhvivuda +- **feat(sse):** relay upstream 4xx error bodies verbatim on the Anthropic request path ([#8622](https://github.com/diegosouzapw/OmniRoute/pull/8622)) +- **feat:** Claude Code discovery aliases (surface non-Claude models in the /model picker) ([#8666](https://github.com/diegosouzapw/OmniRoute/pull/8666)) +- **feat(dashboard):** copy-paste settings.json block for Claude Code discovery ([#8722](https://github.com/diegosouzapw/OmniRoute/pull/8722)) +- **feat(quality):** temporary relax of complexity/file-size ratchets for v3.8.50-3.8.54 PREPARE phase ([#8767](https://github.com/diegosouzapw/OmniRoute/pull/8767)) +- **feat(db):** let the migration runner scan extra namespaced directories ([#8770](https://github.com/diegosouzapw/OmniRoute/pull/8770)) +- **feat(api):** prompt-cache health summary endpoint and analytics tab ([#8827](https://github.com/diegosouzapw/OmniRoute/pull/8827)) ### ⚡ Performance - **perf(db):** project columns + composite index in getProviderConnections ([#6918](https://github.com/diegosouzapw/OmniRoute/pull/6918)) — thanks @oyi77 @@ -309,6 +324,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **perf(memory):** mitigate event-loop starvation under 3000+ provider connections ([#7719](https://github.com/diegosouzapw/OmniRoute/pull/7719)) — thanks @oyi77 - **perf:** reduce long-context request copies ([#7862](https://github.com/diegosouzapw/OmniRoute/pull/7862)) — thanks @RaviTharuma - **perf:** lazy provider init, P2C quota cache, structuredClone elimination, getSettings→getCachedSettings (batch 2) ([#7893](https://github.com/diegosouzapw/OmniRoute/pull/7893)) — thanks @oyi77 +- **perf(api):** singleflight version lookups ([#8301](https://github.com/diegosouzapw/OmniRoute/pull/8301)) — thanks @RaviTharuma +- **perf(api):** skip the full catalog build for quota-exclusive keys ([#8771](https://github.com/diegosouzapw/OmniRoute/pull/8771)) ### 🐛 Bug Fixes - **fix:** add re-entrancy guard to token health check sweep ([#6917](https://github.com/diegosouzapw/OmniRoute/pull/6917)) — thanks @oyi77 @@ -1022,6 +1039,122 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **Auto routing**: `auto/` combos (`auto/glm`, `auto/gemini`, `auto/llama`, …) are recognized as built-in auto models again — the family suffix failed the category/tier parser and fell through as an unknown model instead of routing to that family ([#8866](https://github.com/diegosouzapw/OmniRoute/pull/8866)) — thanks @rafaeldrincon - **fix(oauth):** wire Test Connection for xAI OAuth (`xai-oauth` / `xao`) so dashboard no longer returns "Provider test not supported" ([#8862](https://github.com/diegosouzapw/OmniRoute/pull/8862)) — thanks @allanvb - **Logs**: a failed `auto/` request no longer writes every attempted model into `call_logs.provider` — the logs page builds its quick-filter pills from that column, so one failure produced a giant chip that flooded the filter row. Rejected combo requests are now labelled `auto` (for `auto/*`) or by the combo's own name ([#8867](https://github.com/diegosouzapw/OmniRoute/pull/8867)) — thanks @rafaeldrincon +- **fix(usage):** correct token/request counting for 30D/90D/YTD/ALL ranges ([#7300](https://github.com/diegosouzapw/OmniRoute/pull/7300)) — thanks @growab +- **fix(notion-web):** use Chrome TLS impersonation for runInferenceTranscript ([#8159](https://github.com/diegosouzapw/OmniRoute/pull/8159)) — thanks @artickc +- **fix(bifrost):** send v-prefixed transport version, not bare semver ([#8194](https://github.com/diegosouzapw/OmniRoute/pull/8194)) — thanks @seanford +- **fix(resilience,translator):** three release/v3.8.49 base-red regressions + eslint baseline — conflict resolved ([#8254](https://github.com/diegosouzapw/OmniRoute/pull/8254)) +- **fix(sse):** export PROVIDER_BREAKER_FAILURE_STATUSES — fix ReferenceError in chat.ts (base-red slice 4) ([#8258](https://github.com/diegosouzapw/OmniRoute/pull/8258)) +- **fix(providers):** limit Gemini CLI to legacy OAuth refresh ([#8275](https://github.com/diegosouzapw/OmniRoute/pull/8275)) — thanks @backryun +- **fix(cli):** resolve claude.cmd on Windows in omniroute launch ([#8283](https://github.com/diegosouzapw/OmniRoute/pull/8283)) — thanks @Dingding-leo +- **fix(resilience):** skip terminal connections in token health check sweep ([#8286](https://github.com/diegosouzapw/OmniRoute/pull/8286)) — thanks @Dingding-leo +- **fix(sanitizer):** strip zero-width chars from Anthropic-native streaming text_delta ([#8287](https://github.com/diegosouzapw/OmniRoute/pull/8287)) — thanks @Dingding-leo +- **fix(i18n):** re-sync and complete es-ES translations with latest release/v3.8.49 ([#8289](https://github.com/diegosouzapw/OmniRoute/pull/8289)) — thanks @Dragost +- **fix(antigravity):** add missing gemini-3.6-flash pricing rows to ag OAuth pricing ([#8290](https://github.com/diegosouzapw/OmniRoute/pull/8290)) — thanks @HouMinXi +- **fix(dashboard):** stop sidebar RSC prefetch storms ([#8292](https://github.com/diegosouzapw/OmniRoute/pull/8292)) — thanks @RaviTharuma +- **fix(backend):** add structure-aware chat admission ([#8296](https://github.com/diegosouzapw/OmniRoute/pull/8296)) — thanks @RaviTharuma +- **fix(providers):** adapt Kimi nonstream requests internally ([#8302](https://github.com/diegosouzapw/OmniRoute/pull/8302)) — thanks @RaviTharuma +- **fix(mcp):** keep POST SSE responses uncompressed ([#8303](https://github.com/diegosouzapw/OmniRoute/pull/8303)) — thanks @RaviTharuma +- **fix(api):** enforce image generation API key auth ([#8306](https://github.com/diegosouzapw/OmniRoute/pull/8306)) — thanks @fenix007 +- **fix(cpa):** isolate credential-pool failures ([#8308](https://github.com/diegosouzapw/OmniRoute/pull/8308)) — thanks @RaviTharuma +- **fix(sse):** suppress by default on Chat Completions ([#8309](https://github.com/diegosouzapw/OmniRoute/pull/8309)) — thanks @Prudhvivuda +- **fix(translator):** cap thinking budget on explicit budget_tokens path ([#8312](https://github.com/diegosouzapw/OmniRoute/pull/8312)) — thanks @HouMinXi +- **fix(providers):** classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model ([#8319](https://github.com/diegosouzapw/OmniRoute/pull/8319)) +- **fix(providers):** carve cookie-auth providers out of terminal 401 'expired' classification so one 401 cooldowns instead of killing the connection ([#8321](https://github.com/diegosouzapw/OmniRoute/pull/8321)) +- **fix(api):** fold namespace into the flattened Chat tool name so cross-namespace leaves do not collide ([#8322](https://github.com/diegosouzapw/OmniRoute/pull/8322)) +- **fix(providers):** route noauth opencode-zen connections through their assigned proxy ([#8324](https://github.com/diegosouzapw/OmniRoute/pull/8324)) +- **fix(security):** remove quadratic trailing-slash trim in Alibaba endpoint normalization ([#8333](https://github.com/diegosouzapw/OmniRoute/pull/8333)) +- **fix(memory):** self-heal upsertVector/deleteVector from a raced vec_memories drop ([#8337](https://github.com/diegosouzapw/OmniRoute/pull/8337)) — thanks @hartmark +- **fix(sse):** stop stripInternalReasoningPlaceholder from eating inter-word spaces ([#8341](https://github.com/diegosouzapw/OmniRoute/pull/8341)) — thanks @hartmark +- **fix(compression):** rank codex-responses in adaptive-ladder maps ([#8381](https://github.com/diegosouzapw/OmniRoute/pull/8381)) +- **fix(sse):** gate reasoning-placeholder strip to chunks that contain the sentinel ([#8382](https://github.com/diegosouzapw/OmniRoute/pull/8382)) +- **fix(resilience):** terminal-skip spares the recoverable GitHub Copilot no_refresh_token state ([#8389](https://github.com/diegosouzapw/OmniRoute/pull/8389)) +- **fix(sse):** re-export PROVIDER_BREAKER_FAILURE_STATUSES for the orphaned all-rate-limited breaker path ([#8390](https://github.com/diegosouzapw/OmniRoute/pull/8390)) +- **fix(sse):** family auto-combos include any backend that serves the family (no-auth allowlist scoped to tier pools) ([#8391](https://github.com/diegosouzapw/OmniRoute/pull/8391)) +- **fix(sse):** cap exact cooldowns only when synthetic — verified upstream resets pass uncapped ([#8393](https://github.com/diegosouzapw/OmniRoute/pull/8393)) +- **fix(devin-cli):** update ACP JSON-RPC protocol for Devin CLI 3000.2.x (Fixes #8406) ([#8425](https://github.com/diegosouzapw/OmniRoute/pull/8425)) — thanks @MumuTW +- **fix(auth):** exclude local CLI providers from tokenHealthCheck expiration (Fixes #8407) ([#8426](https://github.com/diegosouzapw/OmniRoute/pull/8426)) — thanks @MumuTW +- **fix(oauth):** add devin-cli and agy entries to OAUTH_TEST_CONFIG ([#8427](https://github.com/diegosouzapw/OmniRoute/pull/8427)) — thanks @MumuTW +- **fix(dashboard):** preserve connection health visual on last routed topology node ([#8428](https://github.com/diegosouzapw/OmniRoute/pull/8428)) — thanks @MumuTW +- **fix(cursor):** bridge native TodoWrite completions ([#8432](https://github.com/diegosouzapw/OmniRoute/pull/8432)) — thanks @makcimbx +- **fix(guardrails):** Vision Bridge describe-fallback ignores unreachable candidates ([#8433](https://github.com/diegosouzapw/OmniRoute/pull/8433)) — thanks @guhcostan +- **fix(sse):** record tool calls into shared state for openai->openai-responses call-log summary ([#8462](https://github.com/diegosouzapw/OmniRoute/pull/8462)) — thanks @hartmark +- **fix(oauth):** actionable guidance for LAN-origin loopback mismatches (codex + Antigravity) ([#8463](https://github.com/diegosouzapw/OmniRoute/pull/8463)) +- **fix(hyperagent):** sticky thread for agentic tool loops (Claude Code) ([#8470](https://github.com/diegosouzapw/OmniRoute/pull/8470)) — thanks @artickc +- **fix:** combo input-bound, Responses->Chat image strip, qwen-web toolCalling, empty-response exhaustion ([#8476](https://github.com/diegosouzapw/OmniRoute/pull/8476)) — thanks @herjarsa +- **fix(sse):** call the real abort-signal helper in the Gemini Business executor ([#8485](https://github.com/diegosouzapw/OmniRoute/pull/8485)) — thanks @backryun +- **fix(providers):** honor Extra API Keys rotation in OpencodeExecutor ([#8493](https://github.com/diegosouzapw/OmniRoute/pull/8493)) — thanks @Prudhvivuda +- **fix(backend):** fail closed when capability filters empty the combo pool ([#8494](https://github.com/diegosouzapw/OmniRoute/pull/8494)) — thanks @Prudhvivuda +- **fix(providers):** resolve native vision for path-shaped multimodal model ids ([#8495](https://github.com/diegosouzapw/OmniRoute/pull/8495)) — thanks @Prudhvivuda +- **fix(hyperagent):** default 1M context for fable/opus/sonnet ([#8496](https://github.com/diegosouzapw/OmniRoute/pull/8496)) — thanks @artickc +- **fix(notion-web):** mint fresh thread for new OpenAI sessions with same opener ([#8511](https://github.com/diegosouzapw/OmniRoute/pull/8511)) — thanks @artickc +- **fix(db):** classify compressionDetailNormalizers as db-internal in check-db-rules ([#8534](https://github.com/diegosouzapw/OmniRoute/pull/8534)) — thanks @MumuTW +- **fix(sse):** label HTTP 499 disconnects as client_disconnected ([#8552](https://github.com/diegosouzapw/OmniRoute/pull/8552)) — thanks @DinonowDev +- **fix(resilience):** honor comboCooldownWait for every combo strategy ([#8559](https://github.com/diegosouzapw/OmniRoute/pull/8559)) — thanks @DinonowDev +- **fix(backend):** add error.code to synthOpenAIErrorChunk for guard compatibility ([#8570](https://github.com/diegosouzapw/OmniRoute/pull/8570)) — thanks @marceli1404 +- **fix(video):** validate Veo AI Free artifacts before success ([#8581](https://github.com/diegosouzapw/OmniRoute/pull/8581)) — thanks @brunnolouzada +- **fix(routing):** exclude locked-out models from auto-combo candidates ([#8586](https://github.com/diegosouzapw/OmniRoute/pull/8586)) — thanks @Prudhvivuda +- **fix(api):** prevent silent lost updates on concurrent settings writes ([#8587](https://github.com/diegosouzapw/OmniRoute/pull/8587)) — thanks @Prudhvivuda +- **fix(auto-combo):** short-circuit expandAutoComboCandidatePool when models[] is non-empty ([#8598](https://github.com/diegosouzapw/OmniRoute/pull/8598)) — thanks @mikeiagents +- **fix(auth):** tag internal/loopback-origin failed logins in the audit log ([#8606](https://github.com/diegosouzapw/OmniRoute/pull/8606)) — thanks @Prudhvivuda +- **fix(providers):** declare explicit OpenCode plugin feature-flag defaults ([#8608](https://github.com/diegosouzapw/OmniRoute/pull/8608)) — thanks @Prudhvivuda +- **fix(ci):** use webpack fallback for Node 26 compat build to stop OOM ([#8611](https://github.com/diegosouzapw/OmniRoute/pull/8611)) — thanks @Prudhvivuda +- **fix(claude):** classify native subscription quota 429 ([#8628](https://github.com/diegosouzapw/OmniRoute/pull/8628)) — thanks @costaeder +- **fix(windows):** request shell when spawning bare qoder binary name on Windows (fixes #8590) ([#8633](https://github.com/diegosouzapw/OmniRoute/pull/8633)) — thanks @Dingding-leo +- **fix(middleware):** declare withInjectionGuard's context parameter optional ([#8644](https://github.com/diegosouzapw/OmniRoute/pull/8644)) — thanks @backryun +- **fix(providers):** handle space-separated search queries via matchesAnyToken ([#8660](https://github.com/diegosouzapw/OmniRoute/pull/8660)) — thanks @maxmad64bis +- **fix(dashboard):** broken icon allignment in `SegmentedControl.tsx` ([#8679](https://github.com/diegosouzapw/OmniRoute/pull/8679)) — thanks @0x2f0 +- **fix(providers):** deprecate Monster API provider (fixes #8676) ([#8691](https://github.com/diegosouzapw/OmniRoute/pull/8691)) — thanks @Dingding-leo +- **fix(quality):** register the #8494 covering test in stryker tap.testFiles ([#8692](https://github.com/diegosouzapw/OmniRoute/pull/8692)) +- **fix(sse):** clamp max_tokens to the model output cap on every path ([#8698](https://github.com/diegosouzapw/OmniRoute/pull/8698)) +- **fix(executors):** pass TimeoutError reason to controller.abort() in 7 niche executors ([#8699](https://github.com/diegosouzapw/OmniRoute/pull/8699)) +- **fix(api):** serve /v1/models stale-first and sanitize its error bodies ([#8703](https://github.com/diegosouzapw/OmniRoute/pull/8703)) +- **fix(sse):** stop thrashing the provider prompt cache for caching-aware clients ([#8705](https://github.com/diegosouzapw/OmniRoute/pull/8705)) +- **fix:** repair five base-red failures on release/v3.8.49 ([#8706](https://github.com/diegosouzapw/OmniRoute/pull/8706)) +- **fix(oauth):** show GitLab Duo setup before authorize error ([#8710](https://github.com/diegosouzapw/OmniRoute/pull/8710)) — thanks @DinonowDev +- **fix:** hydration mismatch, duplicate React keys, and missing ponytail i18n ([#8723](https://github.com/diegosouzapw/OmniRoute/pull/8723)) — thanks @Mananz90 +- **fix(sse):** hide synthetic OpenAI startup reasoning ([#8729](https://github.com/diegosouzapw/OmniRoute/pull/8729)) — thanks @rinseaid +- **fix(guardrails):** check feature flag helper in PIIMasker to honor DB overrides ([#8730](https://github.com/diegosouzapw/OmniRoute/pull/8730)) — thanks @Dingding-leo +- **fix(sse):** report a stream that completes without any content ([#8732](https://github.com/diegosouzapw/OmniRoute/pull/8732)) — thanks @backryun +- **fix(plugins):** delete the generated host script synchronously so plugin loads stop leaking temp files ([#8749](https://github.com/diegosouzapw/OmniRoute/pull/8749)) — thanks @MumuTW +- **fix(sse):** update ANTHROPIC_PING heartbeat data payload to {"type":"ping"} (fixes #8750) ([#8762](https://github.com/diegosouzapw/OmniRoute/pull/8762)) — thanks @Dingding-leo +- **fix(cloudflare-ai):** sync missing free catalog models (fixes #8725) ([#8763](https://github.com/diegosouzapw/OmniRoute/pull/8763)) — thanks @Dingding-leo +- **fix(bedrock):** preserve additionalModelRequestFields in converse payload (fixes #8746) ([#8764](https://github.com/diegosouzapw/OmniRoute/pull/8764)) — thanks @Dingding-leo +- **fix(docs):** use correct kebab-case CLI flags in OpenCode guide (take 2) ([#8766](https://github.com/diegosouzapw/OmniRoute/pull/8766)) — thanks @swingtempo +- **fix(db):** repair the extra-migration-dirs test and env contract on CI ([#8773](https://github.com/diegosouzapw/OmniRoute/pull/8773)) +- **fix(electron):** use NEXT_DIST_DIR when stripping stale native modules ([#8794](https://github.com/diegosouzapw/OmniRoute/pull/8794)) — thanks @NBN-N3 +- **fix(resilience):** add UND_ERR_SOCKET to PROXY_UNREACHABLE_ERROR_CODES ([#8795](https://github.com/diegosouzapw/OmniRoute/pull/8795)) — thanks @Dingding-leo +- **fix(combo):** fail open when strict context filter empties unknown-only pools ([#8798](https://github.com/diegosouzapw/OmniRoute/pull/8798)) — thanks @DinonowDev +- **fix(resilience):** honor Cloudflare 1010 retryable:false — skip COOLDOWN_RETRY ([#8800](https://github.com/diegosouzapw/OmniRoute/pull/8800)) — thanks @DinonowDev +- **fix(dashboard):** restore Usage Model Breakdown column sorting ([#8802](https://github.com/diegosouzapw/OmniRoute/pull/8802)) — thanks @DinonowDev +- **fix(api):** treat cx/* and codex/* as equivalent API-key model permissions ([#8805](https://github.com/diegosouzapw/OmniRoute/pull/8805)) — thanks @Prudhvivuda +- **fix(sse):** pass real response payload into plugin onResponse hooks ([#8806](https://github.com/diegosouzapw/OmniRoute/pull/8806)) — thanks @Prudhvivuda +- **fix(types):** export web executor types from their module ([#8810](https://github.com/diegosouzapw/OmniRoute/pull/8810)) — thanks @backryun +- **fix(types):** preserve reasoning policy record shapes ([#8811](https://github.com/diegosouzapw/OmniRoute/pull/8811)) — thanks @backryun +- **fix(types):** preserve compression detail config shapes ([#8812](https://github.com/diegosouzapw/OmniRoute/pull/8812)) — thanks @backryun +- **fix(types):** declare virtual chaos combo config ([#8815](https://github.com/diegosouzapw/OmniRoute/pull/8815)) — thanks @backryun +- **fix(types):** type memory skills injection logger ([#8816](https://github.com/diegosouzapw/OmniRoute/pull/8816)) — thanks @backryun +- **fix(types):** align web fallback contracts ([#8819](https://github.com/diegosouzapw/OmniRoute/pull/8819)) — thanks @backryun +- **fix(types):** declare idempotency input contracts ([#8820](https://github.com/diegosouzapw/OmniRoute/pull/8820)) — thanks @backryun +- **fix(reasoning):** sanitize streamed K3 think tags ([#8821](https://github.com/diegosouzapw/OmniRoute/pull/8821)) — thanks @rinseaid +- **fix(types):** normalize Kie transcription results ([#8824](https://github.com/diegosouzapw/OmniRoute/pull/8824)) — thanks @backryun +- **fix(dashboard):** surface quota pool delete failures instead of failing silently ([#8829](https://github.com/diegosouzapw/OmniRoute/pull/8829)) +- **fix(autoCombo):** normalize -free suffix in task fitness lookups ([#8636](https://github.com/diegosouzapw/OmniRoute/pull/8636)) — thanks @Dingding-leo +- **fix(sse):** split the reasoning-decision guards so the error arm actually narrows ([#8641](https://github.com/diegosouzapw/OmniRoute/pull/8641)) — thanks @backryun +- **fix(openai-to-claude):** skip empty reasoning_content string deltas ([#8642](https://github.com/diegosouzapw/OmniRoute/pull/8642)) — thanks @Dingding-leo +- **fix(autoCombo):** match longest pattern first in lookupStaticFitnessTable ([#8651](https://github.com/diegosouzapw/OmniRoute/pull/8651)) — thanks @Dingding-leo +- **fix(providers):** sync search query to URL query param ([#8652](https://github.com/diegosouzapw/OmniRoute/pull/8652)) — thanks @Dingding-leo +- **fix(maritalk):** refresh supported model catalog ([#8663](https://github.com/diegosouzapw/OmniRoute/pull/8663)) — thanks @backryun +- **fix(agentSkills):** scope command slice before nested subcommands to prevent flag mis-attribution ([#8667](https://github.com/diegosouzapw/OmniRoute/pull/8667)) — thanks @Dingding-leo +- **fix(guardrails):** ensure request PII masking respects DB feature flag overrides ([#8715](https://github.com/diegosouzapw/OmniRoute/pull/8715)) — thanks @Dingding-leo +- **fix(reasoning):** sanitize Kimi Code K3 think tags ([#8721](https://github.com/diegosouzapw/OmniRoute/pull/8721)) — thanks @rinseaid +- **fix(sse):** clamp out-of-range Gemini thinking_budget and learn the cap ([#8726](https://github.com/diegosouzapw/OmniRoute/pull/8726)) — thanks @fuko2935 +- **fix(providers):** support multi-token search in provider filter ([#8731](https://github.com/diegosouzapw/OmniRoute/pull/8731)) — thanks @Dingding-leo +- **fix(api):** stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) [recovered from #8599] ([#8740](https://github.com/diegosouzapw/OmniRoute/pull/8740)) +- **fix(quality):** let --update remove baseline entries that already fit the cap ([#8741](https://github.com/diegosouzapw/OmniRoute/pull/8741)) — thanks @MumuTW +- **fix:** escape angle brackets in i18n messages to prevent next-intl INVALID_MESSAGE errors ([#8747](https://github.com/diegosouzapw/OmniRoute/pull/8747)) — thanks @SteeleHu +- **fix(dashboard):** the /home quick-start cards no longer prefetch — #8292 opted the sidebar out of automatic route prefetch but left the landing page's own five links untouched, so first paint still fired 12 speculative RSC requests. The e2e guard shipped in that same PR could not catch it: it hung in the auth helper and never reached its assertion until this release's CI. +- **fix(dashboard):** Request Logs detail no longer crashes on a structured error object — #7920 introduced `formatErrorForDisplay` for exactly this, but the combo-503 / cooldown checks added by #8213 read the raw field and called `.toLowerCase()` on it. Both paths now share the helper. +- **fix(dashboard):** the logs detail modal stops reopening on first close again — #6830 fixed it by reading the deep-link id once, and the #8354 page rewrite regressed it by reading the live `searchParams` on every render, flipping the prop mid-session. ### 📚 Docs - **docs(quality):** codify retry policy per runner + release-level drift rule (WS5.4/WS5.5) ([#7107](https://github.com/diegosouzapw/OmniRoute/pull/7107)) @@ -1053,6 +1186,17 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **docs(ops):** publish public branching and release model (#7627) ([#8129](https://github.com/diegosouzapw/OmniRoute/pull/8129)) — thanks @c4usal - **docs(i18n):** full Russian README rewrite ([#8217](https://github.com/diegosouzapw/OmniRoute/pull/8217)) — thanks @MonteNegroX - **docs(readme):** re-audit numbers, fix table scroll, refresh contributors ([#8243](https://github.com/diegosouzapw/OmniRoute/pull/8243)) +- **docs(db):** propose pluggable persistence boundary ([#8261](https://github.com/diegosouzapw/OmniRoute/pull/8261)) — thanks @xiaoyaner0201 +- **docs(db):** add reproducible SQLite coupling inventory ([#8262](https://github.com/diegosouzapw/OmniRoute/pull/8262)) — thanks @xiaoyaner0201 +- **docs:** add public ROADMAP (3.8.5x rail -> 3.9.0 LTS -> 4.0 modular platform) ([#8348](https://github.com/diegosouzapw/OmniRoute/pull/8348)) +- **docs:** sync env-var contract (chaos panel, notion TLS, grok auth path) + repair glued VNC line in .env.example ([#8362](https://github.com/diegosouzapw/OmniRoute/pull/8362)) +- **docs:** one golden path across PR template, CONTRIBUTING, GEMINI, AGENTS + CI milestones in ROADMAP ([#8380](https://github.com/diegosouzapw/OmniRoute/pull/8380)) +- **docs(claude-code):** document unprefixed model IDs and the Ambiguous model error ([#8410](https://github.com/diegosouzapw/OmniRoute/pull/8410)) — thanks @dvirarad +- **docs(podman):** clarify Podman Machine deployment ([#8569](https://github.com/diegosouzapw/OmniRoute/pull/8569)) — thanks @shixi-li +- **docs(env):** document NEXT_PUBLIC_OMNIROUTE_BASE_PATH and OMNIROUTE_BACKUP_SCHEDULE_JOB_INTERVAL_MS ([#8690](https://github.com/diegosouzapw/OmniRoute/pull/8690)) — thanks @MumuTW +- **docs(codex):** document session affinity and stream idle for long tasks ([#8709](https://github.com/diegosouzapw/OmniRoute/pull/8709)) — thanks @DinonowDev +- **docs:** replace outdated Polish docs with translation from latest English ([#8823](https://github.com/diegosouzapw/OmniRoute/pull/8823)) — thanks @leszek3737 +- **docs:** restore the Polish API_REFERENCE removed by #8823 ([#8831](https://github.com/diegosouzapw/OmniRoute/pull/8831)) ### 🧪 Tests & Quality - **test(build):** derive pack-artifact closures for all npm-shipped entrypoints (#7065 class) ([#7081](https://github.com/diegosouzapw/OmniRoute/pull/7081)) @@ -1065,6 +1209,11 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **test(codex):** cover image tool output replay (#7698) ([#7704](https://github.com/diegosouzapw/OmniRoute/pull/7704)) — thanks @dongwook-chan - **test(security):** exact SAN-entry match in mitm leaf-cert test (CodeQL #746) ([#7824](https://github.com/diegosouzapw/OmniRoute/pull/7824)) - **test(#8140):** verify keepalive interval cleanup on disconnect, resolve, and reject ([#8190](https://github.com/diegosouzapw/OmniRoute/pull/8190)) — thanks @rafaumeu +- **test:** realign catalog snapshot tests to current deliberate catalog state ([#8386](https://github.com/diegosouzapw/OmniRoute/pull/8386)) +- **test:** hermetic notion thread-session mocks + drop duplicated usage-analytics suite ([#8392](https://github.com/diegosouzapw/OmniRoute/pull/8392)) +- **test(e2e):** contract test for the full provider journey ([#8444](https://github.com/diegosouzapw/OmniRoute/pull/8444)) — thanks @HoneyTyagii +- **test(sse):** repair two base-red gates on release/v3.8.49 ([#8490](https://github.com/diegosouzapw/OmniRoute/pull/8490)) — thanks @backryun +- **test(context):** isolate context-manager suite from local DATA_DIR ([#8596](https://github.com/diegosouzapw/OmniRoute/pull/8596)) — thanks @DinonowDev ### 🔧 Chores / CI - **chore(release):** gate the sync-back push on release-green --quick (WS0.3) ([#7083](https://github.com/diegosouzapw/OmniRoute/pull/7083)) @@ -1103,6 +1252,58 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - **chore(dashboard):** reframe Kimi partnership as "Open Source Friends" ([#8117](https://github.com/diegosouzapw/OmniRoute/pull/8117)) - **chore(quality):** fix 2 pre-existing lint/suppression drift issues ([#8209](https://github.com/diegosouzapw/OmniRoute/pull/8209)) — thanks @hartmark - **chore:** add K3banner-1.png banner asset ([#8242](https://github.com/diegosouzapw/OmniRoute/pull/8242)) +- **chore(quality):** rebaseline accountFallback+combo for #8252 own-growth (post-merge follow-up) ([#8252](https://github.com/diegosouzapw/OmniRoute/pull/8252)) — thanks @RaviTharuma +- **optimize(chaos+ponytail):** i18n ponytail, dedupl dispatch, provider diversity ([#8264](https://github.com/diegosouzapw/OmniRoute/pull/8264)) — thanks @Moseyuh333 +- **chore(deps):** bump next to 16.2.11 (9 security advisories) ([#8265](https://github.com/diegosouzapw/OmniRoute/pull/8265)) +- **chore:** Add Alibaba-family media model support ([#8266](https://github.com/diegosouzapw/OmniRoute/pull/8266)) — thanks @backryun +- **chore:** Clicking a provider card hitting back loses scroll position ([#8349](https://github.com/diegosouzapw/OmniRoute/pull/8349)) — thanks @swingtempo +- **chore:** feat(log): Added new visual scrolling log page ([#8354](https://github.com/diegosouzapw/OmniRoute/pull/8354)) — thanks @hartmark +- **chore:** [BUG] enforceOutputTokenBudget ignores combo-resolved context limit, silently truncates responses ([#8378](https://github.com/diegosouzapw/OmniRoute/pull/8378)) — thanks @RCrushMe +- **chore(ci):** cancel superseded runs, skip DAST on docs-only PRs, persist TIA shadow evidence ([#8379](https://github.com/diegosouzapw/OmniRoute/pull/8379)) +- **chore(quality):** drop stale muse-spark-web allowlist entry + sync sidebar order snapshots ([#8383](https://github.com/diegosouzapw/OmniRoute/pull/8383)) +- **chore:** i18n(zh-TW): translate missing Reasoning Routing strings ([#8423](https://github.com/diegosouzapw/OmniRoute/pull/8423)) — thanks @MumuTW +- **chore(deps):** bump codecov/codecov-action from 5.5.5 to 7.0.0 ([#8452](https://github.com/diegosouzapw/OmniRoute/pull/8452)) +- **chore(deps):** bump github/codeql-action/analyze from 4.37.1 to 4.37.3 ([#8453](https://github.com/diegosouzapw/OmniRoute/pull/8453)) +- **chore(deps):** bump ossf/scorecard-action from 2.4.3 to 2.4.4 ([#8454](https://github.com/diegosouzapw/OmniRoute/pull/8454)) +- **chore(deps):** bump github/codeql-action/init from 4.37.1 to 4.37.3 ([#8455](https://github.com/diegosouzapw/OmniRoute/pull/8455)) +- **chore(deps):** bump actions/setup-python from 6 to 7 ([#8456](https://github.com/diegosouzapw/OmniRoute/pull/8456)) +- **chore(sse):** drop deprecated baseUrl from open-sse tsconfig for TS 7.0 ([#8473](https://github.com/diegosouzapw/OmniRoute/pull/8473)) — thanks @backryun +- **refactor(sse):** resolve open-sse utils/translator type diagnostics for TS 7 ([#8483](https://github.com/diegosouzapw/OmniRoute/pull/8483)) — thanks @backryun +- **refactor(sse):** declare the executor execute() result contract ([#8489](https://github.com/diegosouzapw/OmniRoute/pull/8489)) — thanks @backryun +- **refactor(sse):** stop three executors shadowing BaseExecutor.buildHeaders ([#8498](https://github.com/diegosouzapw/OmniRoute/pull/8498)) — thanks @backryun +- **refactor(sse):** narrow three result unions via type predicates ([#8499](https://github.com/diegosouzapw/OmniRoute/pull/8499)) — thanks @backryun +- **refactor(sse):** restore three executor types the runtime already relied on ([#8520](https://github.com/diegosouzapw/OmniRoute/pull/8520)) — thanks @backryun +- **refactor(dashboard):** clear file-size base-red by extracting provider-card highlight wiring ([#8524](https://github.com/diegosouzapw/OmniRoute/pull/8524)) — thanks @MumuTW +- **refactor(guardrails):** narrow the documented void return at the dispatch site ([#8525](https://github.com/diegosouzapw/OmniRoute/pull/8525)) — thanks @backryun +- **refactor(sse):** type the rerank response adapter's options parameter ([#8528](https://github.com/diegosouzapw/OmniRoute/pull/8528)) — thanks @backryun +- **refactor(sse):** retag the designer-web result unions with string discriminants ([#8531](https://github.com/diegosouzapw/OmniRoute/pull/8531)) — thanks @backryun +- **refactor(sse):** declare the multipart/gRPC frame bodies as ArrayBuffer-backed ([#8533](https://github.com/diegosouzapw/OmniRoute/pull/8533)) — thanks @backryun +- **chore(ci):** resync stale no-explicit-any suppression count for proxy-registry.test.ts ([#8544](https://github.com/diegosouzapw/OmniRoute/pull/8544)) — thanks @MumuTW +- **chore(usage):** decompose services/usage.ts into per-provider usage/* leaves (999 → 253) ([#8545](https://github.com/diegosouzapw/OmniRoute/pull/8545)) — thanks @MumuTW +- **chore(validation):** decompose providers/validation.ts into validation/* leaves (→ 442) ([#8546](https://github.com/diegosouzapw/OmniRoute/pull/8546)) — thanks @MumuTW +- **chore(token-refresh):** decompose services/tokenRefresh.ts into tokenRefresh/* leaves (999 → 724) ([#8547](https://github.com/diegosouzapw/OmniRoute/pull/8547)) — thanks @MumuTW +- **chore(combo):** extract pure error predicates and quota status helpers to comboPredicates ([#8548](https://github.com/diegosouzapw/OmniRoute/pull/8548)) — thanks @MumuTW +- **chore(i18n):** normalize zh-TW terminology and sync stale README figures ([#8554](https://github.com/diegosouzapw/OmniRoute/pull/8554)) — thanks @MumuTW +- **refactor(sse):** stop isClaudeEventPayload claiming a narrowing it never performs ([#8557](https://github.com/diegosouzapw/OmniRoute/pull/8557)) — thanks @backryun +- **chore(quality):** rebaseline file-size for inherited base growth ([#8561](https://github.com/diegosouzapw/OmniRoute/pull/8561)) — thanks @fenix007 +- **chore(deps):** patch js-yaml + postcss for 2 high Dependabot alerts ([#8572](https://github.com/diegosouzapw/OmniRoute/pull/8572)) +- **refactor(tls):** update TLSClient instantiation to use buildNativeTlsClientOptions across multiple services ([#8583](https://github.com/diegosouzapw/OmniRoute/pull/8583)) — thanks @DinonowDev +- **refactor(sse):** peel the bare Response off handleChatCore's union in responsesHandler ([#8647](https://github.com/diegosouzapw/OmniRoute/pull/8647)) — thanks @backryun +- **refactor(sse):** guard the KIE task-id and callback-url reads at their source ([#8661](https://github.com/diegosouzapw/OmniRoute/pull/8661)) — thanks @backryun +- **refactor(sse):** declare the ArrayBuffer backing on media byte producers ([#8665](https://github.com/diegosouzapw/OmniRoute/pull/8665)) — thanks @backryun +- **merge:** resolve conflicts for #7904 local corpus context ([#8685](https://github.com/diegosouzapw/OmniRoute/pull/8685)) — thanks @terrafirmbot-source (original author of #7904) +- **chore(quality):** update baselines after v3.8.49 merge-train ([#8686](https://github.com/diegosouzapw/OmniRoute/pull/8686)) +- **chore:** Dependabot updates ([#8695](https://github.com/diegosouzapw/OmniRoute/pull/8695)) — thanks @justdoGIT +- **chore:** Create AMIT ([#8727](https://github.com/diegosouzapw/OmniRoute/pull/8727)) — thanks @amitgolan60-coder +- **chore(ci):** add release PR build gate ([#8735](https://github.com/diegosouzapw/OmniRoute/pull/8735)) — thanks @ekinnee +- **chore:** Stabilize Notion web sessions and JSON output ([#8751](https://github.com/diegosouzapw/OmniRoute/pull/8751)) — thanks @0xheycat +- **deps:** bump electron from 43.1.1 to 43.2.0 in /electron ([#8782](https://github.com/diegosouzapw/OmniRoute/pull/8782)) +- **deps:** bump the production group across 1 directory with 18 updates ([#8793](https://github.com/diegosouzapw/OmniRoute/pull/8793)) +- **refactor(sse):** retag the Adobe Firefly IMS token-check union ([#8638](https://github.com/diegosouzapw/OmniRoute/pull/8638)) — thanks @backryun +- **refactor(db):** let the provider-nodes cache keep the row type it already returns ([#8639](https://github.com/diegosouzapw/OmniRoute/pull/8639)) — thanks @backryun +- **refactor(sse):** use the shared ApiKeyMetadata in reasoningRouting instead of a local duck-type ([#8643](https://github.com/diegosouzapw/OmniRoute/pull/8643)) — thanks @backryun +- **refactor(sse):** narrow three media-generation result unions ([#8645](https://github.com/diegosouzapw/OmniRoute/pull/8645)) — thanks @backryun +- **refactor(sse):** declare the semantic-cache read path's parameters ([#8646](https://github.com/diegosouzapw/OmniRoute/pull/8646)) — thanks @backryun ### 🔀 Other - [needs-vps] fix(electron): materialize Turbopack hashed-module symlinks during packaging (#6724, #6594) ([#6794](https://github.com/diegosouzapw/OmniRoute/pull/6794)) — thanks @huohua-dev @@ -1135,6 +1336,8 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 ### 🩹 Direct release-branch fixes (no PR — authorized base-red sweep, 2026-07-18) - **fix(base-red):** full-suite realignment after the 102-PR merge campaign: two real production fixes (legacy `refresh_token` column healed before its index is created; `shouldSkipCloudSyncInitialization` no longer swaps its `(env, argv)` arguments) plus 13 test files, goldens, provider counts, and env docs realigned to the live-validated behavior of the merged PRs. +- **chore(release-branch):** cycle maintenance pushed directly to `release/v3.8.49` with no PR of its own — 19 merge-train landings validated on the `.113` box, 14 quality-ratchet re-pins (file-size / complexity / cognitive) absorbing the drift of the merged batches, 8 base-red realignments (build, oauth, embeddings, security, mitm, combo, antigravity, router-eval), the `changelog.d` aggregation passes and the 42 i18n CHANGELOG mirrors. +- **test(ui):** the `vitest:ui` suite was red across the whole cycle and nobody saw it — the job kept being cancelled by successive pushes, so a blocking gate never ran to completion. Root cause: #7935 instrumented ~180 shared/dashboard components with `next-intl` without updating the tests that mount them. Fixed at the shared setup (`tests/_setup/vitestUiPolyfills.ts`) with a translator backed by the real `en.json`, memoized per namespace so components whose `useCallback`/`useEffect` depend on `t` no longer loop; 15 test files realigned to the real strings. 194→198 files green. ### 📝 Maintenance - **Merge-train script** (`scripts/release/merge-train.sh`): batch-validates N queued PRs as ONE merged result on the runner box — merges every queued PR into a throwaway worktree cut from the release tip, runs the fast-gates parity suite once, and prints the `--admin` evidence block per PR (merge-gates §7). Replaces O(N²) per-PR CI re-runs in merge-storms. Regression guard: `tests/unit/merge-train-plan.test.ts`. ([#6784](https://github.com/diegosouzapw/OmniRoute/pull/6784)) @@ -1235,15 +1438,14 @@ _Living section — regenerated 2026-07-19 from all 306 cycle commits (bump 2c62 - chore(tests): fix all 70 failing `test:vitest:ui` tests across 30 files (was advisory/parked) — root causes were 15 node:test-authored `.tsx` files never collected by vitest, a missing `window.matchMedia` jsdom polyfill, stale assertions against a redesigned BuildTab wizard / CompressionHub Phase-2 UI, and one obsolete test for a retired Plans screen; suite is now 158/158 files, 870/870 tests green (promotion to blocking is a follow-up) - - - ### 🙌 Contributors Thanks to everyone whose work landed in v3.8.49: | Contributor | PRs / Issues | | --- | --- | +| [@0x2f0](https://github.com/0x2f0) | #8679 | +| [@0xheycat](https://github.com/0xheycat) | #8751 | | [@adevwithpurpose](https://github.com/adevwithpurpose) | #8123 | | [@adrianaryaputra](https://github.com/adrianaryaputra) | #7928 | | [@advane204f](https://github.com/advane204f) | direct commit / report | @@ -1251,6 +1453,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@allanvb](https://github.com/allanvb) | #8471, #8759, #8814, #8862 | | [@alltomatos](https://github.com/alltomatos) | #6703, #6715, #6756, #6757, #6759, #6813, #6819, #6821, #7041, #7042, #7164, #7277, #7490, #7492, #7644 | | [@alvaretto](https://github.com/alvaretto) | #8077, #8161, #8170 | +| [@amitgolan60-coder](https://github.com/amitgolan60-coder) | #8727 | | [@andrea-kingautomation](https://github.com/andrea-kingautomation) | #7678 | | [@andrewmunsell](https://github.com/andrewmunsell) | #6774, #6779, #6795 | | [@AndrianBalanescu](https://github.com/AndrianBalanescu) | #6828, #6829, #7794, #7804, #7810, #7813, #7816, #7891, #8050 | @@ -1258,13 +1461,14 @@ Thanks to everyone whose work landed in v3.8.49: | [@anndev-69](https://github.com/anndev-69) | direct commit / report | | [@apoapostolov](https://github.com/apoapostolov) | #8127 | | [@arpit-jaiswal-dev](https://github.com/arpit-jaiswal-dev) | #7881 | -| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8863 | +| [@artickc](https://github.com/artickc) | #6763, #6955, #7204, #7696, #7768, #7896, #7900, #7911, #7930, #7994, #8006, #8159, #8470, #8496, #8511, #8863 | | [@Arul-](https://github.com/Arul-) | #7878 | | [@asynx6](https://github.com/asynx6) | direct commit / report | | [@attid](https://github.com/attid) | #6984 | -| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8298 | +| [@backryun](https://github.com/backryun) | #6280, #6675, #6862, #7296, #7314, #7358, #7531, #7687, #7772, #7812, #7866, #7874, #7882, #7914, #8013, #8225, #8226, #8227, #8230, #8266, #8275, #8298, #8464, #8473, #8483, #8485, #8489, #8490, #8498, #8499, #8520, #8525, #8528, #8531, #8533, #8557, #8638, #8639, #8641, #8643, #8644, #8645, #8646, #8647, #8661, #8663, #8665, #8732, #8810, #8811, #8812, #8815, #8816, #8819, #8820, #8824 | | [@beingshafin](https://github.com/beingshafin) | direct commit / report | | [@brick30llc-ctrl](https://github.com/brick30llc-ctrl) | #6944 | +| [@brunnolouzada](https://github.com/brunnolouzada) | #8581 | | [@c4usal](https://github.com/c4usal) | #7627, #8129 | | [@CahyokPutraDev99](https://github.com/CahyokPutraDev99) | direct commit / report | | [@Capslockb](https://github.com/Capslockb) | #7892 | @@ -1274,35 +1478,41 @@ Thanks to everyone whose work landed in v3.8.49: | [@chitholian](https://github.com/chitholian) | direct commit / report | | [@chy1211](https://github.com/chy1211) | direct commit / report | | [@CitrusIce](https://github.com/CitrusIce) | #6937, #6938 | +| [@costaeder](https://github.com/costaeder) | #8628 | | [@Dan-ex-hub](https://github.com/Dan-ex-hub) | #7743 | | [@danscMax](https://github.com/danscMax) | #7359, #7511, #7517, #7648, #7656, #7672, #7689 | | [@dependabot](https://github.com/dependabot) | #7897, #7898, #8235 | -| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167 | -| [@DinonowDev](https://github.com/DinonowDev) | #8615, #8716 | +| [@Dingding-leo](https://github.com/Dingding-leo) | #7988, #7989, #8162, #8165, #8167, #8283, #8286, #8287, #8633, #8636, #8642, #8651, #8652, #8667, #8691, #8715, #8730, #8731, #8762, #8763, #8764, #8795 | +| [@DinonowDev](https://github.com/DinonowDev) | #8552, #8559, #8583, #8596, #8615, #8709, #8710, #8716, #8798, #8800, #8802 | | [@dionisius95](https://github.com/dionisius95) | direct commit / report | | [@DKotsyuba](https://github.com/DKotsyuba) | #7500 | | [@dongwook-chan](https://github.com/dongwook-chan) | #7574, #7582, #7704 | +| [@Dragost](https://github.com/Dragost) | #8289 | | [@Duongkhanhtool](https://github.com/Duongkhanhtool) | direct commit / report | -| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980 | +| [@dvirarad](https://github.com/dvirarad) | #8410 | +| [@ekinnee](https://github.com/ekinnee) | #7601, #7613, #7614, #7662, #7779, #7927, #7932, #7980, #8735 | | [@enjoyer-hub](https://github.com/enjoyer-hub) | #6647, #7863 | | [@epsilonode](https://github.com/epsilonode) | #8724 | | [@evinjohnn](https://github.com/evinjohnn) | direct commit / report | | [@fajarbossit](https://github.com/fajarbossit) | direct commit / report | | [@felipeleite](https://github.com/felipeleite) | direct commit / report | -| [@fenix007](https://github.com/fenix007) | #7171, #7399 | +| [@fenix007](https://github.com/fenix007) | #7171, #7399, #8306, #8561 | | [@FenjuFu](https://github.com/FenjuFu) | #7942 | | [@floze-the-genius](https://github.com/floze-the-genius) | #7707 | | [@fontvu](https://github.com/fontvu) | direct commit / report | +| [@fuko2935](https://github.com/fuko2935) | #8726 | | [@fzrilsh](https://github.com/fzrilsh) | direct commit / report | | [@gitcommit90](https://github.com/gitcommit90) | #6986 | | [@glazec](https://github.com/glazec) | #8632 | -| [@growab](https://github.com/growab) | #7062 | +| [@growab](https://github.com/growab) | #7062, #7300 | | [@guanbear](https://github.com/guanbear) | #7028 | -| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213 | +| [@guhcostan](https://github.com/guhcostan) | #8433 | +| [@hartmark](https://github.com/hartmark) | #8208, #8209, #8210, #8211, #8212, #8213, #8337, #8341, #8354, #8462 | | [@HassiyYT](https://github.com/HassiyYT) | #7864 | | [@heishen6](https://github.com/heishen6) | direct commit / report | -| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871 | -| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8842, #8845, #8860, #8865 | +| [@herjarsa](https://github.com/herjarsa) | #7612, #7625, #7633, #7869, #7871, #8476 | +| [@HoneyTyagii](https://github.com/HoneyTyagii) | #8444 | +| [@HouMinXi](https://github.com/HouMinXi) | #7035, #7129, #7290, #7398, #7408, #7973, #8290, #8312, #8842, #8845, #8860, #8865 | | [@hppsc1215](https://github.com/hppsc1215) | #7546, #8835 | | [@huohua-dev](https://github.com/huohua-dev) | #6794 | | [@hydraxman](https://github.com/hydraxman) | #7909 | @@ -1315,6 +1525,8 @@ Thanks to everyone whose work landed in v3.8.49: | [@itiwant](https://github.com/itiwant) | direct commit / report | | [@janeza2](https://github.com/janeza2) | #6308 | | [@Jordannst](https://github.com/Jordannst) | direct commit / report | +| [@JoshimOfficial](https://github.com/JoshimOfficial) | #8526 | +| [@justdoGIT](https://github.com/justdoGIT) | #8695 | | [@JxnLexn](https://github.com/JxnLexn) | #6776, #6993, #7154, #7177, #7269, #7273, #7280, #7281, #7282, #7323, #7360, #7377, #7378, #7379, #7380, #7381, #7419, #7607, #7894, #7905, #7912, #8008, #8009, #8010 | | [@kamenkadmitry](https://github.com/kamenkadmitry) | #7350, #7425 | | [@kaon0388v1](https://github.com/kaon0388v1) | #7049 | @@ -1322,24 +1534,30 @@ Thanks to everyone whose work landed in v3.8.49: | [@KooshaPari](https://github.com/KooshaPari) | #6611, #6632, #6856, #7008, #7087, #7093, #7128, #7130, #7136, #7315, #7318, #7334, #7336 | | [@KunN-21](https://github.com/KunN-21) | direct commit / report | | [@leninejunior](https://github.com/leninejunior) | #8049 | -| [@leszek3737](https://github.com/leszek3737) | #7782, #7807 | +| [@leszek3737](https://github.com/leszek3737) | #7782, #7807, #8343, #8543, #8823 | | [@like3213934360-lab](https://github.com/like3213934360-lab) | direct commit / report | +| [@linhdmn](https://github.com/linhdmn) | #8439 | | [@Long-Feeds](https://github.com/Long-Feeds) | #8011 | | [@loulanyue](https://github.com/loulanyue) | #7540 | | [@lucasjustinudin](https://github.com/lucasjustinudin) | direct commit / report | | [@lunkerchen](https://github.com/lunkerchen) | #8024 | -| [@makcimbx](https://github.com/makcimbx) | #7692, #8171 | +| [@makcimbx](https://github.com/makcimbx) | #7692, #8171, #8432 | +| [@Mananz90](https://github.com/Mananz90) | #8723 | +| [@marceli1404](https://github.com/marceli1404) | #8570 | +| [@maxmad64bis](https://github.com/maxmad64bis) | #8660 | | [@megamen32](https://github.com/megamen32) | #7313 | | [@MichaelYcJo](https://github.com/MichaelYcJo) | #8224 | +| [@mikeiagents](https://github.com/mikeiagents) | #8598 | | [@MikeTuev](https://github.com/MikeTuev) | #6586 | | [@mikolaj92](https://github.com/mikolaj92) | #6973 | | [@MisileLab](https://github.com/MisileLab) | #8566 | | [@MonteNegroX](https://github.com/MonteNegroX) | #8217 | -| [@Moseyuh333](https://github.com/Moseyuh333) | #7781 | +| [@Moseyuh333](https://github.com/Moseyuh333) | #7781, #8264 | | [@MrFadiAi](https://github.com/MrFadiAi) | #7073 | | [@mrprohack](https://github.com/mrprohack) | direct commit / report | -| [@MumuTW](https://github.com/MumuTW) | #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657 | +| [@MumuTW](https://github.com/MumuTW) | #8423, #8425, #8426, #8427, #8428, #8524, #8534, #8544, #8545, #8546, #8547, #8548, #8554, #8582, #8585, #8589, #8592, #8604, #8605, #8612, #8619, #8657, #8690, #8741, #8749 | | [@mustafa-phd](https://github.com/mustafa-phd) | #7686 | +| [@NBN-N3](https://github.com/NBN-N3) | #8794 | | [@nguyenha935](https://github.com/nguyenha935) | #7493, #7547, #7552, #7553, #7629, #7935, #8031, #8098, #8233, #8565 | | [@nguyenphi37](https://github.com/nguyenphi37) | direct commit / report | | [@not-knope](https://github.com/not-knope) | #8206 | @@ -1347,32 +1565,36 @@ Thanks to everyone whose work landed in v3.8.49: | [@oyi77](https://github.com/oyi77) | #6917, #6918, #6919, #6920, #6921, #6923, #7032, #7045, #7046, #7066, #7070, #7178, #7719, #7744, #7787, #7893, #8219 | | [@Pitchfork-and-Torch](https://github.com/Pitchfork-and-Torch) | #6747, #6791 | | [@professional-ALFIE](https://github.com/professional-ALFIE) | #6877 | -| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8467, #8488 | +| [@Prudhvivuda](https://github.com/Prudhvivuda) | #8032, #8220, #8250, #8309, #8441, #8467, #8488, #8493, #8494, #8495, #8586, #8587, #8606, #8607, #8608, #8611, #8805, #8806 | | [@QRcode1337](https://github.com/QRcode1337) | #7034 | | [@quanturbo](https://github.com/quanturbo) | #6780 | | [@rafaeldrincon](https://github.com/rafaeldrincon) | #8866, #8867 | | [@rafaumeu](https://github.com/rafaumeu) | #6813, #6979, #6982, #6983, #6987, #6988, #7001, #7808, #7815, #8071, #8113, #8179, #8184, #8185, #8190, #8195, #8196, #8203 | -| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8102, #8124 | -| [@RCrushMe](https://github.com/RCrushMe) | #8151 | +| [@RaviTharuma](https://github.com/RaviTharuma) | #7852, #7853, #7855, #7862, #7885, #7972, #7978, #8021, #8022, #8023, #8025, #8027, #8030, #8101, #8102, #8124, #8252, #8292, #8296, #8301, #8302, #8303, #8304, #8308 | +| [@RCrushMe](https://github.com/RCrushMe) | #8151, #8378 | | [@ricatix](https://github.com/ricatix) | direct commit / report | | [@ridho9](https://github.com/ridho9) | #8310 | +| [@rinseaid](https://github.com/rinseaid) | #8721, #8729, #8821 | | [@rixzkiye](https://github.com/rixzkiye) | direct commit / report | | [@rqzbeh](https://github.com/rqzbeh) | #8514, #8515 | | [@rushsinging](https://github.com/rushsinging) | #7256 | | [@ryanngit](https://github.com/ryanngit) | direct commit / report | | [@samir-abis](https://github.com/samir-abis) | direct commit / report | -| [@seanford](https://github.com/seanford) | #8218, #8232 | +| [@seanford](https://github.com/seanford) | #8194, #8218, #8232 | | [@SeaXen](https://github.com/SeaXen) | #7063, #7264, #7294 | | [@Securiteru](https://github.com/Securiteru) | #7683 | | [@SemonCat](https://github.com/SemonCat) | direct commit / report | +| [@shixi-li](https://github.com/shixi-li) | #8569 | | [@SingCJ](https://github.com/SingCJ) | direct commit / report | | [@skutanjir](https://github.com/skutanjir) | #7865, #7939 | | [@spacesky-cell](https://github.com/spacesky-cell) | direct commit / report | +| [@SteeleHu](https://github.com/SteeleHu) | #8747 | | [@sumanxg](https://github.com/sumanxg) | #8837, #8856 | -| [@swingtempo](https://github.com/swingtempo) | #7790 | +| [@swingtempo](https://github.com/swingtempo) | #7790, #8349, #8766 | | [@Tasogarre](https://github.com/Tasogarre) | #7861, #8207 | | [@techsolutionmta](https://github.com/techsolutionmta) | direct commit / report | | [@tenshiak](https://github.com/tenshiak) | #7274, #7643 | +| [@terrafirmbot-source](https://github.com/terrafirmbot-source) | #8685 | | [@thepigdestroyer](https://github.com/thepigdestroyer) | #7497 | | [@tianrking](https://github.com/tianrking) | #7353 | | [@tientien17](https://github.com/tientien17) | #7841, #7844, #7925 | @@ -1393,7 +1615,7 @@ Thanks to everyone whose work landed in v3.8.49: | [@wilsonicdev](https://github.com/wilsonicdev) | direct commit / report | | [@Witroch4](https://github.com/Witroch4) | #6753, #6762, #6790, #7901, #7902 | | [@XCrag](https://github.com/XCrag) | direct commit / report | -| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122 | +| [@xiaoyaner0201](https://github.com/xiaoyaner0201) | #8122, #8261, #8262 | | [@xier2012](https://github.com/xier2012) | #7036, #7050, #7052, #7053, #7056, #7059, #7060, #7061, #7166, #7299 | | [@xxue-z](https://github.com/xxue-z) | #7098 | | [@xz-dev](https://github.com/xz-dev) | #6323, #6330, #6714, #6727, #7004, #7012, #7027, #7673, #7700, #7747, #7776, #7843 | diff --git a/docs/openapi.yaml b/docs/openapi.yaml index e0c08b53f3..9dfe25f56e 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -49,6 +49,11 @@ tags: description: Provider connection management - name: Provider Nodes description: Provider node configuration + - name: Proxy Subscriptions + description: >- + Operator-supplied proxy subscription links (Karing-style). Nodes are fetched, + parsed, and synced into the provider/account pool on create, refresh, or the + background scheduler tick. - name: API Keys description: API key management - name: Combos @@ -2563,6 +2568,273 @@ paths: "200": description: Ollama model tags + # ─── Proxy Subscriptions ─────────────────────────────────────── + + /api/v1/management/proxy-subscriptions: + get: + tags: [Proxy Subscriptions] + summary: List proxy subscriptions + description: >- + Lists all operator-supplied proxy subscription links. Also starts the + background auto-refresh scheduler (idempotent) so enabled subscriptions + stay in sync. Credentials embedded in `url` are redacted in the response. + security: + - ManagementSessionAuth: [] + responses: + "200": + description: Subscription list + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + $ref: "#/components/schemas/ProxySubscription" + "401": + $ref: "#/components/responses/ManagementAuthenticationRequired" + "403": + $ref: "#/components/responses/ManagementInvalidToken" + post: + tags: [Proxy Subscriptions] + summary: Create a proxy subscription + description: >- + Creates a subscription record. If `mode` is `rule`, at least one entry in + `ruleProviders` is required. `updateIntervalMinutes` defaults to 60 and + `enabled` defaults to `false` when omitted or not exactly `true`. + security: + - ManagementSessionAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name, url] + properties: + name: + type: string + minLength: 1 + url: + type: string + minLength: 1 + mode: + type: string + enum: [global, rule] + default: global + ruleProviders: + type: array + items: + type: string + description: Required (non-empty) when mode is "rule". + localCoreEndpoint: + type: string + nullable: true + updateIntervalMinutes: + type: integer + default: 60 + enabled: + type: boolean + default: false + responses: + "201": + description: Created subscription (url redacted) + content: + application/json: + schema: + $ref: "#/components/schemas/ProxySubscription" + "400": + description: Missing name/url, or ruleProviders empty while mode is "rule" + "401": + $ref: "#/components/responses/ManagementAuthenticationRequired" + "403": + $ref: "#/components/responses/ManagementInvalidToken" + + /api/v1/management/proxy-subscriptions/{id}: + get: + tags: [Proxy Subscriptions] + summary: Get a proxy subscription + security: + - ManagementSessionAuth: [] + parameters: + - $ref: "#/components/parameters/ResourceId" + responses: + "200": + description: Subscription detail (url redacted) + content: + application/json: + schema: + $ref: "#/components/schemas/ProxySubscription" + "401": + $ref: "#/components/responses/ManagementAuthenticationRequired" + "403": + $ref: "#/components/responses/ManagementInvalidToken" + "404": + description: Subscription not found + patch: + tags: [Proxy Subscriptions] + summary: Update a proxy subscription + description: >- + Partial update — only fields present in the body are changed + (name/url/mode/ruleProviders/localCoreEndpoint/updateIntervalMinutes/enabled). + security: + - ManagementSessionAuth: [] + parameters: + - $ref: "#/components/parameters/ResourceId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + url: + type: string + mode: + type: string + enum: [global, rule] + ruleProviders: + type: array + items: + type: string + localCoreEndpoint: + type: string + nullable: true + updateIntervalMinutes: + type: integer + enabled: + type: boolean + responses: + "200": + description: Updated subscription (url redacted) + content: + application/json: + schema: + $ref: "#/components/schemas/ProxySubscription" + "401": + $ref: "#/components/responses/ManagementAuthenticationRequired" + "403": + $ref: "#/components/responses/ManagementInvalidToken" + "404": + description: Subscription not found + delete: + tags: [Proxy Subscriptions] + summary: Delete a proxy subscription + description: Removes the subscription record and unbinds/drops its synced proxy_registry rows. + security: + - ManagementSessionAuth: [] + parameters: + - $ref: "#/components/parameters/ResourceId" + responses: + "200": + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + "401": + $ref: "#/components/responses/ManagementAuthenticationRequired" + "403": + $ref: "#/components/responses/ManagementInvalidToken" + "404": + description: Subscription not found + + /api/v1/management/proxy-subscriptions/{id}/nodes: + get: + tags: [Proxy Subscriptions] + summary: Get a subscription's last-parsed node summary + description: >- + Returns the last-parsed node list without re-fetching the (possibly slow) + subscription URL. + security: + - ManagementSessionAuth: [] + parameters: + - $ref: "#/components/parameters/ResourceId" + responses: + "200": + description: Last-parsed node summary + content: + application/json: + schema: + type: object + properties: + id: + type: string + name: + type: string + mode: + type: string + enum: [global, rule] + enabled: + type: boolean + status: + type: string + enum: [ok, error, empty] + error: + type: string + nullable: true + lastFetchedAt: + type: string + format: date-time + nullable: true + nodes: + type: array + items: {} + "401": + $ref: "#/components/responses/ManagementAuthenticationRequired" + "403": + $ref: "#/components/responses/ManagementInvalidToken" + "404": + description: Subscription not found + + /api/v1/management/proxy-subscriptions/{id}/refresh: + post: + tags: [Proxy Subscriptions] + summary: Refresh a proxy subscription + description: >- + Re-fetches and re-parses the subscription URL, syncs its nodes into + `proxy_registry`, and (re)binds the pool. + security: + - ManagementSessionAuth: [] + parameters: + - $ref: "#/components/parameters/ResourceId" + responses: + "200": + description: Sync result + content: + application/json: + schema: + type: object + properties: + subscriptionId: + type: string + nodes: + type: integer + needsCore: + type: integer + boundProxies: + type: integer + status: + type: string + enum: [ok, error, empty] + error: + type: string + nullable: true + applied: + type: boolean + "401": + $ref: "#/components/responses/ManagementAuthenticationRequired" + "403": + $ref: "#/components/responses/ManagementInvalidToken" + "404": + description: Subscription not found + # ─── Usage & Analytics ───────────────────────────────────────── /api/usage/analytics: @@ -2677,6 +2949,201 @@ paths: "200": description: Updated budget configuration + /api/usage/cache-health: + get: + tags: [Usage] + summary: Get prompt-cache health summary + description: | + Summarizes the `write/read` cache ratio from `call_logs` for a time window: + distribution (p50/p90/p99/max of cache-write tokens), warm/cold/rewrite/uncached + call counts, the "heavy write" outlier share (10x the window median, floored at + 1024 tokens — Anthropic's cache-creation minimum), and a per-model breakdown. + Only successful (`status = 200`) calls with a non-null cache column are counted. + parameters: + - name: range + in: query + schema: + type: string + enum: [1h, 24h, 7d, 30d] + default: 24h + - name: model + in: query + description: Filter to one model or requested-model alias (1-200 chars). + schema: + type: string + minLength: 1 + maxLength: 200 + responses: + "200": + description: Cache health summary for the requested window + content: + application/json: + schema: + type: object + properties: + totalCalls: + type: integer + cacheReadTotal: + type: integer + cacheWriteTotal: + type: integer + writeReadRatio: + type: number + warmCalls: + type: integer + coldCalls: + type: integer + rewriteCalls: + type: integer + uncachedCalls: + type: integer + writeP50: + type: integer + writeP90: + type: integer + writeP99: + type: integer + writeMax: + type: integer + heavyWriteCalls: + type: integer + heavyWriteCallShare: + type: number + heavyWriteTokenShare: + type: number + heavyWriteThreshold: + type: integer + verdict: + type: string + enum: [healthy, degraded, thrash, no-data] + byModel: + type: array + items: + type: object + properties: + model: + type: string + calls: + type: integer + cacheReadTotal: + type: integer + cacheWriteTotal: + type: integer + writeReadRatio: + type: number + heavyWriteCalls: + type: integer + timeRange: + type: string + since: + type: string + format: date-time + truncated: + type: boolean + description: True when the window held more than 5000 rows and only the newest were summarized. + "400": + description: Invalid query parameters + + /api/usage/model-latency-stats: + get: + tags: [Usage] + summary: Get per-model/provider latency statistics + description: >- + Aggregates `usage_history` rows into per-(provider, model) latency stats + (avg/p50/p95/p99, std-dev, TTFT, tokens/sec) over a rolling window. Falls + back from successful-only to all-sample rows when the successful count is + below `minSamples`. + security: + - ManagementSessionAuth: [] + parameters: + - name: windowHours + in: query + schema: + type: number + minimum: 0 + exclusiveMinimum: true + maximum: 720 + default: 24 + - name: minSamples + in: query + schema: + type: integer + minimum: 1 + default: 1 + - name: maxRows + in: query + schema: + type: integer + minimum: 1 + maximum: 50000 + default: 10000 + - name: provider + in: query + schema: + type: string + minLength: 1 + maxLength: 64 + - name: model + in: query + schema: + type: string + minLength: 1 + maxLength: 256 + responses: + "200": + description: Latency stats keyed by provider/model, plus the window used + content: + application/json: + schema: + type: object + properties: + entries: + type: array + items: + type: object + properties: + provider: + type: string + model: + type: string + key: + type: string + totalRequests: + type: integer + successfulRequests: + type: integer + successRate: + type: number + avgLatencyMs: + type: number + p50LatencyMs: + type: number + p95LatencyMs: + type: number + p99LatencyMs: + type: number + latencyStdDev: + type: number + windowHours: + type: number + avgTtftMs: + type: number + avgE2ELatencyMs: + type: number + avgTokensPerSecond: + type: number + windowHours: + type: number + generatedAt: + type: string + format: date-time + "400": + description: Invalid query parameters + "401": + $ref: "#/components/responses/ManagementAuthenticationRequired" + "403": + $ref: "#/components/responses/ManagementInvalidToken" + # ─── Pricing ─────────────────────────────────────────────────── /api/pricing: @@ -4097,6 +4564,49 @@ paths: "200": description: Session cleared + /api/auth/oidc/login: + get: + tags: [System] + summary: Start OIDC login for the dashboard admin gate + description: | + Builds an authorization URL from the configured OIDC issuer/client (discovered + via `{issuer}/.well-known/openid-configuration`, falling back to `{issuer}/authorize`), + sets a short-lived `oidc_state` cookie, and redirects the browser. Password login + remains available as a fallback while OIDC is enabled. + responses: + "302": + description: Redirect to the identity provider's authorization endpoint + "400": + description: OIDC is not configured (missing issuer, client id/secret, or disabled) + + /api/auth/oidc/callback: + get: + tags: [System] + summary: Complete OIDC login for the dashboard admin gate + description: | + Validates the `state` cookie, exchanges the authorization `code` for tokens, + verifies the ID token against the issuer's JWKS (audience = client id), and — + if `oidcAllowedSubjects` is configured — checks the token's `sub`/`email` against + that allowlist. On success it mints the same 30-day `auth_token` dashboard-session + JWT used by password login and redirects to `/dashboard`. + parameters: + - name: code + in: query + required: true + schema: + type: string + - name: state + in: query + required: true + schema: + type: string + responses: + "302": + description: >- + Redirect to `/dashboard` on success, or to + `/login?oidc_error={missing_code|invalid_state|not_configured|token_exchange|token_response|no_id_token|subject_not_allowed|id_token_invalid|server_misconfigured}` + on failure. + /api/init: get: tags: [System] @@ -7181,6 +7691,61 @@ components: owned_by: type: string + ProxySubscription: + type: object + description: >- + An operator-supplied proxy subscription link (Karing-style). `url` is + redacted (credentials stripped) whenever the record is returned by the API. + properties: + id: + type: string + name: + type: string + url: + type: string + description: Redacted subscription URL. + enabled: + type: boolean + mode: + type: string + enum: [global, rule] + ruleProviders: + type: array + items: + type: string + nullable: true + localCoreEndpoint: + type: string + nullable: true + updateIntervalMinutes: + type: integer + lastFetchedAt: + type: string + format: date-time + nullable: true + status: + type: string + enum: [ok, error, empty] + error: + type: string + nullable: true + lastNodes: + type: array + items: {} + nullable: true + lastErrorAt: + type: string + format: date-time + nullable: true + consecutiveFailures: + type: integer + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + ProviderConnection: type: object properties: diff --git a/docs/reference/API_REFERENCE.md b/docs/reference/API_REFERENCE.md index fbf41ea286..3f3e6467a0 100644 --- a/docs/reference/API_REFERENCE.md +++ b/docs/reference/API_REFERENCE.md @@ -532,6 +532,8 @@ Response example: | `/api/usage/request-logs` | GET | Request-level logs | | `/api/usage/[connectionId]` | GET | Per-connection usage | | `/api/usage/token-limits` | GET/POST/DELETE | Per-API-key token-limit budgets | +| `/api/usage/model-latency-stats` | GET | Rolling per-provider/model latency aggregate (avg/p50/p95/p99, success rate); filters: `windowHours`/`minSamples`/`maxRows`/`provider`/`model` (#6873) | +| `/api/usage/cache-health` | GET | Prompt-cache health summary over `call_logs` — write/read ratio, p50/p90/p99 write-size distribution, heavy-write concentration, per-model split, and a `healthy`/`degraded`/`thrash`/`no-data` verdict; query params `range` (`1h`\|`24h`\|`7d`\|`30d`, default `24h`) and optional `model` (#8827) | ### Settings diff --git a/docs/reference/PROVIDER_REFERENCE.md b/docs/reference/PROVIDER_REFERENCE.md index 6e25e6b8e0..f8b776e976 100644 --- a/docs/reference/PROVIDER_REFERENCE.md +++ b/docs/reference/PROVIDER_REFERENCE.md @@ -1,14 +1,14 @@ --- title: "Provider Reference" -version: 3.8.49 -lastUpdated: 2026-07-23 +version: 3.8.50 +lastUpdated: 2026-07-30 --- # Provider Reference > **Auto-generated** from `src/shared/constants/providers.ts` — do not edit by hand. > Regenerate with: `npm run gen:provider-reference` -> **Last generated:** 2026-07-23 +> **Last generated:** 2026-07-30 Total providers: **290**. See category breakdown below. @@ -49,7 +49,7 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each | `devin-cli` | `dv` | Devin CLI (Official) | OAuth | [link](https://cli.devin.ai) | Requires the Devin CLI binary. Run `devin auth login` to authenticate, or provide your WINDSURF_API_KEY. Install: https://cli.devin.ai | | `ghe-copilot` | `ghe-copilot` | GitHub Enterprise Copilot | OAuth | — | Enter your GHE instance URL (e.g., https://ghe.company.com) in provider settings, then authenticate via device flow. | | `github` | `gh` | GitHub Copilot | OAuth | — | — | -| `gitlab-duo` | `gitlab-duo` | GitLab Duo | OAuth | [link](https://docs.gitlab.com/user/duo_agent_platform/code_suggestions/) | OAuth application with ai_features + read_user scopes. Configure GITLAB_DUO_OAUTH_CLIENT_ID and optionally GITLAB_DUO_OAUTH_CLIENT_SECRET on this OmniRoute instance. | +| `gitlab-duo` | `gitlab-duo` | GitLab Duo | OAuth | [link](https://docs.gitlab.com/user/duo_agent_platform/code_suggestions/) | GitLab Duo OAuth is not configured. Register an OAuth application at https://gitlab.com/-/profile/applications with redirect URI http://localhost:20128/callback and scopes "ai_features read_user", then set GITLAB_DUO_OAUTH_CLIENT_ID (and optionally GITLAB_DUO_OAUTH_CLIENT_SECRET) and restart. | | `grok-cli` | `gc` | Grok Build | OAuth | — | Sign in with your browser, or paste your ~/.grok/auth.json (or the JWT access token) from the Grok Build CLI; refresh_token is rotated automatically either way. | | `kilocode` | `kc` | Kilo Code | OAuth | — | — | | `kimi-coding` | `kmc` | Kimi Code CLI | OAuth | [link](https://www.kimi.com/code?aff=omniroute) | Sign in with the same Kimi account used by Kimi Code CLI. OmniRoute uses the CLI OAuth flow and Kimi Coding Plan endpoints. | @@ -155,7 +155,6 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each | `fal-ai` | `fal` | Fal.ai | API key, image | [link](https://fal.ai) | — | | `featherless-ai` | `featherless` | Featherless AI | API key | [link](https://featherless.ai) | Free tier available — no credit card required | | `fenayai` | `fenayai` | FenayAI | API key, aggregator | [link](https://fenayai.com) | Bearer API key for the FenayAI OpenAI-compatible gateway. | -| `firecrawl` | `fc` | Firecrawl | API key | [link](https://firecrawl.dev) | — | | `fireworks` | `fireworks` | Fireworks AI | API key | [link](https://fireworks.ai) | $1 free starter credits on signup for API testing | | `freeaiapikey` | `faik` | FreeAIAPIKey | API key | [link](https://freeaiapikey.com) | — | | `freemodel-dev` | `fmd` | FreeModel.dev | API key | [link](https://freemodel.dev) | $300 free credits on signup — no credit card required. Access GPT-5.4 and GPT-5.5 (OpenAI's latest flagship models) through an OpenAI-compatible API. | @@ -293,6 +292,7 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each | `x5lab` | `x5lab` | X5Lab | API key | [link](https://x5lab.dev) | Use your X5Lab API key (x5-...) in Authorization: Bearer . Fully OpenAI-compatible. API base URL: https://api.x5lab.dev/v1. | | `xai` | `xai` | xAI (Grok) | API key | [link](https://x.ai) | — | | `xiaomi-mimo` | `mimo` | Xiaomi MiMo | API key | [link](https://mimo.mi.com) | — | +| `xiaomi-mimo-token-plan` | `mimotp` | Xiaomi MiMo Token Plan | API key | [link](https://mimo.mi.com) | — | | `yi` | `yi` | Yi (01.AI) | API key | [link](https://01.ai) | Get API key at platform.lingyiwanwu.com | | `zai` | `zai` | Z.AI | API key | [link](https://open.bigmodel.cn) | — | | `zenmux` | `zm` | ZenMux | API key | [link](https://zenmux.ai) | Use your ZenMux API key in Authorization: Bearer . ZenMux is fully OpenAI-compatible. Base URL: https://zenmux.ai/api/v1. | @@ -314,12 +314,13 @@ Use the dashboard at `/dashboard/providers` to enable, configure, and test each | `vllm` | `vllm` | vLLM | Local, self-hosted | [link](https://github.com/vllm-project/vllm) | API key optional. Configure the local vLLM OpenAI-compatible base URL (default: http://localhost:8000/v1). | | `xinference` | `xinference` | XInference | Local, self-hosted | [link](https://inference.readthedocs.io) | API key optional. Configure the local XInference OpenAI-compatible base URL (default: http://localhost:9997/v1). | -## Search Providers (11) +## Search Providers (12) | ID | Alias | Name | Tags | Website | Notes | |----|-------|------|------|---------|-------| | `brave-search` | `brave-search` | Brave Search | Search | [link](https://brave.com/search/api) | Subscription token from Brave Search API dashboard | | `exa-search` | `exa-search` | Exa Search | Search | [link](https://exa.ai) | API key from dashboard.exa.ai | +| `firecrawl` | `fc` | Firecrawl | Search | [link](https://firecrawl.dev) | — | | `google-pse-search` | `google-pse` | Google Programmable Search | Search | [link](https://developers.google.com/custom-search/v1/overview) | Requires a Google API key and your Programmable Search Engine ID (cx) | | `linkup-search` | `linkup` | Linkup Search | Search | [link](https://docs.linkup.so) | Bearer API key from the Linkup dashboard | | `ollama-search` | `ollama-search` | Ollama Search | Search | [link](https://ollama.com/settings/keys) | Same API key as Ollama Cloud (from ollama.com/settings/keys) | diff --git a/docs/routing/AUTO-COMBO.md b/docs/routing/AUTO-COMBO.md index 424926507a..948cd255fa 100644 --- a/docs/routing/AUTO-COMBO.md +++ b/docs/routing/AUTO-COMBO.md @@ -161,11 +161,11 @@ The detection helper lives in `src/lib/combos/modelNameCollision.ts`. ## How It Works (Persisted Auto-Combos) -The Auto-Combo Engine dynamically selects the best provider/model for each request using a **12-factor scoring function** (defined in `open-sse/services/autoCombo/scoring.ts` → `DEFAULT_WEIGHTS`). All weights sum to **1.0**. +The Auto-Combo Engine dynamically selects the best provider/model for each request using a **13-factor scoring function** (defined in `open-sse/services/autoCombo/scoring.ts` → `DEFAULT_WEIGHTS`). All weights sum to **1.0**. ![Auto-Combo 12-factor scoring](../diagrams/exported/auto-combo-12factor.svg) -> Source: [diagrams/auto-combo-12factor.mmd](../diagrams/auto-combo-12factor.mmd) (regenerate via `npm run docs:render-diagrams`). +> Source: [diagrams/auto-combo-12factor.mmd](../diagrams/auto-combo-12factor.mmd) (regenerate via `npm run docs:render-diagrams`). Diagram/filename predate the `cacheAffinity` factor added by #8008 and still show 12 factors. | Factor | Default Weight | Description | | :-------------------- | :------------- | :------------------------------------------------------------------------------------------------- | @@ -180,9 +180,10 @@ The Auto-Combo Engine dynamically selects the best provider/model for each reque | `specificityMatch` | 0.05 | Match between request specificity (manifest hint) and model tier | | `contextAffinity` | 0.05 | Affinity between the request's context-window need and the model's context window | | `connectionDensity` | 0.05 | Spreads load across connections of the same provider (anti-concentration) | +| `cacheAffinity` | 0.00 | Rendezvous-hash affinity toward the connection likeliest to already hold this request's prompt-cache prefix (`open-sse/services/combo/promptCacheAffinity.ts`); disabled by default (#8008) | | `resetWindowAffinity` | 0.00 | Bias toward connections whose quota reset window is favorable (disabled by default) | -**Sum:** `0.20 + 0.15 + 0.15 + 0.12 + 0.08 + 0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.00 = 1.0` (validated by `validateWeights()`). +**Sum:** `0.20 + 0.15 + 0.15 + 0.12 + 0.08 + 0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.00 + 0.00 = 1.0` (validated by `validateWeights()`). ## Mode Packs @@ -237,7 +238,7 @@ resolved values feed the engine's existing `config.modePack` / `config.budgetCap ## All Routing Strategies -OmniRoute's combo engine supports **18 routing strategies** (declared in `src/shared/constants/routingStrategies.ts` → `ROUTING_STRATEGY_VALUES`). The Auto Combo engine itself is exposed under the `auto` strategy; the others are available for persisted combos. +OmniRoute's combo engine supports **19 routing strategies** (declared in `src/shared/constants/routingStrategies.ts` → `ROUTING_STRATEGY_VALUES`). The Auto Combo engine itself is exposed under the `auto` strategy; the others are available for persisted combos. | Strategy | Description | | :------------------ | :--------------------------------------------------------------------------------------------------------------------------- | @@ -257,6 +258,7 @@ OmniRoute's combo engine supports **18 routing strategies** (declared in `src/sh | `auto` | Use Auto Combo scoring (9-factor) — **recommended** | | `lkgp` | Last-Known-Good Path (sticky route to last successful target) | | `context-optimized` | Pick target with best fit for current context size | +| `cache-optimized` | Reorder targets by prompt-cache affinity — the connection likeliest to already hold this request's cached prefix is tried first (`open-sse/services/combo/promptCacheAffinity.ts`, #8008) | | `fusion` 🧬 | Fan out to a panel of models in parallel, then synthesize one answer via a judge (see below) | | `pipeline` | Run targets sequentially, threading each step's output into the next step's input; only the final answer is returned (#6396) | @@ -715,5 +717,5 @@ intentionally excluded from CI because they require live credentials and VPS acc | `open-sse/services/autoCombo/autoPrefix.ts` | `auto/` prefix parser + 6 variants | | `open-sse/services/autoCombo/virtualFactory.ts` | Builds in-memory `AutoComboConfig` from live connections | | `open-sse/services/autoCombo/providerRegistryAccessor.ts` | Test hook for mocking provider registry | -| `src/shared/constants/routingStrategies.ts` | `ROUTING_STRATEGY_VALUES` (18 strategies) | +| `src/shared/constants/routingStrategies.ts` | `ROUTING_STRATEGY_VALUES` (19 strategies) | | `src/sse/handlers/chat.ts` | Integration: auto-prefix short-circuit | diff --git a/docs/security/GUARDRAILS.md b/docs/security/GUARDRAILS.md index 9653207129..68252680c4 100644 --- a/docs/security/GUARDRAILS.md +++ b/docs/security/GUARDRAILS.md @@ -20,14 +20,15 @@ request. Blocking is an explicit decision (`block: true`), never an accident. ## Built-in Guardrails -The registry auto-loads three guardrails in priority order on import +The registry auto-loads four guardrails in priority order on import (see `registry.ts` → `registerDefaultGuardrails()`): -| Priority | Name | Stage(s) | File | -| -------- | ------------------ | -------------- | -------------------- | -| `5` | `vision-bridge` | `preCall` | `visionBridge.ts` | -| `10` | `pii-masker` | `pre` + `post` | `piiMasker.ts` | -| `20` | `prompt-injection` | `preCall` | `promptInjection.ts` | +| Priority | Name | Stage(s) | File | +| -------- | -------------------- | -------------- | --------------------- | +| `5` | `vision-bridge` | `preCall` | `visionBridge.ts` | +| `10` | `pii-masker` | `pre` + `post` | `piiMasker.ts` | +| `20` | `prompt-injection` | `preCall` | `promptInjection.ts` | +| `95` | `credential-masker` | `pre` + `post` | `credentialMasker.ts` | Lower priority numbers run **first**. @@ -118,6 +119,36 @@ the pattern loop. Injection directives sit near the top of an input, so this caps regex CPU/GC on multi-hundred-KB payloads without weakening detection (cf. #3932, #4041). +### Credential Masker (`credentialMasker.ts`) + +Runs on **both** stages, last in the default chain (priority `95`). Redacts +well-known API-key / secret-token patterns from the outbound payload (message +content, tool-call arguments, tool results) **and** the provider response, so a +credential pasted into a prompt (or echoed back by a tool result) is not leaked +to the upstream provider or back to the client. + +- **Opt-in only**, same convention as PII redaction (Hard Rule #20-adjacent): + disabled unless `settings.credentialRedactionEnabled === true` **or** + `CREDENTIAL_REDACTION_ENABLED=true`. With it off, the guardrail is a no-op — + it never blocks and never rewrites. +- `redactCredentials()` walks the full payload/response tree (`walkValue()`, + prototype-pollution-safe, cycle-safe via `WeakSet`) and replaces matches with + a `[REDACTED:]` placeholder, cloning only the branches that actually + changed. +- `CREDENTIAL_PATTERNS` covers LLM provider keys (OpenAI, OpenAI-proj, + Anthropic, Google, Hugging Face, Replicate), VCS/SaaS tokens (GitHub, Slack, + Linear, Notion, npm, Postman, Discord), payment keys (Stripe, Square), cloud + keys (AWS access key, Twilio, SendGrid, Mailgun), private keys / JWTs, + credential-bearing connection strings (`mongodb://user:pass@...`, etc.), and + a generic `Authorization`/`x-api-key`/`api-key`/`apikey` header-value + pattern. Header-shaped keys (`authorization`, `x-api-key`, `api-key`, + `apikey`) are redacted structurally (value only, scheme prefix like + `Bearer `/`Basic ` preserved) rather than via the generic text regex. +- The guardrail never blocks; it only rewrites (`modifiedPayload` / + `modifiedResponse`) and annotates (`meta.credentialsRedacted`, `meta.count`). + +Regression guard: `tests/unit/credential-masker-guardrail.test.ts`. + ## Base Contract (`base.ts`) ```typescript diff --git a/electron/package-lock.json b/electron/package-lock.json index d6652351fb..fc70141ce1 100644 --- a/electron/package-lock.json +++ b/electron/package-lock.json @@ -297,6 +297,45 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@electron/windows-sign": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.2.tgz", + "integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "peer": true, + "dependencies": { + "cross-dirname": "^0.1.0", + "debug": "^4.3.4", + "fs-extra": "^11.1.1", + "minimist": "^1.2.8", + "postject": "^1.0.0-alpha.6" + }, + "bin": { + "electron-windows-sign": "bin/electron-windows-sign.js" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@electron/windows-sign/node_modules/fs-extra": { + "version": "11.3.6", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.6.tgz", + "integrity": "sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", @@ -1091,6 +1130,15 @@ "dev": true, "license": "MIT" }, + "node_modules/cross-dirname": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cross-dirname/-/cross-dirname-0.1.0.tgz", + "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1411,6 +1459,19 @@ "node": ">=14.0.0" } }, + "node_modules/electron-builder-squirrel-windows": { + "version": "26.15.3", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.15.3.tgz", + "integrity": "sha512-Jc19XPV9y9+2bAdZPkXuVNGNIEFBq9poHC61l8Kv6FdK7DRG3+Ic0rerC0DXOaeHNz8yW0fg/JnF8GQROOF5MA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "app-builder-lib": "26.15.3", + "builder-util": "26.15.3", + "electron-winstaller": "5.4.0" + } + }, "node_modules/electron-publish": { "version": "26.15.3", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.15.3.tgz", @@ -1445,6 +1506,66 @@ "tiny-typed-emitter": "^2.1.0" } }, + "node_modules/electron-winstaller": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz", + "integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@electron/asar": "^3.2.1", + "debug": "^4.1.1", + "fs-extra": "^7.0.1", + "lodash": "^4.17.21", + "temp": "^0.9.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "@electron/windows-sign": "^1.1.2" + } + }, + "node_modules/electron-winstaller/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/electron-winstaller/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-winstaller/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2359,6 +2480,20 @@ "node": ">= 18" } }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2622,6 +2757,36 @@ "node": ">=18" } }, + "node_modules/postject": { + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", + "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "commander": "^9.4.0" + }, + "bin": { + "postject": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/postject/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/proc-log": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", @@ -2816,6 +2981,21 @@ "node": ">= 4" } }, + "node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -3071,6 +3251,21 @@ "node": ">=18" } }, + "node_modules/temp": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", + "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "mkdirp": "^0.5.1", + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/temp-file": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", diff --git a/open-sse/services/tokenRefresh.ts b/open-sse/services/tokenRefresh.ts index b4a6e2afe7..43dcba1a6d 100755 --- a/open-sse/services/tokenRefresh.ts +++ b/open-sse/services/tokenRefresh.ts @@ -109,15 +109,50 @@ export const REFRESH_LEAD_MS: Record = { "gitlab-duo": 5 * 60 * 1000, // GitLab token family revocation on misuse kiro: 5 * 60 * 1000, // AWS SSO OIDC issues one-time-use refresh tokens "kimi-coding": 5 * 60 * 1000, // Moonshot rotates per-refresh - // Non-rotating providers — longer lead is safe. - iflow: 24 * 60 * 60 * 1000, // 24 hours // Google OAuth refresh_tokens are permanent (non-rotating) — longer lead // is safe and reduces unnecessary upstream chatter. antigravity: 15 * 60 * 1000, agy: 15 * 60 * 1000, // same Google backend as antigravity (non-rotating refresh tokens) - "gemini-cli": 15 * 60 * 1000, // legacy stored connections; provider is no longer public }; +/** + * Upstream providers that stored connections may still name, but that this build no + * longer serves. They are NOT routable — absent from PROVIDERS, from the chat REGISTRY, + * and without an executor — so keeping their token fresh maintains a credential that can + * never answer a request. + * + * Deprecation, not deletion: a connection here becomes terminal with a reason that names + * where to go instead, rather than silently sitting at `active` doing nothing. The + * migration target must be routable — `tests/unit/gemini-cli-deprecation.test.ts` asserts + * that, so the notice can never point somewhere useless. + */ +export const DEPRECATED_PROVIDERS: Readonly< + Record +> = { + "gemini-cli": { + migrateTo: "gemini", + // The legacy path redeemed the token with PROVIDERS.gemini's client — the very same + // public Gemini CLI / Code Assist OAuth client — which is why re-adding the account + // under `gemini` is a real migration and not a suggestion to start over. + reason: + "The gemini-cli provider was discontinued and is not routable. Re-add this account " + + "under the `gemini` provider — it uses the same Google OAuth client, so the same " + + "login works and the account becomes usable again.", + }, +}; + +/** Whether `provider` is a deprecated upstream that must not be refreshed. */ +export function isDeprecatedProvider(provider: string): boolean { + return Boolean(provider) && Object.prototype.hasOwnProperty.call(DEPRECATED_PROVIDERS, provider); +} + +/** The migration notice for a deprecated provider, or null when it is not deprecated. */ +export function getDeprecationNotice( + provider: string +): { migrateTo: string; reason: string } | null { + return isDeprecatedProvider(provider) ? DEPRECATED_PROVIDERS[provider] : null; +} + /** * Get the proactive refresh lead time (ms) for a given provider. * @@ -263,17 +298,27 @@ export async function refreshAccessToken( */ async function _getAccessTokenInternal(provider, credentials, log, proxyConfig: unknown = null) { switch (provider) { - case "gemini-cli": - // Legacy DB rows can retain this discontinued provider id. Refresh them - // with the same public OAuth client used by Gemini CLI without restoring - // gemini-cli to the routable provider or OAuth UI registries. - return await refreshGoogleToken( - credentials.refreshToken, - PROVIDERS.gemini.clientId, - PROVIDERS.gemini.clientSecret, - log, - proxyConfig + case "gemini-cli": { + // Deprecated (see DEPRECATED_PROVIDERS). This used to refresh successfully against + // PROVIDERS.gemini's client, but the provider is not routable, so the fresh token + // had nowhere to go — periodic upstream calls maintaining an unusable credential. + // + // Return the ESTABLISHED unrecoverable contract, so every existing caller + // (isUnrecoverableRefreshError, the manual-refresh route) already stops retrying — + // but with a code that says WHY and a target to migrate to. A bare `null` here would + // read as a transient failure and be retried forever. + const notice = DEPRECATED_PROVIDERS[provider]; + log?.warn?.( + "TOKEN_REFRESH", + `${provider} is deprecated — not refreshing; migrate this account to ${notice.migrateTo}` ); + return { + error: "unrecoverable_refresh_error", + code: "provider_deprecated", + migrateTo: notice.migrateTo, + reason: notice.reason, + }; + } case "gemini": case "antigravity": @@ -390,7 +435,6 @@ async function _getAccessTokenInternal(provider, credentials, log, proxyConfig: export function supportsTokenRefresh(provider) { const explicitlySupported = new Set([ "gemini", - "gemini-cli", // legacy refresh compatibility only; not a routable provider "antigravity", "agy", "claude", diff --git a/package-lock.json b/package-lock.json index 5d076a23ac..b4df5b0026 100644 --- a/package-lock.json +++ b/package-lock.json @@ -103,7 +103,7 @@ "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@types/better-sqlite3": "^7.6.13", - "@types/bun": "latest", + "@types/bun": "*", "@types/node": "^26.1.0", "@types/react": "^19.2.15", "@types/react-dom": "^19.2.3", diff --git a/package.json b/package.json index 100bb0519d..5b995b365b 100644 --- a/package.json +++ b/package.json @@ -143,6 +143,7 @@ "check:node-runtime": "node --import tsx scripts/check/check-supported-node-runtime.ts", "check:pack-artifact": "node --import tsx scripts/build/validate-pack-artifact.ts", "check:pack-boot": "node scripts/check/check-pack-boot.mjs", + "check:install-upgrade": "node scripts/check/check-install-upgrade.mjs", "check:pack-policy": "node --import tsx scripts/build/validate-pack-artifact.ts --policy-only", "check:cli-i18n": "node scripts/check/check-cli-i18n.mjs", "check:openapi-coverage": "node scripts/check/check-openapi-coverage.mjs", @@ -161,6 +162,7 @@ "check:test-masking": "node scripts/check/check-test-masking.mjs", "check:test-runner-api": "node scripts/check/check-test-runner-api.mjs", "check:changelog-integrity": "node scripts/check/check-changelog-integrity.mjs", + "sweep:stale-fragments": "node scripts/release/sweep-stale-fragments.mjs", "changelog:aggregate": "node scripts/release/aggregate-changelog.mjs", "check:agent-skills-sync": "node --import tsx/esm scripts/skills/generate-agent-skills.mjs", "check:build-scope": "node scripts/check/check-build-scope.mjs", diff --git a/scripts/check/check-env-doc-sync.mjs b/scripts/check/check-env-doc-sync.mjs index ffd4add27a..05921a4e2b 100644 --- a/scripts/check/check-env-doc-sync.mjs +++ b/scripts/check/check-env-doc-sync.mjs @@ -94,6 +94,18 @@ const IGNORE_FROM_CODE = new Set([ // CI passes BASE_REF=${{ github.base_ref }} to the OpenAPI breaking-change gate // (scripts/check/check-openapi-breaking.mjs) — a build/check signal, not OmniRoute runtime config. "BASE_REF", + // Same class as BASE_REF above: the `changes` job passes these four to the + // self-targeting-PR guard (scripts/check/check-pr-self-target.mjs) so it can compare a PR's + // head against its base. CI-only signals from github.head_ref / github.base_ref / + // pull_request.{head,base}.sha — never OmniRoute runtime config, and meaningless in a .env. + "HEAD_REF", + "HEAD_SHA", + "BASE_SHA", + // Escape hatch for the test-masking gate's release-scale skip + // (scripts/check/check-test-masking.mjs): above ~300 changed test files the per-file diff + // subchecks are skipped, and this raises that cap for anyone who wants the full pass anyway. + // A gate tuning knob, not application configuration. + "TEST_MASKING_MAX_CHANGED_TESTS", // PR body injected by GitHub Actions into the pr-evidence gate (github.event.pull_request.body); // a CI-only signal, never an OmniRoute runtime config (Phase 7.10). "PR_BODY", diff --git a/scripts/check/check-install-upgrade.mjs b/scripts/check/check-install-upgrade.mjs new file mode 100644 index 0000000000..87253c611d --- /dev/null +++ b/scripts/check/check-install-upgrade.mjs @@ -0,0 +1,342 @@ +#!/usr/bin/env node +/** + * check-install-upgrade — proves the two install paths a real user takes, BEFORE publishing. + * + * `check:pack-boot` already proves a fresh install boots. It does NOT prove the path that + * actually broke us: installing the new version OVER an existing one, where ~110 SQLite + * migrations run against a populated database. v3.8.48 shipped as a hotfix precisely because + * the published 3.8.47 crashed on boot, and a v3.8.49 manual test on a real 3.8.48 box was + * what first exercised the upgrade path end to end. + * + * Phase A — clean install: fresh prefix + fresh DATA_DIR, install the packed tarball, boot. + * Phase B — upgrade install: fresh prefix + fresh DATA_DIR, install the PREVIOUS published + * version, boot it (creates + migrates the DB), stop, install the + * packed tarball over the SAME prefix, boot against the SAME DATA_DIR. + * + * Schema convergence is the third assertion, and its DIRECTION is what matters: + * + * fresh − upgraded ≠ ∅ → FAIL. A table a clean install creates but an upgrade does not + * means every existing user is missing structure the code expects. + * This is the failure mode that only ever bites upgraders. + * upgraded − fresh ≠ ∅ → WARN. Residue: a table whose CREATE left the migration set in + * some past cycle but survives in databases that already had it. + * Harmless, but it means the two paths do not converge — allowlist + * it explicitly so a NEW divergence is still visible. + * + * Usage: + * node scripts/check/check-install-upgrade.mjs [--from ] [--skip-upgrade] + * + * `--from` pins the previous version (default: the current `latest` dist-tag on npm). + * Requires `npm run build:cli` first — this is a --with-build gate, like check:pack-boot. + */ + +import { execFileSync, spawn } from "node:child_process"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { DatabaseSync } from "node:sqlite"; + +const BOOT_DEADLINE_MS = 180_000; +const POLL_INTERVAL_MS = 2_000; +const ALLOWLIST_PATH = "config/quality/install-upgrade-allowlist.json"; + +const log = (msg) => console.log(`[install-upgrade] ${msg}`); +const warn = (msg) => console.log(`[install-upgrade] ⚠️ ${msg}`); + +function pickTarball(packJson) { + const filename = JSON.parse(packJson)?.[0]?.filename; + if (!filename) throw new Error("npm pack --json returned no filename"); + return filename; +} + +/** Free-ish port per phase so a leaked child from a previous run cannot collide. */ +function pickPort(offset) { + return 21000 + offset + (process.pid % 500); +} + +function loadAllowlist(root) { + const file = path.join(root, ALLOWLIST_PATH); + if (!fs.existsSync(file)) return { residualTables: {} }; + return JSON.parse(fs.readFileSync(file, "utf8")); +} + +/** + * Pure verdict on schema convergence — exported so the asymmetry can be tested without + * building, packing and booting anything (the same reason check-test-masking exports its + * helpers: reproducing the deterministic part must not cost a full gate run). + * + * The two directions are NOT symmetric: + * onlyFresh → always a failure. Upgraders would be missing structure. + * onlyUpgraded → residue. Fails only when not recorded in the allowlist. + */ +export function evaluateConvergence({ freshTables, upgradedTables, residualAllowlist = {} }) { + const fresh = freshTables instanceof Set ? freshTables : new Set(freshTables ?? []); + const upgraded = upgradedTables instanceof Set ? upgradedTables : new Set(upgradedTables ?? []); + const onlyFresh = [...fresh].filter((t) => !upgraded.has(t)).sort(); + const onlyUpgraded = [...upgraded].filter((t) => !fresh.has(t)).sort(); + const unknownResidue = onlyUpgraded.filter((t) => !(t in residualAllowlist)); + const failures = []; + if (onlyFresh.length) { + failures.push( + `schema divergence — tables a CLEAN install creates but an UPGRADE does not: ${onlyFresh.join(", ")}. ` + + "Every existing user would be missing these; add the migration." + ); + } + if (unknownResidue.length) { + failures.push( + `NEW residual table(s) not in ${ALLOWLIST_PATH}: ${unknownResidue.join(", ")}. ` + + "Either drop them in a migration or record them with a justification." + ); + } + return { ok: failures.length === 0, failures, onlyFresh, onlyUpgraded, unknownResidue }; +} + +/** Table names in a SQLite file, excluding sqlite_* internals. */ +function readTables(dbPath) { + if (!fs.existsSync(dbPath)) return null; + const db = new DatabaseSync(dbPath, { readOnly: true }); + try { + const rows = db + .prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'") + .all(); + return new Set(rows.map((r) => r.name)); + } finally { + db.close(); + } +} + +function findDb(dataDir) { + const candidates = ["storage.sqlite", "omniroute.sqlite", "data.sqlite"]; + for (const name of candidates) { + const p = path.join(dataDir, name); + if (fs.existsSync(p)) return p; + } + const found = fs.readdirSync(dataDir).find((f) => f.endsWith(".sqlite")); + return found ? path.join(dataDir, found) : null; +} + +/** Boot an installed CLI and poll health. Returns { ok, version, failures, tail }. */ +async function bootAndProbe({ prefix, dataDir, port, expectVersion, label }) { + const binPath = path.join(prefix, "bin", "omniroute"); + if (!fs.existsSync(binPath)) { + return { ok: false, failures: [`${label}: bin not found at ${binPath}`], tail: [] }; + } + const child = spawn(binPath, ["serve", "--port", String(port)], { + env: { + ...process.env, + PORT: String(port), + DATA_DIR: dataDir, + JWT_SECRET: "install-upgrade-gate-secret-with-sufficient-length", + API_KEY_SECRET: "install-upgrade-gate-api-key-secret-long", + DISABLE_SQLITE_AUTO_BACKUP: "true", + OMNIROUTE_SKIP_SYSTEM_TRUST: "1", + }, + stdio: ["ignore", "pipe", "pipe"], + detached: true, + }); + + const tail = []; + const keepTail = (chunk) => { + tail.push(String(chunk)); + while (tail.length > 80) tail.shift(); + }; + child.stdout.on("data", keepTail); + child.stderr.on("data", keepTail); + let childExit = null; + child.on("exit", (code) => { + childExit = code ?? -1; + }); + + const deadline = Date.now() + BOOT_DEADLINE_MS; + let result = { ok: false, failures: [`${label}: never became healthy`], tail }; + while (Date.now() < deadline) { + if (childExit !== null) { + result = { ok: false, failures: [`${label}: exited with code ${childExit} before serving`], tail }; + break; + } + try { + const res = await fetch(`http://127.0.0.1:${port}/api/monitoring/health`); + const body = await res.json().catch(() => null); + if (res.status === 200 && body && typeof body === "object") { + const failures = []; + // `status` may legitimately report degraded (no providers configured) — the gate + // targets boot crashes and version mismatches, not health of a bare install. + if (expectVersion && body.version !== expectVersion) { + failures.push(`${label}: health reports version ${body.version}, expected ${expectVersion}`); + } + result = { ok: failures.length === 0, version: body.version, failures, tail }; + break; + } + } catch { + // not listening yet + } + await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS)); + } + + try { + if (childExit === null) process.kill(-child.pid, "SIGTERM"); + } catch { + /* already gone */ + } + // Give the process a moment to flush and release the SQLite handle before we read the file. + await new Promise((r) => setTimeout(r, 3_000)); + return result; +} + +function npmInstallInto(prefix, spec) { + execFileSync("npm", ["install", "-g", "--prefix", prefix, "--no-audit", "--no-fund", spec], { + encoding: "utf8", + maxBuffer: 128 * 1024 * 1024, + }); +} + +function resolvePreviousVersion(current, explicit) { + if (explicit) return explicit; + const out = execFileSync("npm", ["view", "omniroute", "dist-tags.latest"], { encoding: "utf8" }); + const latest = out.trim(); + if (!latest) throw new Error("could not resolve omniroute@latest from npm"); + if (latest === current) { + // The version under test is already published (re-run of a shipped release): step back + // to the highest published version strictly below it. + const all = JSON.parse(execFileSync("npm", ["view", "omniroute", "versions", "--json"], { encoding: "utf8" })); + const stable = all.filter((v) => !/-(rc|alpha|beta|pre|next)/.test(v) && v !== current); + return stable[stable.length - 1]; + } + return latest; +} + +async function main() { + const ROOT = process.cwd(); + const args = process.argv.slice(2); + const fromIdx = args.indexOf("--from"); + const explicitFrom = fromIdx >= 0 ? args[fromIdx + 1] : null; + const skipUpgrade = args.includes("--skip-upgrade"); + + if (!fs.existsSync(path.join(ROOT, "dist", "server.js"))) { + console.error("[install-upgrade] dist/server.js missing — run `npm run build:cli` first"); + process.exit(2); + } + const version = JSON.parse(fs.readFileSync(path.join(ROOT, "package.json"), "utf8")).version; + const allowlist = loadAllowlist(ROOT); + const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-install-upgrade-")); + const failures = []; + const warnings = []; + + try { + log(`packing v${version}…`); + const packOut = execFileSync("npm", ["pack", "--json", "--pack-destination", tmp], { + cwd: ROOT, + encoding: "utf8", + maxBuffer: 128 * 1024 * 1024, + }); + const tarball = path.join(tmp, pickTarball(packOut)); + + // ---- Phase A: clean install ------------------------------------------------- + log("PHASE A — clean install of the packed tarball"); + const aPrefix = path.join(tmp, "a-prefix"); + const aData = path.join(tmp, "a-data"); + fs.mkdirSync(aData, { recursive: true }); + npmInstallInto(aPrefix, tarball); + const a = await bootAndProbe({ + prefix: aPrefix, + dataDir: aData, + port: pickPort(0), + expectVersion: version, + label: "clean", + }); + failures.push(...a.failures); + if (a.ok) log(`clean install healthy on v${a.version}`); + const aDb = findDb(aData); + const freshTables = aDb ? readTables(aDb) : null; + if (!freshTables) failures.push("clean: no SQLite database was created"); + else log(`clean install schema: ${freshTables.size} tables`); + + // ---- Phase B: upgrade over the previous published version ------------------- + let upgradedTables = null; + if (skipUpgrade) { + warn("PHASE B skipped (--skip-upgrade)"); + } else { + const previous = resolvePreviousVersion(version, explicitFrom); + log(`PHASE B — upgrade path: omniroute@${previous} → v${version}`); + const bPrefix = path.join(tmp, "b-prefix"); + const bData = path.join(tmp, "b-data"); + fs.mkdirSync(bData, { recursive: true }); + + npmInstallInto(bPrefix, `omniroute@${previous}`); + const before = await bootAndProbe({ + prefix: bPrefix, + dataDir: bData, + port: pickPort(1), + expectVersion: previous, + label: `previous(${previous})`, + }); + if (!before.ok) { + // A broken PREVIOUS version is not this release's fault — degrade to a warning so a + // historically bad publish cannot block the current one. + warnings.push(`previous version ${previous} did not boot cleanly — upgrade path unverified`); + for (const f of before.failures) warn(f); + } else { + const beforeDb = findDb(bData); + const beforeTables = beforeDb ? readTables(beforeDb) : new Set(); + log(`previous(${previous}) schema: ${beforeTables.size} tables — upgrading in place`); + + npmInstallInto(bPrefix, tarball); + const after = await bootAndProbe({ + prefix: bPrefix, + dataDir: bData, + port: pickPort(2), + expectVersion: version, + label: "upgraded", + }); + failures.push(...after.failures); + if (after.ok) log(`upgrade healthy on v${after.version}`); + + const afterDb = findDb(bData); + upgradedTables = afterDb ? readTables(afterDb) : null; + if (!upgradedTables) { + failures.push("upgraded: database disappeared after the upgrade"); + } else { + log(`upgraded schema: ${upgradedTables.size} tables`); + const dropped = [...beforeTables].filter((t) => !upgradedTables.has(t)); + if (dropped.length) { + failures.push(`upgrade DROPPED tables that existed before: ${dropped.join(", ")}`); + } + } + } + } + + // ---- Schema convergence ----------------------------------------------------- + if (freshTables && upgradedTables) { + const verdict = evaluateConvergence({ + freshTables, + upgradedTables, + residualAllowlist: allowlist.residualTables ?? {}, + }); + if (verdict.onlyUpgraded.length) { + warn(`residual tables present only after upgrade: ${verdict.onlyUpgraded.join(", ")}`); + } + failures.push(...verdict.failures); + if (verdict.ok) log("schema convergence OK (no new divergence)"); + } + + if (warnings.length) for (const w of warnings) warn(w); + if (failures.length) { + console.error(`[install-upgrade] FAIL — ${failures.length} problem(s):`); + for (const f of failures) console.error(` ✗ ${f}`); + process.exit(1); + } + log("PASS — clean install and upgrade path both boot; schema converges."); + process.exit(0); + } finally { + fs.rmSync(tmp, { recursive: true, force: true }); + } +} + +// Only run the (expensive) gate when invoked directly — importing this module for the pure +// helper above must not pack, install or boot anything. +if (process.argv[1] && path.resolve(process.argv[1]) === path.resolve(new URL(import.meta.url).pathname)) { + main().catch((err) => { + console.error(`[install-upgrade] crashed: ${err?.message ?? err}`); + process.exit(1); + }); +} diff --git a/scripts/check/check-pr-self-target.mjs b/scripts/check/check-pr-self-target.mjs new file mode 100644 index 0000000000..1e30fc3366 --- /dev/null +++ b/scripts/check/check-pr-self-target.mjs @@ -0,0 +1,90 @@ +#!/usr/bin/env node +// Refuse a pull request that targets its own head branch. +// +// WHY: PR #8912 has head == base == release/v3.8.50 — a PR from a branch to itself. It has no +// diff, it can never merge, and GitHub keeps it in the queue forever with a full check board +// attached. It survived because nothing looks wrong: the checks are green (there is nothing to +// check), the mergeability just reads "unknown", and it quietly costs review attention and CI +// minutes on every push to that branch. +// +// The check is one field comparison, which is the point — it is cheaper than the confusion. +// +// Usage (in CI, inside a pull_request job): +// HEAD_REF="$GITHUB_HEAD_REF" BASE_REF="$GITHUB_BASE_REF" \ +// HEAD_SHA=... BASE_SHA=... node scripts/check/check-pr-self-target.mjs +// Exit: 0 when the PR is well-formed or there is no PR context, 1 when it targets itself. + +import fs from "node:fs"; +import { fileURLToPath } from "node:url"; + +/** + * Classify a PR's head/base pair. + * + * Both signals are checked because either alone can be absent: `*_REF` is empty for + * cross-fork events in some contexts, and the SHAs coincide on a freshly branched PR that is + * NOT self-targeting (branch cut, nothing pushed yet) — so an equal-SHA alone must not fail. + * Only an equal REF is conclusive; equal SHAs are reported as a warning. + */ +export function classifyPrTarget({ headRef, baseRef, headSha, baseSha } = {}) { + const hr = String(headRef ?? "").trim(); + const br = String(baseRef ?? "").trim(); + const hs = String(headSha ?? "").trim(); + const bs = String(baseSha ?? "").trim(); + + if (!hr && !br) return { verdict: "no-pr-context" }; + + if (hr && br && hr === br) { + return { + verdict: "self-targeting", + reason: `head and base are the same branch (${hr}) — this PR has no diff and can never merge`, + }; + } + + if (hs && bs && hs === bs) { + // Legitimate right after cutting a branch: the tip has not moved yet. Not a failure. + return { + verdict: "empty-diff", + reason: `head and base point at the same commit (${hs.slice(0, 10)}) — nothing to review yet`, + }; + } + + return { verdict: "ok" }; +} + +function main() { + const r = classifyPrTarget({ + headRef: process.env.HEAD_REF, + baseRef: process.env.BASE_REF, + headSha: process.env.HEAD_SHA, + baseSha: process.env.BASE_SHA, + }); + + if (r.verdict === "self-targeting") { + process.stderr.write( + `::error::PR targets its own branch — ${r.reason}.\n` + + `Close it, or repoint the base at the branch you actually want to merge into ` + + `(gh pr edit --base , then VERIFY with gh pr view --json baseRefName — ` + + `the edit fails silently).\n` + ); + return 1; + } + + if (r.verdict === "empty-diff") { + process.stdout.write(`::warning::${r.reason}.\n`); + return 0; + } + + process.stdout.write( + r.verdict === "no-pr-context" + ? "[pr-self-target] no PR context — skipping.\n" + : "[pr-self-target] OK — head and base differ.\n" + ); + return 0; +} + +if ( + process.argv[1] && + fs.realpathSync(process.argv[1]) === fs.realpathSync(fileURLToPath(import.meta.url)) +) { + process.exit(main()); +} diff --git a/scripts/check/check-test-masking.mjs b/scripts/check/check-test-masking.mjs index 96f67e9d0b..33f41edb88 100644 --- a/scripts/check/check-test-masking.mjs +++ b/scripts/check/check-test-masking.mjs @@ -436,6 +436,22 @@ function resolveBase() { return null; } +/** + * Whether the per-file diff subchecks should be skipped for being too large to be a + * reviewable unit. Exported so the threshold behavior is testable without a repo: the + * boundary is what matters, and an off-by-one here either blocks a release or silently + * disables the check on a big-but-legitimate PR. + * + * `max <= 0` disables the skip entirely (always analyze) — a deliberate escape hatch. + */ +export function shouldSkipDiffSubchecks(changedCount, max) { + const n = Number(changedCount); + const cap = Number(max); + if (!Number.isFinite(n) || n < 0) return false; + if (!Number.isFinite(cap) || cap <= 0) return false; + return n > cap; +} + function main() { // (#6404) Absolute floor scan — runs unconditionally, PR or not, so a tautology // that is already merged into the base (and thus invisible to the diff-only @@ -507,6 +523,34 @@ function main() { .map((s) => s.trim()) .filter((f) => TEST_RE.test(f) && fs.existsSync(f)); + // (gap 6) A release PR is not a reviewable unit, and this is where that stops being free. + // Releases squash-merge into `main`, so a release PR's merge-base is the PREVIOUS cycle's + // fork point and the diff spans the whole cycle. In the v3.8.49 run that was ~1277 changed + // test files, each costing a `git show base:file` process plus a full regex pass — the check + // ran twice without finishing, >30 min pegged on one core, and the release waited on it. + // + // Every one of those files was already gated by this same check on its own PR during the + // cycle. Re-analyzing the aggregate buys nothing and blocks the release, so above the + // threshold the per-file diff subchecks are skipped — LOUDLY, naming the count, because a + // silent skip is how a gate becomes indistinguishable from a passing one (that is gap 12, + // and it cost two production bugs this cycle). + // + // The floor is untouched: scanBareTautologies() above already ran unconditionally over all + // tracked test files (3977 files, ~1 s), so nothing here lowers absolute coverage. + const maxChangedTests = Number(process.env.TEST_MASKING_MAX_CHANGED_TESTS || 300); + if (shouldSkipDiffSubchecks(changed.length + renamePerFile.length, maxChangedTests)) { + console.log( + `[test-masking] ${changed.length} teste(s) modificado(s) + ${renamePerFile.length} ` + + `renomeado(s) excede o teto de ${maxChangedTests} — pulando os subchecks de diff.\n` + + ` Um diff desse tamanho é um PR de release (base = main, merge-base = fork do ciclo ` + + `anterior por causa do squash), não uma unidade revisável.\n` + + ` Cada um desses arquivos já passou por este mesmo gate no PR de origem.\n` + + ` O scan absoluto de tautologias rodou sobre TODOS os testes rastreados e está OK.\n` + + ` Para forçar a análise completa: TEST_MASKING_MAX_CHANGED_TESTS=999999` + ); + return; + } + const perFile = [...renamePerFile]; for (const file of changed) { const baseSrc = git(["show", `${base}:${file}`]); diff --git a/scripts/check/check-workflows.mjs b/scripts/check/check-workflows.mjs index 5887134ecb..2ac213ff37 100644 --- a/scripts/check/check-workflows.mjs +++ b/scripts/check/check-workflows.mjs @@ -235,6 +235,23 @@ export function runActionlint(files) { * @param {string} workflowsDir - Path to .github/workflows * @returns {{ count: number, diagnostics: unknown[], skipped: boolean }} */ +/** + * The zizmor version actually doing the auditing, or "unknown". + * + * Emitted next to the count because the two must be read together. The GitHub runner measured + * 1 finding MORE than the devbox on the identical commit (190 vs 189) during the v3.8.49 cycle, + * which cost a second rebaseline push: CI installed whatever PyPI served that day while the + * devbox had an older build. A count without the version that produced it is not a + * reproducible number, and rebaselining against it just moves the disagreement. + */ +export function zizmorVersion() { + try { + return execFileSync("zizmor", ["--version"], { encoding: "utf8" }).trim() || "unknown"; + } catch { + return "unknown"; + } +} + export function runZizmor(workflowsDir) { const args = ["--format", "json"]; if (fs.existsSync(ZIZMOR_CONFIG)) { @@ -337,6 +354,9 @@ function main() { process.stdout.write(`workflowFindings=${total}\n`); process.stdout.write(`actionlintFindings=${actionlintCount}\n`); process.stdout.write(`zizmorFindings=${zizmorCount}\n`); + // Read this line with the count above: a finding total is only reproducible against the + // version that produced it. See zizmorVersion(). + process.stdout.write(`zizmorVersion=${hasZizmor ? zizmorVersion() : "absent"}\n`); if (STRICT && total > 0) { console.error(`\n[check-workflows] FAIL — ${total} workflow finding(s) total (--strict mode).`); diff --git a/scripts/i18n/check-ui-value-drift.mjs b/scripts/i18n/check-ui-value-drift.mjs index d2788c35a0..f897dc9a4b 100644 --- a/scripts/i18n/check-ui-value-drift.mjs +++ b/scripts/i18n/check-ui-value-drift.mjs @@ -78,6 +78,39 @@ export function flattenLeaves(node, prefix = "", out = {}) { * @param {Record} args.headLocales locale -> catalog in the working tree * @returns {Array<{ key: string, locale: string }>} sorted, stable */ +/** + * Whether an English rewrite is COSMETIC — the same sentence, differently cased, spaced, or + * terminally punctuated. A translation of the old string is still a correct translation of the + * new one, so it must not be marked stale. + * + * Why this exists: `"Reset Defaults"` → `"Reset defaults"` marked the key stale in 41 locales + * during the v3.8.49 cycle. Every one of those translations was still correct, and in locales + * with no letter case the "fix" is not even expressible. Worse, the documented escape hatch + * (a `__MISSING__:` placeholder) is BANNED in `vi` by tests/unit/i18n-vi-completeness.test.ts, + * so `vi` had no legitimate way out of a purely cosmetic English edit. + * + * Deliberately narrow: ONLY letter case and trailing terminal punctuation. + * + * **Whitespace is NOT folded, on purpose.** A first version of this folded whitespace runs and + * trimmed, and it collided with a pre-existing, deliberately conservative decision — + * tests/unit/i18n-ui-value-drift.test.ts, "a value that only changes whitespace still counts as + * an edit", whose comment reads: *"trailing-space churn is rare, and treating it as a no-op would + * let a real reword slip through behind an innocuous-looking diff."* That call belongs to whoever + * made it; the problem actually reported here was CASE + * (`"Reset Defaults"` → `"Reset defaults"`, 41 locales invalidated), and quietly reversing + * someone else's documented decision to fix something they never reported is not this change's + * job. Narrowed to the reported scope instead. + * + * Any change to the words themselves — added or removed words, and any change inside an + * interpolation like `{count}` — is a real rewrite and still flags. + */ +export function isCosmeticRewrite(before, after) { + if (typeof before !== "string" || typeof after !== "string") return false; + if (before === after) return true; + const norm = (s) => s.replace(/[.:!?;,]+$/u, "").toLowerCase(); + return norm(before) === norm(after); +} + export function findStaleTranslations({ baseEn, headEn, baseLocales, headLocales }) { const baseFlat = flattenLeaves(baseEn); const headFlat = flattenLeaves(headEn); @@ -85,8 +118,14 @@ export function findStaleTranslations({ baseEn, headEn, baseLocales, headLocales // Keys whose English copy was REWRITTEN by this change. A key absent from either side // is an add or a delete: nothing can be stale against text that did not exist, and a // renamed key (delete + add) is exactly the safe fix pattern. + // + // Cosmetic rewrites (case, spacing, trailing punctuation) are excluded — see + // isCosmeticRewrite. They used to invalidate correct translations in 41 locales at once. const rewritten = Object.keys(headFlat).filter( - (key) => key in baseFlat && baseFlat[key] !== headFlat[key] + (key) => + key in baseFlat && + baseFlat[key] !== headFlat[key] && + !isCosmeticRewrite(baseFlat[key], headFlat[key]) ); if (rewritten.length === 0) return []; diff --git a/scripts/release/list-uncovered-commits.mjs b/scripts/release/list-uncovered-commits.mjs index b2a5ae819b..0b92eb1b09 100644 --- a/scripts/release/list-uncovered-commits.mjs +++ b/scripts/release/list-uncovered-commits.mjs @@ -25,6 +25,56 @@ const git = (args) => execFileSync("git", args, { cwd: ROOT, encoding: "utf8" }) const ROLLUP_TYPES = new Set(["chore", "ci", "test", "refactor", "build", "docs", "style"]); +/** + * Pick the commit that OPENED the current development cycle, and use that as the range base. + * + * `git describe --tags` is wrong here, and wrong in a way that hides work rather than + * announcing itself. Releases reach `main` by SQUASH, so no commit on a release branch is + * ever an ancestor of the tag — `v3.8.49..HEAD` therefore re-lists the un-squashed history + * of every prior cycle. Measured on release/v3.8.50 at 7eca04fd12: + * + * v3.8.49..HEAD ............ 1361 commits + * cycle open..HEAD ......... 22 commits + * + * 62× the real range. The report drowns in noise, which is exactly how a previous + * reconciliation let ~200 PRs through with no CHANGELOG bullet. + * + * Resolved by CONTENT, not by commit message: the cycle opens when package.json first + * carries this version, so `git log -S` on that exact string finds it regardless of how the + * subject was worded. The wording has already changed once — + * `chore(release): bump v3.8.49 (development cycle version)` became + * `chore(release): open v3.8.50 development cycle` — and a message-matching resolver would + * have silently fallen back to the broken tag base on the newer format. + * + * Falls back to the tag with an explicit stderr warning, so a shallow clone or a rewritten + * history degrades loudly instead of quietly reproducing the original bug. + */ +export function resolveCycleBase(version, runGit = git) { + let openCommit = ""; + try { + // Oldest commit that introduced this version string = the cycle-open commit. + const hits = runGit(["log", "--format=%H", "-S", `"version": "${version}"`, "--", "package.json"]); + openCommit = hits ? hits.split("\n").filter(Boolean).pop() : ""; + } catch { + openCommit = ""; + } + if (openCommit) return { base: openCommit, source: "cycle-open" }; + + let tag = ""; + try { + tag = runGit(["describe", "--tags", "--abbrev=0"]); + } catch { + tag = ""; + } + process.stderr.write( + `[list-uncovered-commits] WARNING: could not find the commit that opened v${version} ` + + `(searched package.json for the version string). Falling back to ` + + `${tag || "the repository root"} — because releases squash-merge, that range re-lists ` + + `previous cycles and the report below will contain noise.\n` + ); + return { base: tag, source: "tag-fallback" }; +} + export function refsOf(subject) { return [...subject.matchAll(/#(\d+)/g)].map((m) => Number(m[1])); } @@ -137,9 +187,10 @@ export function changelogRefWindow(changelog, version) { function main(argv) { const jsonOut = argv.includes("--json"); - const lastTag = git(["describe", "--tags", "--abbrev=0"]); const version = JSON.parse(fs.readFileSync(path.join(ROOT, "package.json"), "utf8")).version; - const log = git(["log", "--no-merges", `${lastTag}..HEAD`, "--pretty=format:%h%x09%s"]); + const { base, source } = resolveCycleBase(version); + const lastTag = base ? git(["rev-parse", "--short", base]) : base; + const log = git(["log", "--no-merges", `${base}..HEAD`, "--pretty=format:%h%x09%s"]); const commits = log ? log.split("\n").map((l) => { const [hash, subject] = l.split("\t"); @@ -153,14 +204,19 @@ function main(argv) { if (jsonOut) { process.stdout.write( - JSON.stringify({ version, lastTag, total: commits.length, covered, uncovered }, null, 2) + - "\n" + JSON.stringify( + { version, base: lastTag, baseSource: source, total: commits.length, covered, uncovered }, + null, + 2 + ) + "\n" ); return; } const bulletsWorthy = uncovered.filter((c) => !c.rollup); const rollupCandidates = uncovered.filter((c) => c.rollup); - process.stdout.write(`# Uncovered-commit reconciliation — v${version} (${lastTag}..HEAD)\n\n`); + process.stdout.write( + `# Uncovered-commit reconciliation — v${version} (${lastTag}..HEAD, base from ${source})\n\n` + ); process.stdout.write( `Commits: ${commits.length} · covered: ${covered} · uncovered: ${uncovered.length}\n\n` ); diff --git a/scripts/release/merge-mac-update-manifest.mjs b/scripts/release/merge-mac-update-manifest.mjs new file mode 100644 index 0000000000..ad862763b7 --- /dev/null +++ b/scripts/release/merge-mac-update-manifest.mjs @@ -0,0 +1,173 @@ +#!/usr/bin/env node +// Merge the per-architecture `latest-mac.yml` manifests into one that serves BOTH Macs. +// +// THE BUG THIS FIXES IS LIVE IN v3.8.48: an Intel Mac downloads the ARM dmg. +// +// electron-builder runs once per macOS job (macos-intel, macos-arm64) and each run emits its +// own `latest-mac.yml` listing only its own dmg — 338 and 350 bytes, different content, same +// filename. `actions/download-artifact` with `merge-multiple: true` resolves that name +// collision by ARRIVAL ORDER, so one silently overwrites the other. In the published v3.8.48 +// manifest the arm64 build won. +// +// Why that breaks Intel, from electron-updater's own selection code +// (electron-updater/out/providers/Provider.js): +// +// const result = filteredFiles.find(it => +// [it.url.pathname, it.info.url].some(n => n.includes(process.arch)) +// ) ?? filteredFiles.shift(); +// +// The Intel dmg is named `OmniRoute-X.Y.Z.dmg` — no arch suffix. On an Intel Mac +// `process.arch` is `"x64"`, no file URL contains "x64", the find misses, and the fallback +// takes the FIRST entry. With an arm64-only manifest that is the ARM dmg. +// +// So ORDER IS THE FIX, not merely tidiness: the entry without an arch suffix must come first, +// because it is the one that can only ever be reached by that fallback. arm64 is found by +// substring wherever it sits. +// +// Usage: +// node scripts/release/merge-mac-update-manifest.mjs +// Exit: 0 on success or when there is nothing to merge (a release with no mac build), 1 when +// the inputs are present but unusable — a wrong manifest is worse than none. + +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +/** Parse the tiny subset of YAML electron-builder emits. No dependency, no surprises. */ +export function parseManifest(text) { + const src = String(text ?? ""); + const out = { version: "", files: [], path: "", sha512: "", releaseDate: "" }; + const top = /^(version|path|sha512|releaseDate):\s*'?([^'\n]*)'?\s*$/gm; + for (const m of src.matchAll(top)) out[m[1]] = m[2].trim(); + + // files: entries are ` - url: X` followed by indented `sha512:` / `size:` / `blockMapSize:`. + const fileBlocks = src.split(/^\s*-\s+url:\s*/m).slice(1); + for (const block of fileBlocks) { + const url = block.split("\n")[0].trim(); + if (!url) continue; + const grab = (k) => { + const m = new RegExp(`^\\s+${k}:\\s*(.+)$`, "m").exec(block); + return m ? m[1].trim() : ""; + }; + const entry = { url, sha512: grab("sha512"), size: grab("size") }; + const bms = grab("blockMapSize"); + if (bms) entry.blockMapSize = bms; + out.files.push(entry); + } + return out; +} + +/** True when the URL carries an explicit architecture electron-updater can match on. */ +export function hasArchSuffix(url) { + return /-(arm64|x64|universal)\./.test(String(url ?? "")); +} + +/** + * Merge parsed manifests into one, ordered so electron-updater resolves every arch. + * + * Entries WITHOUT an arch suffix come first, because the un-suffixed build is only ever + * reachable through electron-updater's `?? shift()` fallback. Suffixed entries are found by + * substring regardless of position. Duplicate URLs are collapsed, keeping the first. + */ +export function mergeManifests(manifests) { + const usable = (manifests ?? []).filter((m) => m && Array.isArray(m.files) && m.files.length); + if (usable.length === 0) return null; + + const seen = new Set(); + const files = []; + for (const m of usable) { + for (const f of m.files) { + if (!f.url || seen.has(f.url)) continue; + seen.add(f.url); + files.push(f); + } + } + // Stable partition: un-suffixed first, order otherwise preserved. + files.sort((a, b) => Number(hasArchSuffix(a.url)) - Number(hasArchSuffix(b.url))); + + const primary = files[0]; + const versions = [...new Set(usable.map((m) => m.version).filter(Boolean))]; + return { + version: versions[0] ?? "", + versionConflict: versions.length > 1 ? versions : null, + files, + // The legacy top-level fields older clients read must agree with the first entry. + path: primary.url, + sha512: primary.sha512, + releaseDate: usable.map((m) => m.releaseDate).filter(Boolean).sort().pop() ?? "", + }; +} + +export function renderManifest(merged) { + const lines = [`version: ${merged.version}`, "files:"]; + for (const f of merged.files) { + lines.push(` - url: ${f.url}`); + lines.push(` sha512: ${f.sha512}`); + lines.push(` size: ${f.size}`); + if (f.blockMapSize) lines.push(` blockMapSize: ${f.blockMapSize}`); + } + lines.push(`path: ${merged.path}`); + lines.push(`sha512: ${merged.sha512}`); + lines.push(`releaseDate: '${merged.releaseDate}'`); + return lines.join("\n") + "\n"; +} + +function main(argv) { + const [inDir, outDir] = argv; + if (!inDir || !outDir) { + process.stderr.write("usage: merge-mac-update-manifest.mjs \n"); + return 1; + } + if (!fs.existsSync(inDir)) { + process.stdout.write(`[merge-mac-manifest] ${inDir} does not exist — nothing to merge.\n`); + return 0; + } + + // Every latest-mac.yml under the per-artifact subdirectories. + const found = []; + const walk = (dir) => { + for (const e of fs.readdirSync(dir, { withFileTypes: true })) { + const p = path.join(dir, e.name); + if (e.isDirectory()) walk(p); + else if (e.name === "latest-mac.yml") found.push(p); + } + }; + walk(inDir); + + if (found.length === 0) { + process.stdout.write("[merge-mac-manifest] no latest-mac.yml found — nothing to merge.\n"); + return 0; + } + + const parsed = found.map((p) => parseManifest(fs.readFileSync(p, "utf8"))); + const merged = mergeManifests(parsed); + if (!merged) { + process.stderr.write( + `[merge-mac-manifest] found ${found.length} manifest(s) but none listed any file — ` + + `refusing to write a manifest that would send every Mac to nothing.\n` + ); + return 1; + } + if (merged.versionConflict) { + process.stderr.write( + `[merge-mac-manifest] the manifests disagree on version (${merged.versionConflict.join(", ")}) ` + + `— that means artifacts from two different builds are mixed. Refusing.\n` + ); + return 1; + } + + fs.mkdirSync(outDir, { recursive: true }); + fs.writeFileSync(path.join(outDir, "latest-mac.yml"), renderManifest(merged)); + process.stdout.write( + `[merge-mac-manifest] merged ${found.length} manifest(s) → ${merged.files.length} file(s), ` + + `first entry ${merged.path} (the arch electron-updater reaches by fallback).\n` + ); + return 0; +} + +if ( + process.argv[1] && + fs.realpathSync(process.argv[1]) === fs.realpathSync(fileURLToPath(import.meta.url)) +) { + process.exit(main(process.argv.slice(2))); +} diff --git a/scripts/release/sweep-stale-fragments.mjs b/scripts/release/sweep-stale-fragments.mjs new file mode 100644 index 0000000000..53e4aced6e --- /dev/null +++ b/scripts/release/sweep-stale-fragments.mjs @@ -0,0 +1,166 @@ +#!/usr/bin/env node +// Remove `changelog.d/` fragments whose bullet is ALREADY in CHANGELOG.md. +// +// WHY: the release reaches `main` as a single squash commit, so `main` still carries every +// fragment the reconciliation already folded in and deleted. The moment the release branch +// back-merges `main`, git faithfully restores all of them — 191 in the v3.8.49 run. Nothing +// is broken at that instant, which is the problem: the next aggregation folds them in a +// SECOND time and the section grows duplicate bullets that then have to be hand-unpicked. +// +// The rule is deliberately the simple one: a fragment is stale iff its content is already +// represented in CHANGELOG.md. Not "iff it belongs to an older version" — that needs the +// script to reason about which section owns it and gets the in-flight cycle wrong. Already +// present means redundant, wherever it is. +// +// Identity comes from the FILENAME (`-.md`), which is what that convention +// exists for, and NOT from the `#N` refs inside the bullet. Matching on any body ref looked +// right and was wrong — caught by running this against the live repo, where +// `changelog.d/features/8980-deprecate-gemini-cli-provider.md` was flagged stale because its +// bullet cites issue **#7034** for context, and #7034 shipped in an earlier cycle. That would +// have deleted an unreleased fragment and dropped its credit. A bullet routinely cites issues +// it merely references; only the filename says which PR the fragment *is*. +// +// Fragments with no number in the filename fall back to normalized text, and anything matching +// neither is always kept. Keeping a duplicate is a visible nuisance someone notices; deleting +// an unreleased bullet silently loses a contributor's credit — so every ambiguous case +// resolves toward keeping. +// +// Usage: +// node scripts/release/sweep-stale-fragments.mjs # report only +// node scripts/release/sweep-stale-fragments.mjs --apply # delete the stale ones +// Exit: 0 when nothing stale (or after a successful --apply), 1 when stale fragments remain +// in report mode — so the back-merge step can gate on it. + +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", ".."); +const FRAGMENT_DIRS = ["features", "fixes", "maintenance"]; + +/** Every `#N` in a piece of text. */ +export function refsIn(text) { + return [...String(text ?? "").matchAll(/#(\d+)/g)].map((m) => Number(m[1])); +} + +/** + * The fragment's own PR number, taken from the `-.md` filename convention. + * Returns null when the name carries no leading number — those fall back to text matching. + */ +export function prNumberOf(filename) { + const m = /^(\d+)-/.exec(String(filename ?? "")); + return m ? Number(m[1]) : null; +} + +/** + * Collapse a bullet to a comparable shape: drop markdown emphasis, links, refs and + * punctuation, fold whitespace, lowercase. Two bullets that say the same thing in slightly + * different markdown must collide here, or the text fallback is useless. + */ +export function normalizeBullet(text) { + return String(text ?? "") + .replace(/\[([^\]]+)\]\([^)]*\)/g, "$1") // [label](url) → label + .replace(/#\d+/g, "") // refs are handled separately + .replace(/[*_`~]/g, "") + .replace(/^[-*+]\s*/gm, "") + .replace(/[^\p{L}\p{N}\s]/gu, " ") + .replace(/\s+/g, " ") + .trim() + .toLowerCase(); +} + +/** + * Split fragments into `stale` (already in the changelog) and `keep`. + * + * Pure — takes the changelog text and the fragment list, touches no disk. That is what makes + * the dangerous direction (deleting a bullet that never shipped) testable. + */ +export function classifyFragments({ fragments = [], changelog = "" }) { + const changelogRefs = new Set(refsIn(changelog)); + // Index the changelog's own bullets by normalized text for the ref-less fallback. + const changelogBullets = new Set( + changelog + .split("\n") + .filter((l) => /^\s*[-*+]\s/.test(l)) + .map((l) => normalizeBullet(l)) + .filter((s) => s.length >= 12) // too-short lines collide by accident + ); + + const stale = []; + const keep = []; + + for (const frag of fragments) { + // The filename carries the fragment's OWN PR number. Body refs are context, not identity. + const own = prNumberOf(frag.name); + if (own !== null) { + if (changelogRefs.has(own)) { + stale.push({ ...frag, reason: `#${own} already in CHANGELOG.md`, matchedBy: "pr-number" }); + } else { + keep.push(frag); + } + continue; + } + const norm = normalizeBullet(frag.body); + if (norm.length >= 12 && changelogBullets.has(norm)) { + stale.push({ ...frag, reason: "identical bullet text already in CHANGELOG.md", matchedBy: "text" }); + } else { + keep.push(frag); + } + } + + return { stale, keep }; +} + +export function readFragments(root) { + const out = []; + for (const sub of FRAGMENT_DIRS) { + const dir = path.join(root, "changelog.d", sub); + if (!fs.existsSync(dir)) continue; + for (const name of fs.readdirSync(dir)) { + if (!name.endsWith(".md") || name === "README.md") continue; + const rel = path.join("changelog.d", sub, name); + out.push({ name, rel, body: fs.readFileSync(path.join(root, rel), "utf8") }); + } + } + return out; +} + +function main(argv) { + const apply = argv.includes("--apply"); + const changelog = fs.readFileSync(path.join(ROOT, "CHANGELOG.md"), "utf8"); + const fragments = readFragments(ROOT); + const { stale, keep } = classifyFragments({ fragments, changelog }); + + process.stdout.write( + `[sweep-stale-fragments] ${fragments.length} fragment(s): ${stale.length} already in ` + + `CHANGELOG.md, ${keep.length} pending.\n` + ); + + if (stale.length === 0) { + process.stdout.write("[sweep-stale-fragments] nothing to sweep.\n"); + return 0; + } + + const byRef = stale.filter((s) => s.matchedBy === "ref").length; + const byText = stale.length - byRef; + process.stdout.write(` matched by ref: ${byRef} · by text: ${byText}\n`); + for (const s of stale) process.stdout.write(` ${apply ? "removed" : "stale"}: ${s.rel} — ${s.reason}\n`); + + if (!apply) { + process.stdout.write( + "\n[sweep-stale-fragments] report only. Re-run with --apply to delete them.\n" + + "These are almost certainly fragments that a back-merge from main restored after the\n" + + "reconciliation had already folded them in — leaving them duplicates the bullets on the\n" + + "next aggregation.\n" + ); + return 1; + } + + for (const s of stale) fs.rmSync(path.join(ROOT, s.rel)); + process.stdout.write(`[sweep-stale-fragments] removed ${stale.length} stale fragment(s).\n`); + return 0; +} + +if (process.argv[1] && fs.realpathSync(process.argv[1]) === fs.realpathSync(fileURLToPath(import.meta.url))) { + process.exit(main(process.argv.slice(2))); +} diff --git a/skills/omni-auth/SKILL.md b/skills/omni-auth/SKILL.md index f010763008..ba14739107 100644 --- a/skills/omni-auth/SKILL.md +++ b/skills/omni-auth/SKILL.md @@ -36,6 +36,37 @@ curl -X POST https://localhost:20128/api/auth/logout \ -d '{}' ``` +### GET /api/auth/oidc/login + +Start OIDC login for the dashboard admin gate + +Builds an authorization URL from the configured OIDC issuer/client (discovered +via `{issuer}/.well-known/openid-configuration`, falling back to `{issuer}/authorize`), +sets a short-lived `oidc_state` cookie, and redirects the browser. Password login +remains available as a fallback while OIDC is enabled. + + +```bash +curl https://localhost:20128/api/auth/oidc/login \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" +``` + +### GET /api/auth/oidc/callback + +Complete OIDC login for the dashboard admin gate + +Validates the `state` cookie, exchanges the authorization `code` for tokens, +verifies the ID token against the issuer's JWKS (audience = client id), and — +if `oidcAllowedSubjects` is configured — checks the token's `sub`/`email` against +that allowlist. On success it mints the same 30-day `auth_token` dashboard-session +JWT used by password login and redirects to `/dashboard`. + + +```bash +curl https://localhost:20128/api/auth/oidc/callback \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" +``` + ## Payloads See the full OpenAPI specification at `GET /api/openapi/spec` or `docs/openapi.yaml` for detailed request/response schemas. diff --git a/skills/omni-inference/SKILL.md b/skills/omni-inference/SKILL.md index 40079c16f9..67de72868f 100644 --- a/skills/omni-inference/SKILL.md +++ b/skills/omni-inference/SKILL.md @@ -219,6 +219,87 @@ curl https://localhost:20128/api/v1/providers/{provider}/models \ -H "Authorization: Bearer $OMNIROUTE_TOKEN" ``` +### GET /api/v1/management/proxy-subscriptions + +List proxy subscriptions + +Lists all operator-supplied proxy subscription links. Also starts the background auto-refresh scheduler (idempotent) so enabled subscriptions stay in sync. Credentials embedded in `url` are redacted in the response. + +```bash +curl https://localhost:20128/api/v1/management/proxy-subscriptions \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" +``` + +### POST /api/v1/management/proxy-subscriptions + +Create a proxy subscription + +Creates a subscription record. If `mode` is `rule`, at least one entry in `ruleProviders` is required. `updateIntervalMinutes` defaults to 60 and `enabled` defaults to `false` when omitted or not exactly `true`. + +```bash +curl -X POST https://localhost:20128/api/v1/management/proxy-subscriptions \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" + -H "Content-Type: application/json" \ + -d '{}' +``` + +### GET /api/v1/management/proxy-subscriptions/{id} + +Get a proxy subscription + +```bash +curl https://localhost:20128/api/v1/management/proxy-subscriptions/{id} \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" +``` + +### PATCH /api/v1/management/proxy-subscriptions/{id} + +Update a proxy subscription + +Partial update — only fields present in the body are changed (name/url/mode/ruleProviders/localCoreEndpoint/updateIntervalMinutes/enabled). + +```bash +curl -X PATCH https://localhost:20128/api/v1/management/proxy-subscriptions/{id} \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" + -H "Content-Type: application/json" \ + -d '{}' +``` + +### DELETE /api/v1/management/proxy-subscriptions/{id} + +Delete a proxy subscription + +Removes the subscription record and unbinds/drops its synced proxy_registry rows. + +```bash +curl -X DELETE https://localhost:20128/api/v1/management/proxy-subscriptions/{id} \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" +``` + +### GET /api/v1/management/proxy-subscriptions/{id}/nodes + +Get a subscription's last-parsed node summary + +Returns the last-parsed node list without re-fetching the (possibly slow) subscription URL. + +```bash +curl https://localhost:20128/api/v1/management/proxy-subscriptions/{id}/nodes \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" +``` + +### POST /api/v1/management/proxy-subscriptions/{id}/refresh + +Refresh a proxy subscription + +Re-fetches and re-parses the subscription URL, syncs its nodes into `proxy_registry`, and (re)binds the pool. + +```bash +curl -X POST https://localhost:20128/api/v1/management/proxy-subscriptions/{id}/refresh \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" + -H "Content-Type: application/json" \ + -d '{}' +``` + ### POST /api/v1/ocr Document OCR diff --git a/skills/omni-usage-logs/SKILL.md b/skills/omni-usage-logs/SKILL.md index 120e6d8106..dd090853a7 100644 --- a/skills/omni-usage-logs/SKILL.md +++ b/skills/omni-usage-logs/SKILL.md @@ -110,6 +110,33 @@ curl -X POST https://localhost:20128/api/usage/budget \ -d '{}' ``` +### GET /api/usage/cache-health + +Get prompt-cache health summary + +Summarizes the `write/read` cache ratio from `call_logs` for a time window: +distribution (p50/p90/p99/max of cache-write tokens), warm/cold/rewrite/uncached +call counts, the "heavy write" outlier share (10x the window median, floored at +1024 tokens — Anthropic's cache-creation minimum), and a per-model breakdown. +Only successful (`status = 200`) calls with a non-null cache column are counted. + + +```bash +curl https://localhost:20128/api/usage/cache-health \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" +``` + +### GET /api/usage/model-latency-stats + +Get per-model/provider latency statistics + +Aggregates `usage_history` rows into per-(provider, model) latency stats (avg/p50/p95/p99, std-dev, TTFT, tokens/sec) over a rolling window. Falls back from successful-only to all-sample rows when the successful count is below `minSamples`. + +```bash +curl https://localhost:20128/api/usage/model-latency-stats \ + -H "Authorization: Bearer $OMNIROUTE_TOKEN" +``` + ## Payloads See the full OpenAPI specification at `GET /api/openapi/spec` or `docs/openapi.yaml` for detailed request/response schemas. diff --git a/src/app/(dashboard)/dashboard/HomePageClient.tsx b/src/app/(dashboard)/dashboard/HomePageClient.tsx index 24cec3140a..3b1e2a91da 100644 --- a/src/app/(dashboard)/dashboard/HomePageClient.tsx +++ b/src/app/(dashboard)/dashboard/HomePageClient.tsx @@ -104,6 +104,12 @@ function mergeUpdateStep(steps: UpdateStep[], nextStep: UpdateStep) { return next; } +// Quick-start link classes, extracted so each still fits on one line with +// prefetch={false} (#8281) — this file is size-frozen. +const INLINE_LINK = "text-primary hover:underline"; +const DOCS_LINK = + "hidden sm:inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium border border-border text-text-muted hover:text-text-main hover:bg-bg-subtle transition-colors"; + export default function HomePageClient({ machineId }: HomePageClientProps) { const router = useRouter(); const isElectron = useIsElectron(); @@ -1088,10 +1094,7 @@ export default function HomePageClient({ machineId }: HomePageClientProps) {

{t("quickStart")}

{t("quickStartDesc")}

- + menu_book {t("fullDocs")} @@ -1109,7 +1112,8 @@ export default function HomePageClient({ machineId }: HomePageClientProps) { endpoint: (chunks) => ( {chunks} @@ -1127,7 +1131,7 @@ export default function HomePageClient({ machineId }: HomePageClientProps) {

{t.rich("step2Desc", { providers: (chunks) => ( - + {chunks} ), @@ -1155,12 +1159,12 @@ export default function HomePageClient({ machineId }: HomePageClientProps) {

{t.rich("step4Desc", { logs: (chunks) => ( - + {chunks} ), analytics: (chunks) => ( - + {chunks} ), diff --git a/src/app/(dashboard)/dashboard/logs/page.tsx b/src/app/(dashboard)/dashboard/logs/page.tsx index fa9801de34..cbe0d4f340 100644 --- a/src/app/(dashboard)/dashboard/logs/page.tsx +++ b/src/app/(dashboard)/dashboard/logs/page.tsx @@ -28,7 +28,11 @@ function logsText( function LogsPageContent() { const searchParams = useSearchParams(); - const initialId = searchParams.get("id"); + // Read ONCE: #6830 fixed the detail modal reopening on first close by freezing this + // value, and the #8354 page rewrite regressed it by reading the live searchParams on + // every render — the prop flips mid-session and re-fires the child's deep-link effect + // exactly when the modal closes. + const [initialId] = useState(() => searchParams.get("id")); const [showExport, setShowExport] = useState(false); const [exporting, setExporting] = useState(false); diff --git a/src/app/api/providers/[id]/refresh/route.ts b/src/app/api/providers/[id]/refresh/route.ts index a6a0847c5c..e171d9f093 100644 --- a/src/app/api/providers/[id]/refresh/route.ts +++ b/src/app/api/providers/[id]/refresh/route.ts @@ -94,12 +94,30 @@ export async function POST(_request: Request, { params }: { params: Promise<{ id newCredentials.error === "refresh_token_reused" || newCredentials.error === "invalid_grant" ) { + // A deprecated provider reuses the unrecoverable contract so callers stop + // retrying, but "Refresh token expired" would be a lie: the token is fine, the + // provider is gone. Say that, and say where to go — the operator otherwise + // re-authenticates in a loop against something that no longer exists. + const isDeprecated = newCredentials.code === "provider_deprecated"; + const reason = + isDeprecated && typeof newCredentials.reason === "string" + ? newCredentials.reason + : "Refresh token expired. Please re-authenticate this account."; await updateProviderConnection(id, { - testStatus: "invalid", - lastError: "Refresh token expired. Please re-authenticate this account.", + testStatus: isDeprecated ? "expired" : "invalid", + lastError: reason, + ...(isDeprecated + ? { lastErrorType: "provider_deprecated", errorCode: "provider_deprecated" } + : {}), }); return NextResponse.json( - { error: "Token refresh failed — provider returned no new token", requiresReauth: true }, + { + error: isDeprecated + ? "This provider was deprecated and can no longer be refreshed" + : "Token refresh failed — provider returned no new token", + requiresReauth: true, + ...(isDeprecated ? { deprecated: true, migrateTo: newCredentials.migrateTo } : {}), + }, { status: 401 } ); } diff --git a/src/app/api/v1/chat/completions/route.ts b/src/app/api/v1/chat/completions/route.ts index f8f92b308e..77eed06416 100644 --- a/src/app/api/v1/chat/completions/route.ts +++ b/src/app/api/v1/chat/completions/route.ts @@ -1,7 +1,9 @@ +import { z } from "zod"; import { CORS_HEADERS, handleCorsOptions } from "@/shared/utils/cors"; import { callCloudWithMachineId } from "@/shared/utils/cloud"; import { handleChat } from "@/sse/handlers/chat"; import { generateRequestId } from "@/shared/utils/requestId"; +import { errorResponse } from "@omniroute/open-sse/utils/error.ts"; import { initTranslators } from "@omniroute/open-sse/translator/index.ts"; import { createInjectionGuard } from "@/middleware/promptInjectionGuard"; import { acceptHeaderForcesStream } from "@omniroute/open-sse/utils/aiSdkCompat.ts"; @@ -44,6 +46,28 @@ function isRecord(value: unknown): value is Record { return value !== null && typeof value === "object" && !Array.isArray(value); } +// Minimal request-shape validation (Rule #7 / T06 gate). This is the hottest path in the +// proxy, and the body is already parsed exactly once above into `parsedBody` (see the +// #4380/#7862 comment on the single `request.json()` call) — so this only runs `.safeParse()` +// over that already-parsed object, it does NOT read the body again. +// +// Deliberately permissive: `src/sse/handlers/chat.ts` (deeper in `handleChat`) owns the real +// validation of this payload — messages/model/temperature/top_p/max_tokens/n — and accepts +// shapes this schema must not newly reject, e.g. a `model` that is entirely absent (resolved +// later via `input`/antigravity) or `null`, and message `role`s such as `"developer"` (see +// `open-sse/services/roleNormalizer.ts`) that a stricter enum would exclude. `.passthrough()` +// keeps every other field (stream, tools, reasoning, provider-specific extras, ...) intact. +// This schema only asserts what the route already assumes before handing `parsedBody` to +// `handleChat`: a non-null object, `model` a nullable string when present, `messages` an +// array when present — so `.safeParse()` failing here is always a shape the deep validation +// would already have rejected with its own 400, never a new rejection. +const chatCompletionsRouteShapeSchema = z + .object({ + model: z.string().nullable().optional(), + messages: z.array(z.unknown()).optional(), + }) + .passthrough(); + /** * Handle CORS preflight */ @@ -103,6 +127,18 @@ export async function POST(request) { try { parsedBody = await request.json().catch(() => null); if (parsedBody) { + // Route-level shape gate (T06) — validates the object already parsed above; it + // never reads the request body a second time. See chatCompletionsRouteShapeSchema + // for why this stays scoped to record-shaped bodies and deliberately permissive. + if (isRecord(parsedBody)) { + const shapeCheck = chatCompletionsRouteShapeSchema.safeParse(parsedBody); + if (!shapeCheck.success) { + const issue = shapeCheck.error.issues[0]; + const field = issue?.path?.length ? issue.path.join(".") : "body"; + return finishAdmission(errorResponse(400, `${field}: ${issue?.message ?? "Invalid request"}`)); + } + } + const structuralAdmission = admitChatStructure(parsedBody, admission.lease); if (structuralAdmission.admit === false) { admission.lease?.release(); diff --git a/src/app/api/v1/management/proxy-subscriptions/[id]/route.ts b/src/app/api/v1/management/proxy-subscriptions/[id]/route.ts index c19b5d6b9c..b303eef6ba 100644 --- a/src/app/api/v1/management/proxy-subscriptions/[id]/route.ts +++ b/src/app/api/v1/management/proxy-subscriptions/[id]/route.ts @@ -5,7 +5,8 @@ import { updateSubscription, deleteSubscription, redactSubscriptionUrl, - type ProxySubscriptionPayload, + proxySubscriptionUpdateSchema, + firstIssueMessage, } from "@/lib/proxySubscription"; type RouteCtx = { params: Promise<{ id: string }> }; @@ -36,26 +37,12 @@ export async function PATCH(request: Request, ctx: RouteCtx) { try { const { id } = await ctx.params; const body = await request.json().catch(() => null); - if (!body || typeof body !== "object") { - return Response.json({ error: "Invalid JSON body" }, { status: 400 }); - } - const b = body as Record; - const payload: Partial = {}; - if (typeof b.name === "string") payload.name = b.name.trim(); - if (typeof b.url === "string") payload.url = b.url.trim(); - if (typeof b.mode === "string") payload.mode = b.mode === "rule" ? "rule" : "global"; - if (typeof b.enabled === "boolean") payload.enabled = b.enabled; - if (typeof b.localCoreEndpoint === "string") { - payload.localCoreEndpoint = b.localCoreEndpoint.trim() || null; - } - if (typeof b.updateIntervalMinutes === "number") { - payload.updateIntervalMinutes = b.updateIntervalMinutes; - } - if (Array.isArray(b.ruleProviders)) { - payload.ruleProviders = b.ruleProviders.filter((x) => typeof x === "string"); + const parsed = proxySubscriptionUpdateSchema.safeParse(body); + if (!parsed.success) { + return Response.json({ error: firstIssueMessage(parsed.error) }, { status: 400 }); } - const updated = await updateSubscription(id, payload); + const updated = await updateSubscription(id, parsed.data); if (!updated) return Response.json({ error: "Subscription not found" }, { status: 404 }); return Response.json({ ...updated, url: redactSubscriptionUrl(updated.url) }); } catch (error) { diff --git a/src/app/api/v1/management/proxy-subscriptions/route.ts b/src/app/api/v1/management/proxy-subscriptions/route.ts index 4ba9c68d8f..5b9554fa92 100644 --- a/src/app/api/v1/management/proxy-subscriptions/route.ts +++ b/src/app/api/v1/management/proxy-subscriptions/route.ts @@ -5,7 +5,8 @@ import { createSubscription, startSubscriptionScheduler, redactSubscriptionUrl, - type ProxySubscriptionPayload, + proxySubscriptionCreateSchema, + firstIssueMessage, } from "@/lib/proxySubscription"; /** @@ -32,51 +33,16 @@ export async function GET(request: Request) { } } -function parsePayload(body: unknown): ProxySubscriptionPayload | { error: string } { - if (!body || typeof body !== "object") return { error: "Invalid JSON body" }; - const b = body as Record; - const name = typeof b.name === "string" ? b.name.trim() : ""; - const url = typeof b.url === "string" ? b.url.trim() : ""; - if (!name) return { error: "name is required" }; - if (!url) return { error: "url is required" }; - - const mode = b.mode === "rule" ? "rule" : "global"; - let ruleProviders: string[] | null = null; - if (Array.isArray(b.ruleProviders)) { - ruleProviders = b.ruleProviders.filter((x) => typeof x === "string"); - } - if (mode === "rule" && (!ruleProviders || ruleProviders.length === 0)) { - return { error: "ruleProviders is required when mode is 'rule'" }; - } - - const localCoreEndpoint = - typeof b.localCoreEndpoint === "string" && b.localCoreEndpoint.trim() - ? b.localCoreEndpoint.trim() - : null; - const updateIntervalMinutes = Number(b.updateIntervalMinutes) || 60; - const enabled = b.enabled === true; - - return { - name, - url, - mode, - ruleProviders, - localCoreEndpoint, - updateIntervalMinutes, - enabled, - }; -} - export async function POST(request: Request) { const authError = await requireManagementAuth(request); if (authError) return authError; try { const body = await request.json().catch(() => null); - const parsed = parsePayload(body); - if ("error" in parsed) { - return Response.json({ error: parsed.error }, { status: 400 }); + const parsed = proxySubscriptionCreateSchema.safeParse(body); + if (!parsed.success) { + return Response.json({ error: firstIssueMessage(parsed.error) }, { status: 400 }); } - const created = await createSubscription(parsed); + const created = await createSubscription(parsed.data); return Response.json({ ...created, url: redactSubscriptionUrl(created.url) }, { status: 201 }); } catch (error) { return createErrorResponseFromUnknown(error, "Failed to create proxy subscription"); diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index 662ef34f95..b3a61c40d3 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -3704,7 +3704,7 @@ "modelsCount": "النماذج: {count, plural, one {نموذج واحد} other {# نماذج}}", "sectionTitle": "سطح التكامل", "sectionDescription": "واجهات برمجة التطبيقات المتوافقة مع OpenAI ونقاط نهاية البروتوكول التشغيلية", - "tabApis": "واجهات برمجة تطبيقات متوافقة مع OpenAI", + "tabApis": "__MISSING__:APIs", "tabProtocols": "البروتوكولات", "tabsAria": "أقسام نقطة النهاية", "protocolsTitle": "البروتوكولات", @@ -6748,7 +6748,7 @@ "howPricingWorks": "كيف يعمل التسعير", "cacheWrite": "كتابة ذاكرة التخزين المؤقت", "unsaved": "غير محفوظ", - "resetDefaults": "إعادة تعيين الإعدادات الافتراضية", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "حفظ المزود", "model": "نموذج", "models": "نماذج", diff --git a/src/i18n/messages/az.json b/src/i18n/messages/az.json index fe43d5855c..418c3bc0eb 100644 --- a/src/i18n/messages/az.json +++ b/src/i18n/messages/az.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → Proqram → Yerli Yaddaş → https://t3.chat açın, 'convex-session-id' kopyalayın. Sonra DevTools → Network açın, istənilən söhbət sorğusundan tam kuki başlığını kopyalayın. Hər iki dəyəri aşağıdakı sahələrə yapışdırın.", "t3ChatWebCookiePlaceholder": "konveks-sessiya-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Hide extra Claude usage rows reported by some providers when they duplicate primary token accounting.", - "blockClaudeExtraUsageLabel": "Block duplicate Claude usage rows", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Müvəqqəti soyuma müddətini atlayın ki, bu bağlantı bərpa edilə bilən xətalardan sonra belə uyğun qalsın (bloklanmış/vaxtı keçmiş kimi terminal vəziyyətlər hələ də tətbiq olunur).", "disableCoolingLabel": "Bu bağlantı üçün soyuma müddətini söndürün", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build kimlik doğrulaması idxal et", "zedImportTitle": "Zed Keychain-dən idxal et", "zedImportDescription": "Zed IDE tərəfindən OS keychain-də saxlanılan AI provayder etibarnamələrini (OpenAI, Anthropic, Google, Mistral, xAI) aşkar edin və onları bağlantı kimi idxal edin. Zed IDE bu cihazda quraşdırılmalıdır.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Keychain-də heç bir Zed etibarnaməsi tapılmadı", "zedUnsupportedCredentials": "{count} keychain etibarnaməsi tapıldı, lakin heç biri dəstəklənən provayderlərə uyğun gəlmədi", "zedManualTitle": "Əl ilə token idxalı", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/bg.json b/src/i18n/messages/bg.json index 09fbd55fa8..82295b9023 100644 --- a/src/i18n/messages/bg.json +++ b/src/i18n/messages/bg.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Интеграционна повърхност", "sectionDescription": "Съвместими с OpenAI API и крайни точки на оперативния протокол", - "tabApis": "API, съвместими с OpenAI", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Протоколи", "tabsAria": "Раздели на крайните точки", "protocolsTitle": "Протоколи", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Отворете t3.chat → DevTools → Приложение → Локално хранилище → https://t3.chat, копирайте 'convex-session-id'. След това отворете DevTools → Network, копирайте пълния хедър на Cookie от всяка заявка за чат. Поставете и двете стойности в полетата по-долу.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Пропускане на временния период на изчакване, така че тази връзка да остане допустима дори след възстановими грешки (терминалните състояния като блокиран/изтекъл все още се прилагат).", "disableCoolingLabel": "Деактивиране на периода на изчакване за тази връзка", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Импортиране на Grok Build оторизация", "zedImportTitle": "Импортиране от Zed Keychain", "zedImportDescription": "Открийте идентификационни данни за AI доставчици (OpenAI, Anthropic, Google, Mistral, xAI), съхранени от Zed IDE в ключодържателя на ОС, и ги импортирайте като връзки. Zed IDE трябва да бъде инсталиран на тази машина.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "В ключодържателя не са намерени идентификационни данни за Zed", "zedUnsupportedCredentials": "Намерени са {count} идентификационни данни в ключодържателя, но нито едни не съвпадат с поддържаните доставчици", "zedManualTitle": "Ръчно импортиране на токен", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Как работи ценообразуването", "cacheWrite": "Кеш запис", "unsaved": "незаписан", - "resetDefaults": "Нулиране на настройките по подразбиране", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Запазване на доставчика", "model": "Модел", "models": "модели", diff --git a/src/i18n/messages/bn.json b/src/i18n/messages/bn.json index 295b6d945b..87bddc2480 100644 --- a/src/i18n/messages/bn.json +++ b/src/i18n/messages/bn.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → Application → Local Storage → https://t3.chat খুলুন, 'convex-session-id' কপি করুন। তারপর DevTools → Network খুলুন, যেকোনো চ্যাট অনুরোধ থেকে সম্পূর্ণ কুকি হেডারটি কপি করুন। নীচের ক্ষেত্রগুলিতে উভয় মান আটকান।", "t3ChatWebCookiePlaceholder": "উত্তল-সেশন-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "অস্থায়ী কুলডাউন এড়িয়ে যান যাতে পুনরুদ্ধারযোগ্য ত্রুটির পরেও এই সংযোগটি যোগ্য থাকে (নিষিদ্ধ/মেয়াদোত্তীর্ণের মতো টার্মিনাল অবস্থাগুলি এখনও প্রযোজ্য)।", "disableCoolingLabel": "এই সংযোগের জন্য কুলডাউন নিষ্ক্রিয় করুন", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build auth ইম্পোর্ট করুন", "zedImportTitle": "Zed Keychain থেকে ইম্পোর্ট করুন", "zedImportDescription": "OS কীচেইনে Zed IDE দ্বারা সংরক্ষিত AI প্রোভাইডার ক্রেডেনশিয়াল (OpenAI, Anthropic, Google, Mistral, xAI) খুঁজুন এবং সেগুলিকে কানেকশন হিসেবে ইম্পোর্ট করুন। এই মেশিনে Zed IDE ইনস্টল করা থাকতে হবে।", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "কীচেইনে কোনো Zed ক্রেডেনশিয়াল পাওয়া যায়নি", "zedUnsupportedCredentials": "{count}টি কীচেইন ক্রেডেনশিয়াল পাওয়া গেছে, কিন্তু কোনোটিই সমর্থিত প্রোভাইডারের সাথে মেলেনি", "zedManualTitle": "ম্যানুয়াল টোকেন ইম্পোর্ট", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/cs.json b/src/i18n/messages/cs.json index 83f3310e7d..e3bb0fb746 100644 --- a/src/i18n/messages/cs.json +++ b/src/i18n/messages/cs.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# modelů}}", "sectionTitle": "Integrační plocha", "sectionDescription": "OpenAI-compatible API operační protokoly koncového bodu", - "tabApis": "OpenAI-compatible API", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protokoly", "tabsAria": "Koncové sekce", "protocolsTitle": "Protokoly", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Otevřete t3.chat → DevTools → Aplikace → Místní úložiště → https://t3.chat, zkopírujte 'convex-session-id'. Poté otevřete DevTools → Network, zkopírujte celou hlavičku cookie z libovolné žádosti o chat. Obě hodnoty vložte do polí níže.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Přeskočit přechodný cooldown, aby toto připojení zůstalo způsobilé i po obnovitelných chybách (konečné stavy jako zablokováno/vypršelo stále platí).", "disableCoolingLabel": "Zakázat cooldown pro toto připojení", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Importovat ověření Grok Build", "zedImportTitle": "Importovat z klíčenky Zed", "zedImportDescription": "Vyhledejte přihlašovací údaje poskytovatelů AI (OpenAI, Anthropic, Google, Mistral, xAI) uložené editorem Zed IDE v klíčence operačního systému a importujte je jako připojení. Na tomto počítači musí být nainstalován Zed IDE.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "V klíčence nebyly nalezeny žádné přihlašovací údaje pro Zed", "zedUnsupportedCredentials": "Nalezeno {count} přihlašovacích údajů v klíčence, ale žádný neodpovídá podporovaným poskytovatelům", "zedManualTitle": "Ruční import tokenu", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Jak funguje stanovování cen", "cacheWrite": "Zápis do mezipaměti", "unsaved": "neuloženo", - "resetDefaults": "Obnovit výchozí nastavení", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Uložit poskytovatele", "model": "Model", "models": "modely", diff --git a/src/i18n/messages/da.json b/src/i18n/messages/da.json index 1f824bdde1..ce03c456a3 100644 --- a/src/i18n/messages/da.json +++ b/src/i18n/messages/da.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integrationsoverflade", "sectionDescription": "OpenAI-kompatible API'er og operationelle protokolendepunkter", - "tabApis": "OpenAI-kompatible API'er", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protokoller", "tabsAria": "Endepunktsafsnit", "protocolsTitle": "Protokoller", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Åbn t3.chat → DevTools → Application → Local Storage → https://t3.chat, kopier 'convex-session-id'. Åbn derefter DevTools → Netværk, kopier den fulde Cookie-header fra enhver chatanmodning. Indsæt begge værdier i felterne nedenfor.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Skip the transient cooldown so this connection stays eligible even after recoverable errors (terminal states like banned/expired still apply).", "disableCoolingLabel": "Deaktiver afkøling for denne forbindelse", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Importer Grok Build-godkendelse", "zedImportTitle": "Importer fra Zed Keychain", "zedImportDescription": "Find AI-udbyderoplysninger (OpenAI, Anthropic, Google, Mistral, xAI) gemt af Zed IDE i OS-nøgleringen og importer dem som forbindelser. Zed IDE skal være installeret på denne maskine.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Ingen Zed-legitimationsoplysninger fundet i nøgleringen", "zedUnsupportedCredentials": "Fandt {count} legitimationsoplysning(er) i nøgleringen, men ingen matchede understøttede udbydere", "zedManualTitle": "Manuel token-import", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Hvordan prissætning fungerer", "cacheWrite": "Cache skriv", "unsaved": "ikke gemt", - "resetDefaults": "Nulstil standarder", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Gem udbyder", "model": "Model", "models": "modeller", diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index fafcb0d1a0..abed70d555 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integrationsoberfläche", "sectionDescription": "OpenAI-kompatible APIs und Betriebsprotokoll-Endpunkte", - "tabApis": "OpenAI-kompatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protokolle", "tabsAria": "Endpunktabschnitte", "protocolsTitle": "Protokolle", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Öffnen Sie t3.chat → DevTools → Anwendung → Lokaler Speicher → https://t3.chat, kopieren Sie „convex-session-id“. Öffnen Sie dann DevTools → Netzwerk und kopieren Sie den vollständigen Cookie-Header aus jeder Chat-Anfrage. Fügen Sie beide Werte in die Felder unten ein.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Vorübergehende Abklingzeit überspringen, damit diese Verbindung auch nach behebbaren Fehlern verfügbar bleibt (endgültige Zustände wie gesperrt/abgelaufen gelten weiterhin).", "disableCoolingLabel": "Abklingzeit für diese Verbindung deaktivieren", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build-Authentifizierung importieren", "zedImportTitle": "Aus Zed-Schlüsselbund importieren", "zedImportDescription": "Von der Zed IDE im Betriebssystem-Schlüsselbund gespeicherte KI-Anbieter-Anmeldedaten (OpenAI, Anthropic, Google, Mistral, xAI) erkennen und als Verbindungen importieren. Die Zed IDE muss auf diesem Computer installiert sein.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Keine Zed-Anmeldedaten im Schlüsselbund gefunden", "zedUnsupportedCredentials": "{count} Schlüsselbund-Anmeldedaten gefunden, aber keine stimmten mit unterstützten Anbietern überein", "zedManualTitle": "Manueller Token-Import", @@ -6748,7 +6748,7 @@ "howPricingWorks": "So funktioniert die Preisgestaltung", "cacheWrite": "Cache-Schreiben", "unsaved": "nicht gespeichert", - "resetDefaults": "Standardeinstellungen zurücksetzen", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Anbieter speichern", "model": "Modell", "models": "Modelle", diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index c80d2a6253..7d7e8cc49f 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Superficie de integración", "sectionDescription": "API compatibles con OpenAI y puntos finales de protocolo operativo", - "tabApis": "API compatibles con OpenAI", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocolos", "tabsAria": "Secciones de punto final", "protocolsTitle": "Protocolos", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Abra t3.chat → DevTools → Aplicación → Almacenamiento local → https://t3.chat, copie 'convex-session-id'. Luego abra DevTools → Red, copie el encabezado completo de la cookie de cualquier solicitud de chat. Pegue ambos valores en los campos siguientes.", "t3ChatWebCookiePlaceholder": "ID-sesión-convexa=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Skip the transient cooldown so this connection stays eligible even after recoverable errors (terminal states like banned/expired still apply).", "disableCoolingLabel": "Disable cooldown for this connection", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Import Grok Build auth", "zedImportTitle": "Import from Zed Keychain", "zedImportDescription": "Discover AI provider credentials (OpenAI, Anthropic, Google, Mistral, xAI) stored by Zed IDE in the OS keychain and import them as connections. Zed IDE must be installed on this machine.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", "zedImportSuccess": "Se han importado {credentials} credencial(es) de Zed para {providers} proveedor(es)", - "zedImporting": "Zed Importing", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "No Zed credentials found in the keychain", "zedUnsupportedCredentials": "Found {count} keychain credential(s), but none matched supported providers", "zedManualTitle": "Manual Token Import", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Cómo funcionan los precios", "cacheWrite": "Escritura en caché", "unsaved": "no salvo", - "resetDefaults": "Restablecer valores predeterminados", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Guardar proveedor", "model": "modelo", "models": "modelos", diff --git a/src/i18n/messages/fa.json b/src/i18n/messages/fa.json index eaa78af1c1..a07a9fc9a4 100644 --- a/src/i18n/messages/fa.json +++ b/src/i18n/messages/fa.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → Application → Local Storage → https://t3.chat را باز کنید، «convex-session-id» را کپی کنید. سپس DevTools → Network را باز کنید، هدر کامل کوکی را از هر درخواست چت کپی کنید. هر دو مقدار را در فیلدهای زیر قرار دهید.", "t3ChatWebCookiePlaceholder": "محدب-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "نادیده گرفتن دوره خنک‌سازی گذرا تا این اتصال حتی پس از خطاهای قابل بازیابی واجد شرایط باقی بماند (حالت‌های نهایی مانند مسدود شده/منقضی شده همچنان اعمال می‌شوند).", "disableCoolingLabel": "غیرفعال کردن دوره خنک‌سازی برای این اتصال", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "وارد کردن اطلاعات احراز هویت Grok Build", "zedImportTitle": "وارد کردن از Zed Keychain", "zedImportDescription": "اعتبارنامه‌های ارائه‌دهنده هوش مصنوعی (OpenAI، Anthropic، Google، Mistral، xAI) ذخیره‌شده توسط Zed IDE در keychain سیستم‌عامل را شناسایی کرده و آن‌ها را به عنوان اتصال وارد کنید. Zed IDE باید روی این دستگاه نصب باشد.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "هیچ اعتبارنامه Zed در keychain یافت نشد", "zedUnsupportedCredentials": "تعداد {count} اعتبارنامه keychain یافت شد، اما هیچ‌کدام با ارائه‌دهندگان پشتیبانی‌شده مطابقت نداشتند", "zedManualTitle": "وارد کردن دستی توکن", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/fi.json b/src/i18n/messages/fi.json index 184c31500a..a4f3239898 100644 --- a/src/i18n/messages/fi.json +++ b/src/i18n/messages/fi.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integrointipinta", "sectionDescription": "OpenAI-yhteensopivat API:t ja toimintaprotokollan päätepisteet", - "tabApis": "OpenAI-yhteensopivat sovellusliittymät", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protokollat", "tabsAria": "Päätepisteen osat", "protocolsTitle": "Protokollat", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Avaa t3.chat → DevTools → Sovellus → Paikallinen tallennus → https://t3.chat, kopioi 'convex-session-id'. Avaa sitten DevTools → Network, kopioi koko eväste-otsikko mistä tahansa chat-pyynnöstä. Liitä molemmat arvot alla oleviin kenttiin.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Ohita tilapäinen jäädytysaika, jotta tämä yhteys pysyy käytettävissä myös palautettavien virheiden jälkeen (lopulliset tilat, kuten estetty/vanhentunut, ovat edelleen voimassa).", "disableCoolingLabel": "Poista jäädytysaika käytöstä tälle yhteydelle", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Tuo Grok Build -tunnistautumistiedot", "zedImportTitle": "Tuo Zed-avainnipusta", "zedImportDescription": "Hae Zed IDE:n käyttöjärjestelmän avainnippuun tallentamat tekoälytarjoajien tunnistetiedot (OpenAI, Anthropic, Google, Mistral, xAI) ja tuo ne yhteyksinä. Zed IDE:n on oltava asennettuna tälle koneelle.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Avainnipusta ei löytynyt Zed-tunnistetietoja", "zedUnsupportedCredentials": "Löytyi {count} avainnipun tunnistetieto(a), mutta mikään niistä ei vastannut tuettuja palveluntarjoajia", "zedManualTitle": "Manuaalinen tokenin tuonti", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Kuinka hinnoittelu toimii", "cacheWrite": "Välimuistin kirjoitus", "unsaved": "tallentamaton", - "resetDefaults": "Palauta oletukset", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Tallenna palveluntarjoaja", "model": "Malli", "models": "mallit", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index f68757aeed..c963fa1fcb 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Surface d'intégration", "sectionDescription": "API compatibles OpenAI et points de terminaison du protocole opérationnel", - "tabApis": "API compatibles OpenAI", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocoles", "tabsAria": "Sections de point de terminaison", "protocolsTitle": "Protocoles", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Ouvrez t3.chat → DevTools → Application → Stockage local → https://t3.chat, copiez 'convex-session-id'. Ensuite, ouvrez DevTools → Réseau, copiez l'en-tête complet du cookie de toute demande de chat. Collez les deux valeurs dans les champs ci-dessous.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Ignorer le délai de récupération temporaire pour que cette connexion reste éligible même après des erreurs récupérables (les états terminaux comme banni/expiré s'appliquent toujours).", "disableCoolingLabel": "Désactiver le délai de récupération pour cette connexion", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Importer l'authentification Grok Build", "zedImportTitle": "Importer depuis le trousseau Zed", "zedImportDescription": "Détectez les identifiants de fournisseurs d'IA (OpenAI, Anthropic, Google, Mistral, xAI) stockés par Zed IDE dans le trousseau d'accès du système d'exploitation et importez-les en tant que connexions. Zed IDE doit être installé sur cette machine.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Aucun identifiant Zed trouvé dans le trousseau d'accès", "zedUnsupportedCredentials": "Trouvé {count} identifiant(s) dans le trousseau d'accès, mais aucun ne correspond aux fournisseurs pris en charge", "zedManualTitle": "Importation manuelle de jeton", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Comment fonctionne la tarification", "cacheWrite": "Écriture du cache", "unsaved": "non enregistré", - "resetDefaults": "Réinitialiser les paramètres par défaut", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Enregistrer le fournisseur", "model": "Modèle", "models": "modèles", diff --git a/src/i18n/messages/gu.json b/src/i18n/messages/gu.json index 6c87077ac2..89f696a61f 100644 --- a/src/i18n/messages/gu.json +++ b/src/i18n/messages/gu.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → Application → Local Storage → https://t3.chat ખોલો, 'convex-session-id' કૉપિ કરો. પછી DevTools → નેટવર્ક ખોલો, કોઈપણ ચેટ વિનંતીમાંથી સંપૂર્ણ કૂકી હેડરની નકલ કરો. નીચેના ફીલ્ડમાં બંને મૂલ્યો પેસ્ટ કરો.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "અસ્થાયી કૂલડાઉન છોડો જેથી પુનઃપ્રાપ્ત કરી શકાય તેવી ભૂલો પછી પણ આ કનેક્શન પાત્ર રહે (પ્રતિબંધિત/સમાપ્ત જેવી ટર્મિનલ સ્થિતિઓ હજુ પણ લાગુ પડે છે).", "disableCoolingLabel": "આ કનેક્શન માટે કૂલડાઉન અક્ષમ કરો", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build auth આયાત કરો", "zedImportTitle": "Zed Keychain માંથી આયાત કરો", "zedImportDescription": "OS કીચેઇનમાં Zed IDE દ્વારા સંગ્રહિત AI પ્રદાતા ઓળખપત્રો (OpenAI, Anthropic, Google, Mistral, xAI) શોધો અને તેમને કનેક્શન્સ તરીકે આયાત કરો. આ મશીન પર Zed IDE ઇન્સ્ટોલ કરેલું હોવું આવશ્યક છે.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "કીચેઇનમાં કોઈ Zed ઓળખપત્રો મળ્યા નથી", "zedUnsupportedCredentials": "{count} કીચેઇન ઓળખપત્ર(ઓ) મળ્યા, પરંતુ કોઈ પણ સમર્થિત પ્રદાતાઓ સાથે મેળ ખાતા નથી", "zedManualTitle": "મેન્યુઅલ ટોકન આયાત", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/he.json b/src/i18n/messages/he.json index 50a84aa9e5..ac23997432 100644 --- a/src/i18n/messages/he.json +++ b/src/i18n/messages/he.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "פתח את t3.chat → DevTools → יישום → אחסון מקומי → https://t3.chat, העתק את 'convex-session-id'. לאחר מכן פתח את DevTools → רשת, העתק את כותרת העוגייה המלאה מכל בקשת צ'אט. הדבק את שני הערכים בשדות למטה.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "דלג על תקופת הצינון הזמנית כדי שחיבור זה יישאר זמין גם לאחר שגיאות הניתנות לשחזור (מצבים סופיים כמו חסום/פג תוקף עדיין חלים).", "disableCoolingLabel": "השבת תקופת צינון עבור חיבור זה", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "ייבוא אימות Grok Build", "zedImportTitle": "ייבוא מ-Zed Keychain", "zedImportDescription": "גלה אישורי ספקי בינה מלאכותית (OpenAI, Anthropic, Google, Mistral, xAI) המאוחסנים על ידי Zed IDE במחזיק המפתחות של מערכת ההפעלה ויבא אותם כחיבורים. Zed IDE חייב להיות מותקן במחשב זה.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "לא נמצאו אישורי Zed במחזיק המפתחות", "zedUnsupportedCredentials": "נמצאו {count} אישורים במחזיק המפתחות, אך אף אחד מהם לא תאם לספקים הנתמכים", "zedManualTitle": "ייבוא אסימון ידני", @@ -6748,7 +6748,7 @@ "howPricingWorks": "איך עובד התמחור", "cacheWrite": "כתוב מטמון", "unsaved": "לא נשמר", - "resetDefaults": "אפס את ברירת המחדל", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "שמור ספק", "model": "דגם", "models": "דגמים", diff --git a/src/i18n/messages/hi.json b/src/i18n/messages/hi.json index 2c9191bfb5..56f409ab0b 100644 --- a/src/i18n/messages/hi.json +++ b/src/i18n/messages/hi.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Bagian titik akhir", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat खोलें → DevTools → एप्लिकेशन → लोकल स्टोरेज → https://t3.chat, 'convex-session-id' कॉपी करें। फिर DevTools → Network खोलें, किसी भी चैट अनुरोध से पूर्ण कुकी हेडर कॉपी करें। दोनों मानों को नीचे दिए गए फ़ील्ड में चिपकाएँ।", "t3ChatWebCookiePlaceholder": "उत्तल-सत्र-आईडी=एबीसी123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "अस्थायी कूलडाउन को छोड़ें ताकि पुनर्प्राप्ति योग्य त्रुटियों के बाद भी यह कनेक्शन योग्य बना रहे (प्रतिबंधित/समाप्त जैसी अंतिम स्थितियां अभी भी लागू होती हैं)।", "disableCoolingLabel": "इस कनेक्शन के लिए कूलडाउन अक्षम करें", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build ऑथ आयात करें", "zedImportTitle": "Zed Keychain से आयात करें", "zedImportDescription": "OS कीचेन में Zed IDE द्वारा संग्रहीत AI प्रदाता क्रेडेंशियल (OpenAI, Anthropic, Google, Mistral, xAI) खोजें और उन्हें कनेक्शन के रूप में आयात करें। इस मशीन पर Zed IDE इंस्टॉल होना चाहिए।", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "कीचेन में कोई Zed क्रेडेंशियल नहीं मिले", "zedUnsupportedCredentials": "{count} कीचेन क्रेडेंशियल मिले, लेकिन कोई भी समर्थित प्रदाताओं से मेल नहीं खाता", "zedManualTitle": "मैन्युअल टोकन आयात", @@ -6748,7 +6748,7 @@ "howPricingWorks": "मूल्य निर्धारण कैसे काम करता है", "cacheWrite": "कैश लिखें", "unsaved": "सहेजा नहीं गया", - "resetDefaults": "डिफ़ॉल्ट रीसेट करें", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "प्रदाता सहेजें", "model": "मॉडल", "models": "मॉडल", diff --git a/src/i18n/messages/hu.json b/src/i18n/messages/hu.json index e11a330741..21695842a3 100644 --- a/src/i18n/messages/hu.json +++ b/src/i18n/messages/hu.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Nyissa meg a t3.chat → DevTools → Alkalmazás → Helyi tárhely → https://t3.chat menüpontot, másolja ki a 'convex-session-id'-t. Ezután nyissa meg a DevTools → Network lehetőséget, és másolja ki a teljes Cookie fejlécet bármely csevegési kérelemből. Illessze be mindkét értéket az alábbi mezőkbe.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Skip the transient cooldown so this connection stays eligible even after recoverable errors (terminal states like banned/expired still apply).", "disableCoolingLabel": "Lehűlési idő (cooldown) letiltása ehhez a kapcsolathoz", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build hitelesítés importálása", "zedImportTitle": "Importálás a Zed kulcstartóból", "zedImportDescription": "Fedezd fel a Zed IDE által az operációs rendszer kulcstartójában tárolt AI-szolgáltatói hitelesítési adatokat (OpenAI, Anthropic, Google, Mistral, xAI), és importáld őket kapcsolatként. A Zed IDE-nek telepítve kell lennie ezen a gépen.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Nem találhatók Zed hitelesítési adatok a kulcstartóban", "zedUnsupportedCredentials": "{count} kulcstartó-hitelesítési adat található, de egyik sem felelt meg a támogatott szolgáltatóknak", "zedManualTitle": "Kézi tokenimportálás", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Hogyan működik az árképzés", "cacheWrite": "Gyorsítótár írás", "unsaved": "nem mentve", - "resetDefaults": "Alapértékek visszaállítása", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Mentse a Szolgáltatót", "model": "Modell", "models": "modellek", diff --git a/src/i18n/messages/id.json b/src/i18n/messages/id.json index 0fd5440b53..c65693c536 100644 --- a/src/i18n/messages/id.json +++ b/src/i18n/messages/id.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Buka t3.chat → DevTools → Aplikasi → Penyimpanan Lokal → https://t3.chat, salin 'convex-session-id'. Lalu buka DevTools → Jaringan, salin header Cookie lengkap dari permintaan obrolan apa pun. Tempelkan kedua nilai pada kolom di bawah.", "t3ChatWebCookiePlaceholder": "id-sesi-cembung=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Lewati cooldown transien agar koneksi ini tetap memenuhi syarat bahkan setelah kesalahan yang dapat dipulihkan (status terminal seperti diblokir/kedaluwarsa tetap berlaku).", "disableCoolingLabel": "Nonaktifkan cooldown untuk koneksi ini", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Impor autentikasi Grok Build", "zedImportTitle": "Impor dari Zed Keychain", "zedImportDescription": "Temukan kredensial penyedia AI (OpenAI, Anthropic, Google, Mistral, xAI) yang disimpan oleh Zed IDE di keychain OS dan impor sebagai koneksi. Zed IDE harus terinstal di mesin ini.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Tidak ada kredensial Zed yang ditemukan di keychain", "zedUnsupportedCredentials": "Ditemukan {count} kredensial keychain, tetapi tidak ada yang cocok dengan penyedia yang didukung", "zedManualTitle": "Impor Token Manual", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Bagaimana Penetapan Harga Bekerja", "cacheWrite": "Tulis Cache", "unsaved": "belum disimpan", - "resetDefaults": "Atur Ulang Default", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Simpan Penyedia", "model": "Model", "models": "model", diff --git a/src/i18n/messages/in.json b/src/i18n/messages/in.json index 3324640709..a69d33694e 100644 --- a/src/i18n/messages/in.json +++ b/src/i18n/messages/in.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Buka t3.chat → DevTools → Aplikasi → Penyimpanan Lokal → https://t3.chat, salin 'convex-session-id'. Lalu buka DevTools → Jaringan, salin header Cookie lengkap dari permintaan obrolan apa pun. Tempelkan kedua nilai pada kolom di bawah.", "t3ChatWebCookiePlaceholder": "id-sesi-cembung=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Lewati cooldown sementara agar koneksi ini tetap memenuhi syarat bahkan setelah kesalahan yang dapat dipulihkan (status terminal seperti diblokir/kedaluwarsa tetap berlaku).", "disableCoolingLabel": "Nonaktifkan cooldown untuk koneksi ini", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Impor autentikasi Grok Build", "zedImportTitle": "Impor dari Zed Keychain", "zedImportDescription": "Temukan kredensial penyedia AI (OpenAI, Anthropic, Google, Mistral, xAI) yang disimpan oleh Zed IDE di keychain OS dan impor sebagai koneksi. Zed IDE harus terpasang di mesin ini.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Tidak ada kredensial Zed yang ditemukan di keychain", "zedUnsupportedCredentials": "Ditemukan {count} kredensial keychain, tetapi tidak ada yang cocok dengan penyedia yang didukung", "zedManualTitle": "Impor Token Manual", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/it.json b/src/i18n/messages/it.json index 757291d682..21329d2aaf 100644 --- a/src/i18n/messages/it.json +++ b/src/i18n/messages/it.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Apri t3.chat → DevTools → Applicazione → Archiviazione locale → https://t3.chat, copia 'convex-session-id'. Quindi apri DevTools → Rete, copia l'intestazione completa del cookie da qualsiasi richiesta di chat. Incolla entrambi i valori nei campi sottostanti.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Salta il cooldown transitorio in modo che questa connessione rimanga idonea anche dopo errori ripristinabili (gli stati terminali come bannato/scaduto si applicano ancora).", "disableCoolingLabel": "Disabilita il cooldown per questa connessione", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Importa autenticazione Grok Build", "zedImportTitle": "Importa da Zed Keychain", "zedImportDescription": "Trova le credenziali dei provider AI (OpenAI, Anthropic, Google, Mistral, xAI) memorizzate da Zed IDE nel portachiavi del sistema operativo e importale come connessioni. Zed IDE deve essere installato su questa macchina.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Nessuna credenziale Zed trovata nel portachiavi", "zedUnsupportedCredentials": "Trovate {count} credenziali nel portachiavi, ma nessuna corrisponde ai provider supportati", "zedManualTitle": "Importazione manuale del token", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Come funzionano i prezzi", "cacheWrite": "Scrittura nella cache", "unsaved": "non salvato", - "resetDefaults": "Ripristina le impostazioni predefinite", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Salva fornitore", "model": "Modello", "models": "modelli", @@ -6802,7 +6802,7 @@ "purgeLogsFailed": "Failed to purge logs", "logsDeleted": "{count, plural, =0 {Nessun log scaduto eliminato} one {Eliminato # log scaduto} other {Eliminati # log scaduti}}", "resetUsageData": "Ripristina Dati di Utilizzo", - "resetUsageDataDesc": "Seleziona fino a quando eliminare i dati di utilizzo. Questa azione non può essere annullata.", + "resetUsageDataDesc": "__MISSING__:Select how far back you want to delete usage, request logs, and analytics data. Provider configuration, connections, API keys, combos, and settings are preserved. This action cannot be undone.", "resetUsagePeriod_5m": "5 minuti", "resetUsagePeriod_1h": "1 ora", "resetUsagePeriod_3h": "3 ore", @@ -7489,9 +7489,9 @@ "resilienceEnableServerWaitDesc": "Quando abilitato, OmniRoute attende la scadenza del primo tempo di recupero e riprova automaticamente.", "resilienceMaxAttempts": "Tentativi massimi", "resilienceMaxWaitPerAttempt": "Attesa massima per tentativo", - "resilienceComboCooldownWaitTitle": "Attesa cooldown combo quota-share", - "resilienceComboCooldownWaitDesc": "Solo per combo quota-share: attende un breve cooldown transitorio e reinoltra invece di restituire subito un 429. Non attende mai su quota_exhausted.", - "resilienceComboCooldownWaitToggleDesc": "Solo combo quota-share; non attende mai su quota_exhausted.", + "resilienceComboCooldownWaitTitle": "__MISSING__:Combo cooldown wait", + "resilienceComboCooldownWaitDesc": "__MISSING__:For all combo strategies: wait out a short transient cooldown and re-dispatch instead of returning a 429 immediately. Never waits on quota_exhausted.", + "resilienceComboCooldownWaitToggleDesc": "__MISSING__:All combo strategies; never waits on quota_exhausted.", "resilienceComboCooldownMaxWaitMs": "Attesa massima per tentativo", "resilienceComboCooldownBudgetMs": "Budget attesa totale", "resilienceQuotaShareConcurrencyTitle": "Concorrenza per connessione quota-share", diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json index 846587a2ac..aac71c81f7 100644 --- a/src/i18n/messages/ja.json +++ b/src/i18n/messages/ja.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → Application → Local Storage → https://t3.chat を開き、「convex-session-id」をコピーします。次に、[DevTools] → [Network] を開き、チャット リクエストから完全な Cookie ヘッダーをコピーします。両方の値を下のフィールドに貼り付けます。", "t3ChatWebCookiePlaceholder": "凸セッションID=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "一時的なクールダウンをスキップし、回復可能なエラーの後でもこの接続を対象として維持します (banned/expired などの終端状態は引き続き適用されます)。", "disableCoolingLabel": "この接続のクールダウンを無効化", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build 認証情報をインポート", "zedImportTitle": "Zed キーチェーンからインポート", "zedImportDescription": "OS キーチェーンに Zed IDE によって保存された AI プロバイダーの認証情報 (OpenAI、Anthropic、Google、Mistral、xAI) を検出し、接続としてインポートします。このマシンに Zed IDE がインストールされている必要があります。", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "キーチェーンに Zed の認証情報が見つかりませんでした", "zedUnsupportedCredentials": "{count} 件のキーチェーン認証情報が見つかりましたが、サポートされているプロバイダーと一致するものはありませんでした", "zedManualTitle": "手動トークンインポート", @@ -6748,7 +6748,7 @@ "howPricingWorks": "価格設定の仕組み", "cacheWrite": "キャッシュ書き込み", "unsaved": "未保存", - "resetDefaults": "デフォルトにリセット", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "プロバイダーの保存", "model": "モデル", "models": "モデル", diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json index a178aa7752..11c649976a 100644 --- a/src/i18n/messages/ko.json +++ b/src/i18n/messages/ko.json @@ -6748,7 +6748,7 @@ "howPricingWorks": "가격 책정 방식", "cacheWrite": "캐시 쓰기", "unsaved": "저장되지 않은", - "resetDefaults": "기본값 재설정", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "공급자 저장", "model": "모델", "models": "모델", diff --git a/src/i18n/messages/mr.json b/src/i18n/messages/mr.json index 4ed7c9fbe2..5451454675 100644 --- a/src/i18n/messages/mr.json +++ b/src/i18n/messages/mr.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → Application → Local Storage → https://t3.chat उघडा, 'convex-session-id' कॉपी करा. नंतर DevTools → नेटवर्क उघडा, कोणत्याही चॅट विनंतीवरून संपूर्ण कुकी शीर्षलेख कॉपी करा. खालील फील्डमध्ये दोन्ही मूल्ये पेस्ट करा.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "अस्थायी कूलडाउन वगळा जेणेकरून पुनर्प्राप्त करण्यायोग्य त्रुटींनंतरही हे कनेक्शन पात्र राहील (प्रतिबंधित/कालबाह्य यांसारख्या अंतिम स्थिती अजूनही लागू होतात).", "disableCoolingLabel": "या कनेक्शनसाठी कूलडाउन अक्षम करा", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build auth इम्पोर्ट करा", "zedImportTitle": "Zed Keychain मधून इम्पोर्ट करा", "zedImportDescription": "OS कीचेनमध्ये Zed IDE द्वारे स्टोअर केलेली AI प्रदाता क्रेडेंशियल्स (OpenAI, Anthropic, Google, Mistral, xAI) शोधा आणि त्यांना कनेक्शन्स म्हणून इम्पोर्ट करा. या मशीनवर Zed IDE इन्स्टॉल केलेले असणे आवश्यक आहे.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "कीचेनमध्ये कोणतीही Zed क्रेडेंशियल्स आढळली नाहीत", "zedUnsupportedCredentials": "{count} कीचेन क्रेडेंशियल आढळले, परंतु समर्थित प्रदात्यांशी कोणतेही जुळले नाही", "zedManualTitle": "मॅन्युअल टोकन इम्पोर्ट", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/ms.json b/src/i18n/messages/ms.json index 2eafb97d93..592e2bd368 100644 --- a/src/i18n/messages/ms.json +++ b/src/i18n/messages/ms.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Buka t3.chat → DevTools → Aplikasi → Storan Tempatan → https://t3.chat, salin 'convex-session-id'. Kemudian buka DevTools → Rangkaian, salin pengepala Kuki penuh daripada sebarang permintaan sembang. Tampalkan kedua-dua nilai dalam medan di bawah.", "t3ChatWebCookiePlaceholder": "cembung-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Langkau tempoh bertenang sementara supaya sambungan ini kekal layak walaupun selepas ralat yang boleh dipulihkan (keadaan terminal seperti disekat/tamat tempoh masih terpakai).", "disableCoolingLabel": "Nyahdayakan tempoh bertenang untuk sambungan ini", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Import pengesahan Grok Build", "zedImportTitle": "Import daripada Rantai Kunci Zed", "zedImportDescription": "Kesan kelayakan penyedia AI (OpenAI, Anthropic, Google, Mistral, xAI) yang disimpan oleh Zed IDE dalam rantai kunci OS dan importnya sebagai sambungan. Zed IDE mesti dipasang pada mesin ini.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Tiada kelayakan Zed ditemui dalam rantai kunci", "zedUnsupportedCredentials": "Menemui {count} kelayakan rantai kunci, tetapi tiada yang sepadan dengan penyedia yang disokong", "zedManualTitle": "Import Token Manual", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Cara Harga Berfungsi", "cacheWrite": "Tulis Cache", "unsaved": "belum disimpan", - "resetDefaults": "Tetapkan Semula Lalai", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Simpan Penyedia", "model": "Model", "models": "model", diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json index 75d8bcbf92..afe5aea540 100644 --- a/src/i18n/messages/nl.json +++ b/src/i18n/messages/nl.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Open t3.chat → DevTools → Applicatie → Lokale opslag → https://t3.chat, kopieer 'convex-session-id'. Open vervolgens DevTools → Netwerk en kopieer de volledige Cookie-header van elk chatverzoek. Plak beide waarden in de onderstaande velden.", "t3ChatWebCookiePlaceholder": "convexe-sessie-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Sla de tijdelijke afkoelperiode over, zodat deze verbinding in aanmerking blijft komen, zelfs na herstelbare fouten (definitieve statussen zoals verbannen/verlopen zijn nog steeds van toepassing).", "disableCoolingLabel": "Afkoelperiode uitschakelen voor deze verbinding", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build-authenticatie importeren", "zedImportTitle": "Importeren uit Zed-sleutelhanger", "zedImportDescription": "Ontdek inloggegevens van AI-providers (OpenAI, Anthropic, Google, Mistral, xAI) die door Zed IDE zijn opgeslagen in de sleutelhanger van het besturingssysteem en importeer ze als verbindingen. Zed IDE moet op deze machine zijn geïnstalleerd.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Geen Zed-inloggegevens gevonden in de sleutelhanger", "zedUnsupportedCredentials": "{count} inloggegeven(s) in de sleutelhanger gevonden, maar geen enkele kwam overeen met ondersteunde providers", "zedManualTitle": "Handmatige tokenimport", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Hoe prijzen werken", "cacheWrite": "Cache schrijven", "unsaved": "niet opgeslagen", - "resetDefaults": "Standaardwaarden opnieuw instellen", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Aanbieder opslaan", "model": "Model", "models": "modellen", diff --git a/src/i18n/messages/no.json b/src/i18n/messages/no.json index 13bbbc03e1..82dbeff23f 100644 --- a/src/i18n/messages/no.json +++ b/src/i18n/messages/no.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Åpne t3.chat → DevTools → Applikasjon → Lokal lagring → https://t3.chat, kopier 'convex-session-id'. Åpne deretter DevTools → Nettverk, kopier hele informasjonskapseloverskriften fra enhver chat-forespørsel. Lim inn begge verdiene i feltene nedenfor.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Hopp over den forbigående nedkjølingen slik at denne tilkoblingen forblir kvalifisert selv etter gjenopprettelige feil (sluttilstander som utestengt/utløpt gjelder fortsatt).", "disableCoolingLabel": "Deaktiver nedkjøling for denne tilkoblingen", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Importer Grok Build-autentisering", "zedImportTitle": "Importer fra Zed-nøkkelring", "zedImportDescription": "Oppdag påloggingsinformasjon for AI-leverandører (OpenAI, Anthropic, Google, Mistral, xAI) lagret av Zed IDE i operativsystemets nøkkelring, og importer dem som tilkoblinger. Zed IDE må være installert på denne maskinen.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Ingen Zed-påloggingsinformasjon funnet i nøkkelringen", "zedUnsupportedCredentials": "Fant {count} påloggingsinformasjon(er) i nøkkelringen, men ingen samsvarte med støttede leverandører", "zedManualTitle": "Manuell token-import", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Hvordan prissetting fungerer", "cacheWrite": "Cache-skriving", "unsaved": "ikke lagret", - "resetDefaults": "Tilbakestill standarder", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Lagre leverandør", "model": "Modell", "models": "modeller", diff --git a/src/i18n/messages/phi.json b/src/i18n/messages/phi.json index 31a7bce3a9..23074a502f 100644 --- a/src/i18n/messages/phi.json +++ b/src/i18n/messages/phi.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Buksan ang t3.chat → DevTools → Application → Local Storage → https://t3.chat, kopyahin ang 'convex-session-id'. Pagkatapos ay buksan ang DevTools → Network, kopyahin ang buong Cookie header mula sa anumang kahilingan sa chat. I-paste ang parehong mga halaga sa mga patlang sa ibaba.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Laktawan ang transient cooldown para manatiling kwalipikado ang koneksyong ito kahit pagkatapos ng mga error na maaaring ma-recover (nalalapat pa rin ang mga terminal state tulad ng banned/expired).", "disableCoolingLabel": "I-disable ang cooldown para sa koneksyong ito", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "I-import ang Grok Build auth", "zedImportTitle": "I-import mula sa Zed Keychain", "zedImportDescription": "Tukuyin ang mga credential ng AI provider (OpenAI, Anthropic, Google, Mistral, xAI) na nakaimbak sa pamamagitan ng Zed IDE sa OS keychain at i-import ang mga ito bilang mga koneksyon. Dapat ay naka-install ang Zed IDE sa makinang ito.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Walang nahanap na mga credential ng Zed sa keychain", "zedUnsupportedCredentials": "Nakahanap ng {count} credential sa keychain, ngunit walang tumugma sa mga sinusuportahang provider", "zedManualTitle": "Manwal na Pag-import ng Token", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Paano Gumagana ang Pagpepresyo", "cacheWrite": "Cache Write", "unsaved": "hindi naligtas", - "resetDefaults": "I-reset ang Mga Default", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "I-save ang Provider", "model": "Modelo", "models": "mga modelo", diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json index a43eb374c6..8f836bb504 100644 --- a/src/i18n/messages/pt-BR.json +++ b/src/i18n/messages/pt-BR.json @@ -3726,7 +3726,7 @@ "modelsCount": "{count, plural, one {# modelo} other {# modelos}}", "sectionTitle": "Superfície de Integração", "sectionDescription": "APIs compatíveis com OpenAI e endpoints operacionais de protocolos", - "tabApis": "APIs compatíveis com OpenAI", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocolos", "tabsAria": "Seções de endpoint", "protocolsTitle": "Protocolos", @@ -5431,8 +5431,8 @@ "t3ChatWebCookieHint": "Abra t3.chat → DevTools → Aplicativo → Armazenamento local → https://t3.chat, copie 'convex-session-id'. Em seguida, abra DevTools → Rede, copie o cabeçalho completo do cookie de qualquer solicitação de chat. Cole os dois valores nos campos abaixo.", "t3ChatWebCookiePlaceholder": "id-de-sessão-convexa=abc123...", "grokWebCookieHint": "Cole o cookie sso do grok.com. Um valor completo `sso=...` também funciona.", - "blockClaudeExtraUsageDescription": "Quando habilitado, o OmniRoute marca esta conta do Claude Code como indisponível assim que a API de usage reporta `extra_usage.queued`, para que o fallback troque para outra conta antes de continuar com cobranças extras pay-as-you-go.", - "blockClaudeExtraUsageLabel": "Bloquear Claude Extra Usage", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Ignore o cooldown transitório para que esta conexão permaneça qualificada mesmo após erros recuperáveis (estados terminais como banido/expirado ainda se aplicam).", "disableCoolingLabel": "Desativar cooldown para esta conexão", "bulkPasteAdded": "{count, plural, one {1 chave adicionada} other {# chaves adicionadas}}", @@ -5611,13 +5611,13 @@ "importGrokAuth": "Importar autenticação do Grok Build", "zedImportTitle": "Importar do chaveiro do Zed", "zedImportDescription": "Descubra credenciais de provedores de IA (OpenAI, Anthropic, Google, Mistral, xAI) armazenadas pelo Zed IDE no chaveiro do SO e importe-as como conexões. O Zed IDE deve estar instalado nesta máquina.", - "zedImportButton": "Importar do Zed", - "zedImportFailed": "Falha ao importar do Zed IDE.", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Importar credenciais do Zed IDE", "zedImportNetworkError": "Erro de rede ao tentar importar do Zed.", "zedImportNone": "Nenhuma credencial OAuth suportada encontrada no Zed IDE.", - "zedImportSuccess": "Importadas {count} credencial(is) do Zed IDE ({providers}).", - "zedImporting": "Importando...", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Nenhuma credencial do Zed encontrada no chaveiro", "zedUnsupportedCredentials": "Encontrada(s) {count} credencial(is) no chaveiro, mas nenhuma correspondeu aos provedores suportados", "zedManualTitle": "Importação manual de token", @@ -6773,7 +6773,7 @@ "howPricingWorks": "Como os Preços Funcionam", "cacheWrite": "Escrita em Cache", "unsaved": "não salvo", - "resetDefaults": "Restaurar Padrões", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Salvar Provedor", "model": "Modelo", "models": "modelos", @@ -6827,7 +6827,7 @@ "purgeLogsFailed": "Falha ao purgar logs", "logsDeleted": "{count, plural, =0 {Nenhum log expirado removido} one {# log expirado removido} other {# logs expirados removidos}}", "resetUsageData": "Redefinir dados de uso", - "resetUsageDataDesc": "Selecione quanto tempo no passado você deseja excluir dados de uso. Esta ação não pode ser desfeita.", + "resetUsageDataDesc": "__MISSING__:Select how far back you want to delete usage, request logs, and analytics data. Provider configuration, connections, API keys, combos, and settings are preserved. This action cannot be undone.", "resetUsagePeriod_5m": "5 minutos", "resetUsagePeriod_1h": "1 hora", "resetUsagePeriod_3h": "3 horas", @@ -7514,9 +7514,9 @@ "resilienceEnableServerWaitDesc": "Quando ativado, o OmniRoute aguarda o primeiro resfriamento expirar e tenta novamente automaticamente.", "resilienceMaxAttempts": "Máximo de tentativas", "resilienceMaxWaitPerAttempt": "Espera máxima por tentativa", - "resilienceComboCooldownWaitTitle": "Espera de cooldown do combo de cota compartilhada", - "resilienceComboCooldownWaitDesc": "Somente para combos de cota compartilhada: aguarda um cooldown transitório curto e reenvia em vez de retornar um 429 imediatamente. Nunca espera em quota_exhausted.", - "resilienceComboCooldownWaitToggleDesc": "Somente combos de cota compartilhada; nunca espera em quota_exhausted.", + "resilienceComboCooldownWaitTitle": "__MISSING__:Combo cooldown wait", + "resilienceComboCooldownWaitDesc": "__MISSING__:For all combo strategies: wait out a short transient cooldown and re-dispatch instead of returning a 429 immediately. Never waits on quota_exhausted.", + "resilienceComboCooldownWaitToggleDesc": "__MISSING__:All combo strategies; never waits on quota_exhausted.", "resilienceComboCooldownMaxWaitMs": "Espera máxima por tentativa", "resilienceComboCooldownBudgetMs": "Orçamento total de espera", "resilienceQuotaShareConcurrencyTitle": "Concorrência por conexão de cota compartilhada", @@ -11347,7 +11347,7 @@ } }, "pageTitle": "Agent Skills", - "pageSubtitle": "Ensine seu agente a operar o OmniRoute — 22 áreas de API + 20 famílias de CLI", + "pageSubtitle": "__MISSING__:Teach your agent to operate OmniRoute — 23 API areas + 21 CLI families", "conceptCard": { "agent": { "title": "Agent Skills — Saída", diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index 4e7f8127b2..9891203fee 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Abra t3.chat → DevTools → Aplicativo → Armazenamento local → https://t3.chat, copie 'convex-session-id'. Em seguida, abra DevTools → Rede, copie o cabeçalho completo do cookie de qualquer solicitação de chat. Cole os dois valores nos campos abaixo.", "t3ChatWebCookiePlaceholder": "id-de-sessão-convexa=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Ignorar o cooldown transitório para que esta ligação permaneça elegível mesmo após erros recuperáveis (estados terminais como banido/expirado continuam a aplicar-se).", "disableCoolingLabel": "Desativar cooldown para esta ligação", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Importar autenticação do Grok Build", "zedImportTitle": "Importar do Porta-chaves do Zed", "zedImportDescription": "Detetar credenciais de fornecedores de IA (OpenAI, Anthropic, Google, Mistral, xAI) guardadas pelo Zed IDE no porta-chaves do SO e importá-las como ligações. O Zed IDE tem de estar instalado nesta máquina.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Nenhuma credencial do Zed encontrada no porta-chaves", "zedUnsupportedCredentials": "Encontradas {count} credenciais no porta-chaves, mas nenhuma corresponde aos fornecedores suportados", "zedManualTitle": "Importação manual de token", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Como funciona o preço", "cacheWrite": "Gravação em cache", "unsaved": "não salvo", - "resetDefaults": "Redefinir padrões", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Salvar provedor", "model": "Modelo", "models": "modelos", diff --git a/src/i18n/messages/ro.json b/src/i18n/messages/ro.json index cbf800b52b..68c9f99780 100644 --- a/src/i18n/messages/ro.json +++ b/src/i18n/messages/ro.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Deschideți t3.chat → DevTools → Aplicație → Stocare locală → https://t3.chat, copiați „convex-session-id”. Apoi deschideți DevTools → Network, copiați antetul complet Cookie din orice solicitare de chat. Lipiți ambele valori în câmpurile de mai jos.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Omite perioada de răcire tranzitorie, astfel încât această conexiune să rămână eligibilă chiar și după erori recuperabile (stările terminale precum blocat/expirat se aplică în continuare).", "disableCoolingLabel": "Dezactivează perioada de răcire pentru această conexiune", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Importare autentificare Grok Build", "zedImportTitle": "Importare din Zed Keychain", "zedImportDescription": "Descoperă acreditările furnizorilor de IA (OpenAI, Anthropic, Google, Mistral, xAI) stocate de Zed IDE în keychain-ul sistemului de operare și le importă ca conexiuni. Zed IDE trebuie să fie instalat pe acest computer.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Nu s-au găsit acreditări Zed în keychain", "zedUnsupportedCredentials": "S-au găsit {count} acreditări în keychain, dar niciuna nu s-a potrivit cu furnizorii acceptați", "zedManualTitle": "Import manual de tokenuri", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Cum funcționează prețurile", "cacheWrite": "Scriere în cache", "unsaved": "nesalvat", - "resetDefaults": "Resetează setările implicite", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Salvați furnizorul", "model": "Model", "models": "modele", diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index 6ab25ef0c4..2a337ee4fb 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# модель} few {# модели} many {# моделей} other {# модели}}", "sectionTitle": "Интерфейс интеграции", "sectionDescription": "API, совместимые с OpenAI, и конечные точки операционных протоколов", - "tabApis": "OpenAI-совместимые API", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Протоколы", "tabsAria": "Разделы конечной точки", "protocolsTitle": "Протоколы", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Откройте t3.chat → DevTools → Приложение → Локальное хранилище → https://t3.chat, скопируйте «convex-session-id». Затем откройте DevTools → Network и скопируйте полный заголовок Cookie из любого запроса в чате. Вставьте оба значения в поля ниже.", "t3ChatWebCookiePlaceholder": "выпуклый-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Пропускать временный кулдаун, чтобы это подключение оставалось доступным даже после устранимых ошибок (терминальные состояния, такие как banned/expired, по-прежнему применяются).", "disableCoolingLabel": "Отключить кулдаун для этого подключения", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Импортировать авторизацию Grok Build", "zedImportTitle": "Импортировать из связки ключей Zed", "zedImportDescription": "Найти учетные данные провайдеров ИИ (OpenAI, Anthropic, Google, Mistral, xAI), сохраненные Zed IDE в связке ключей ОС, и импортировать их как подключения. На этом компьютере должна быть установлена Zed IDE.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "В связке ключей не найдено учетных данных Zed", "zedUnsupportedCredentials": "Найдено {count} учетных записей в связке ключей, но ни одна не соответствует поддерживаемым провайдерам", "zedManualTitle": "Ручной импорт токена", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Как работает ценообразование", "cacheWrite": "Запись в кэш", "unsaved": "несохраненный", - "resetDefaults": "Сбросить настройки по умолчанию", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Сохранить поставщика", "model": "Модель", "models": "модели", @@ -11322,7 +11322,7 @@ } }, "pageTitle": "Навыки агента", - "pageSubtitle": "Научите вашего агента работать с OmniRoute — 22 области API + 20 семейств CLI", + "pageSubtitle": "__MISSING__:Teach your agent to operate OmniRoute — 23 API areas + 21 CLI families", "conceptCard": { "agent": { "title": "Навыки агента — Исходящие", diff --git a/src/i18n/messages/sk.json b/src/i18n/messages/sk.json index f89c26f81a..a3ed834ac0 100644 --- a/src/i18n/messages/sk.json +++ b/src/i18n/messages/sk.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Otvorte t3.chat → DevTools → Aplikácia → Miestne úložisko → https://t3.chat, skopírujte 'convex-session-id'. Potom otvorte DevTools → Network, skopírujte celú hlavičku súboru cookie z akejkoľvek žiadosti o rozhovor. Prilepte obe hodnoty do polí nižšie.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Preskočiť prechodný cooldown (doba chladnutia), aby toto pripojenie zostalo oprávnené aj po odstrániteľných chybách (konečné stavy ako zablokované/vypršané stále platia).", "disableCoolingLabel": "Zakázať cooldown pre toto pripojenie", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Importovať overenie Grok Build", "zedImportTitle": "Importovať z kľúčenky Zed", "zedImportDescription": "Vyhľadať prihlasovacie údaje poskytovateľov AI (OpenAI, Anthropic, Google, Mistral, xAI) uložené prostredím Zed IDE v kľúčenke operačného systému a importovať ich ako pripojenia. Na tomto počítači musí byť nainštalované Zed IDE.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "V kľúčenke sa nenašli žiadne prihlasovacie údaje pre Zed", "zedUnsupportedCredentials": "Našlo sa {count} prihlasovacích údajov v kľúčenke, ale žiadne nezodpovedali podporovaným poskytovateľom", "zedManualTitle": "Manuálny import tokenu", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Ako funguje tvorba cien", "cacheWrite": "Zápis do vyrovnávacej pamäte", "unsaved": "neuložené", - "resetDefaults": "Obnoviť predvolené nastavenia", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Uložiť poskytovateľa", "model": "Model", "models": "modelov", diff --git a/src/i18n/messages/sv.json b/src/i18n/messages/sv.json index 1572555fba..4cbcc38ea1 100644 --- a/src/i18n/messages/sv.json +++ b/src/i18n/messages/sv.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integrationsyta", "sectionDescription": "OpenAI-kompatibla API:er och operativa protokollslutpunkter", - "tabApis": "OpenAI-kompatibla API:er", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protokoll", "tabsAria": "Slutpunktssektioner", "protocolsTitle": "Protokoll", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Öppna t3.chat → DevTools → Application → Local Storage → https://t3.chat, kopiera 'convex-session-id'. Öppna sedan DevTools → Nätverk, kopiera hela Cookie-huvudet från valfri chattförfrågan. Klistra in båda värdena i fälten nedan.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Hoppa över den tillfälliga cooldown-perioden så att denna anslutning förblir tillgänglig även efter återställningsbara fel (slutgiltiga tillstånd som banned/expired gäller fortfarande).", "disableCoolingLabel": "Inaktivera cooldown för denna anslutning", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Importera Grok Build-autentisering", "zedImportTitle": "Importera från Zed-nyckelring", "zedImportDescription": "Hitta autentiseringsuppgifter för AI-leverantörer (OpenAI, Anthropic, Google, Mistral, xAI) som lagrats av Zed IDE i operativsystemets nyckelring och importera dem som anslutningar. Zed IDE måste vara installerat på den här datorn.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Inga Zed-autentiseringsuppgifter hittades i nyckelringen", "zedUnsupportedCredentials": "Hittade {count} autentiseringsuppgift(er) i nyckelringen, men ingen matchade leverantörer som stöds", "zedManualTitle": "Manuell tokenimport", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Hur prissättning fungerar", "cacheWrite": "Cache Skriv", "unsaved": "osparade", - "resetDefaults": "Återställ standardvärden", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Spara leverantör", "model": "Modell", "models": "modeller", diff --git a/src/i18n/messages/sw.json b/src/i18n/messages/sw.json index d25e1b5570..e85b452beb 100644 --- a/src/i18n/messages/sw.json +++ b/src/i18n/messages/sw.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Fungua t3.chat → DevTools → Programu → Hifadhi ya Ndani → https://t3.chat, nakili 'convex-session-id'. Kisha ufungue DevTools → Mtandao, nakili kichwa kamili cha Kidakuzi kutoka kwa ombi lolote la gumzo. Bandika thamani zote mbili katika sehemu zilizo hapa chini.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Ruka muda wa utulivu wa mpito ili muunganisho huu uendelee kustahiki hata baada ya hitilafu zinazoweza kurekebishwa (hali za mwisho kama vile zilizopigwa marufuku/zilizopitwa na wakati bado zinatumika).", "disableCoolingLabel": "Zima muda wa utulivu kwa muunganisho huu", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Ingiza uthibitishaji wa Grok Build", "zedImportTitle": "Ingiza kutoka kwa Zed Keychain", "zedImportDescription": "Gundua vitambulisho vya mtoa huduma wa AI (OpenAI, Anthropic, Google, Mistral, xAI) vilivyohifadhiwa na Zed IDE kwenye keychain ya OS na uviingize kama miunganisho. Zed IDE lazima iwe imesakinishwa kwenye mashine hii.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Hakuna vitambulisho vya Zed vilivyopatikana kwenye keychain", "zedUnsupportedCredentials": "Imepata vitambulisho vya keychain {count}, lakini hakuna vilivyolingana na watoa huduma wanaoungwa mkono", "zedManualTitle": "Uingizaji wa Tokeni wa Mwongozo", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/ta.json b/src/i18n/messages/ta.json index caad2f34ab..b66212a388 100644 --- a/src/i18n/messages/ta.json +++ b/src/i18n/messages/ta.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → Application → Local Storage → https://t3.chat ஐ திறக்கவும், 'convex-session-id' ஐ நகலெடுக்கவும். பின்னர் DevTools → Networkஐத் திறந்து, எந்த அரட்டை கோரிக்கையிலிருந்தும் முழு குக்கீ தலைப்பையும் நகலெடுக்கவும். இரண்டு மதிப்புகளையும் கீழே உள்ள புலங்களில் ஒட்டவும்.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "தற்காலிக கூல்டவுனைத் தவிர்க்கவும், இதனால் மீட்டெடுக்கக்கூடிய பிழைகளுக்குப் பிறகும் இந்த இணைப்பு தகுதியுடையதாக இருக்கும் (தடைசெய்யப்பட்ட/காலாவதியான போன்ற இறுதி நிலைகள் இன்னும் பொருந்தும்).", "disableCoolingLabel": "இந்த இணைப்பிற்கான கூல்டவுனை முடக்கவும்", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build அங்கீகாரத்தை இறக்குமதி செய்யவும்", "zedImportTitle": "Zed கீசெயினிலிருந்து இறக்குமதி செய்யவும்", "zedImportDescription": "OS keychain-இல் Zed IDE சேமித்துள்ள AI வழங்குநர் நற்சான்றுகளை (OpenAI, Anthropic, Google, Mistral, xAI) கண்டறிந்து அவற்றை இணைப்புகளாக இறக்குமதி செய்யவும். இந்த கணினியில் Zed IDE நிறுவப்பட்டிருக்க வேண்டும்.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "keychain-இல் Zed நற்சான்றுகள் எதுவும் கண்டறியப்படவில்லை", "zedUnsupportedCredentials": "{count} keychain நற்சான்று(கள்) கண்டறியப்பட்டது, ஆனால் எதுவும் ஆதரிக்கப்படும் வழங்குநர்களுடன் பொருந்தவில்லை", "zedManualTitle": "கைமுறை டோக்கன் இறக்குமதி", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/te.json b/src/i18n/messages/te.json index 4d95f6d2c0..ce813f0f93 100644 --- a/src/i18n/messages/te.json +++ b/src/i18n/messages/te.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → అప్లికేషన్ → స్థానిక నిల్వ → https://t3.chat తెరవండి, 'convex-session-id'ని కాపీ చేయండి. తర్వాత DevTools → నెట్‌వర్క్‌ని తెరవండి, ఏదైనా చాట్ అభ్యర్థన నుండి పూర్తి కుకీ హెడర్‌ను కాపీ చేయండి. దిగువ ఫీల్డ్‌లలో రెండు విలువలను అతికించండి.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "తాత్కాలిక కూల్‌డౌన్‌ను దాటవేయండి, తద్వారా రికవర్ చేయగల ఎర్రర్‌ల తర్వాత కూడా ఈ కనెక్షన్ అర్హత కలిగి ఉంటుంది (banned/expired వంటి టెర్మినల్ స్థితులు ఇప్పటికీ వర్తిస్తాయి).", "disableCoolingLabel": "ఈ కనెక్షన్ కోసం కూల్‌డౌన్‌ను నిలిపివేయండి", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build authని దిగుమతి చేయండి", "zedImportTitle": "Zed Keychain నుండి దిగుమతి చేయండి", "zedImportDescription": "OS కీచైన్‌లో Zed IDE నిల్వ చేసిన AI ప్రొవైడర్ ఆధారాలను (OpenAI, Anthropic, Google, Mistral, xAI) కనుగొని, వాటిని కనెక్షన్‌లుగా దిగుమతి చేయండి. ఈ మెషీన్‌లో Zed IDE ఇన్‌స్టాల్ చేయబడి ఉండాలి.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "కీచైన్‌లో Zed ఆధారాలు ఏవీ కనుగొనబడలేదు", "zedUnsupportedCredentials": "{count} కీచైన్ ఆధారాలు కనుగొనబడ్డాయి, కానీ ఏవీ మద్దతు ఉన్న ప్రొవైడర్‌లతో సరిపోలలేదు", "zedManualTitle": "మాన్యువల్ టోకెన్ దిగుమతి", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/th.json b/src/i18n/messages/th.json index 46d620498a..ca78348afe 100644 --- a/src/i18n/messages/th.json +++ b/src/i18n/messages/th.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "เปิด t3.chat → DevTools → Application → Local Storage → https://t3.chat คัดลอก 'convex-session-id' จากนั้นเปิด DevTools → Network คัดลอกส่วนหัวคุกกี้แบบเต็มจากคำขอแชท วางทั้งสองค่าในช่องด้านล่าง", "t3ChatWebCookiePlaceholder": "นูน-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "ข้ามคูลดาวน์ชั่วคราวเพื่อให้การเชื่อมต่อนี้ยังคงมีสิทธิ์ใช้งานได้แม้หลังจากเกิดข้อผิดพลาดที่กู้คืนได้ (สถานะสิ้นสุด เช่น ถูกแบน/หมดอายุ ยังคงมีผลอยู่)", "disableCoolingLabel": "ปิดใช้งานคูลดาวน์สำหรับการเชื่อมต่อนี้", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "นำเข้าข้อมูลการยืนยันตัวตน Grok Build", "zedImportTitle": "นำเข้าจาก Zed Keychain", "zedImportDescription": "ค้นหาข้อมูลประจำตัวของผู้ให้บริการ AI (OpenAI, Anthropic, Google, Mistral, xAI) ที่จัดเก็บโดย Zed IDE ในพวงกุญแจของระบบปฏิบัติการ (OS keychain) และนำเข้ามาเป็นรายการเชื่อมต่อ ต้องติดตั้ง Zed IDE บนเครื่องนี้", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "ไม่พบข้อมูลประจำตัวของ Zed ในพวงกุญแจ", "zedUnsupportedCredentials": "พบข้อมูลประจำตัวในพวงกุญแจ {count} รายการ แต่ไม่มีรายการใดที่ตรงกับผู้ให้บริการที่รองรับ", "zedManualTitle": "นำเข้าโทเค็นด้วยตนเอง", @@ -6748,7 +6748,7 @@ "howPricingWorks": "วิธีการทำงานของการกำหนดราคา", "cacheWrite": "แคชเขียน", "unsaved": "ไม่ได้บันทึก", - "resetDefaults": "รีเซ็ตค่าเริ่มต้น", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "บันทึกผู้ให้บริการ", "model": "รุ่น", "models": "โมเดล", diff --git a/src/i18n/messages/tr.json b/src/i18n/messages/tr.json index c417f31099..43d3035400 100644 --- a/src/i18n/messages/tr.json +++ b/src/i18n/messages/tr.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Entegrasyon Yüzeyi", "sectionDescription": "OpenAI uyumlu API'ler ve operasyonel protokol uç noktaları", - "tabApis": "OpenAI uyumlu API'ler", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protokoller", "tabsAria": "Uç nokta bölümleri", "protocolsTitle": "Protokoller", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → Uygulama → Yerel Depolama → https://t3.chat'i açın, 'convex-session-id'yi kopyalayın. Ardından DevTools → Ağ'ı açın ve herhangi bir sohbet isteğindeki Çerez başlığının tamamını kopyalayın. Her iki değeri de aşağıdaki alanlara yapıştırın.", "t3ChatWebCookiePlaceholder": "dışbükey-oturum-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Geçici bekleme süresini atlayın; böylece bu bağlantı kurtarılabilir hatalardan sonra bile uygun kalmaya devam eder (yasaklandı/süresi doldu gibi nihai durumlar yine de geçerlidir).", "disableCoolingLabel": "Bu bağlantı için bekleme süresini devre dışı bırak", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build kimlik doğrulamasını içe aktar", "zedImportTitle": "Zed Keychain'den içe aktar", "zedImportDescription": "Zed IDE tarafından işletim sistemi anahtar zincirinde saklanan yapay zeka sağlayıcı kimlik bilgilerini (OpenAI, Anthropic, Google, Mistral, xAI) keşfedin ve bunları bağlantı olarak içe aktarın. Zed IDE bu makinede yüklü olmalıdır.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "Anahtar zincirinde hiçbir Zed kimlik bilgisi bulunamadı", "zedUnsupportedCredentials": "{count} anahtar zinciri kimlik bilgisi bulundu, ancak hiçbiri desteklenen sağlayıcılarla eşleşmedi", "zedManualTitle": "Manuel Token İçe Aktarma", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Fiyatlandırma Nasıl Çalışır?", "cacheWrite": "Önbellek Yazımı", "unsaved": "kaydedilmemiş", - "resetDefaults": "Varsayılanları Sıfırla", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Sağlayıcıyı Kaydet", "model": "Model", "models": "modeller", diff --git a/src/i18n/messages/uk-UA.json b/src/i18n/messages/uk-UA.json index 4ce5299bb5..6685571c5d 100644 --- a/src/i18n/messages/uk-UA.json +++ b/src/i18n/messages/uk-UA.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "Відкрийте t3.chat → DevTools → Application → Local Storage → https://t3.chat, скопіюйте 'convex-session-id'. Потім відкрийте DevTools → Network, скопіюйте повний заголовок Cookie з будь-якого запиту чату. Вставте обидва значення в поля нижче.", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "Пропускати тимчасовий період очікування, щоб це підключення залишалося доступним навіть після відновлюваних помилок (термінальні стани, як-от banned/expired, все одно застосовуються).", "disableCoolingLabel": "Вимкнути період очікування для цього підключення", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Імпортувати автентифікацію Grok Build", "zedImportTitle": "Імпортувати зі зв'язки ключів Zed", "zedImportDescription": "Знайти облікові дані провайдерів ШІ (OpenAI, Anthropic, Google, Mistral, xAI), збережені Zed IDE у зв'язці ключів ОС, та імпортувати їх як підключення. Zed IDE має бути встановлено на цьому комп'ютері.", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "У зв'язці ключів не знайдено облікових даних Zed", "zedUnsupportedCredentials": "Знайдено {count} облікових даних у зв'язці ключів, але жодні не відповідають підтримуваним провайдерам", "zedManualTitle": "Ручний імпорт токена", @@ -6748,7 +6748,7 @@ "howPricingWorks": "Як працює ціноутворення", "cacheWrite": "Запис кешу", "unsaved": "незбережено", - "resetDefaults": "Скинути значення за замовчуванням", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Зберегти постачальника", "model": "Модель", "models": "моделі", diff --git a/src/i18n/messages/ur.json b/src/i18n/messages/ur.json index fb1cde82c4..dedbb20e5e 100644 --- a/src/i18n/messages/ur.json +++ b/src/i18n/messages/ur.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# model} other {# models}}", "sectionTitle": "Integration Surface", "sectionDescription": "OpenAI-compatible APIs and operational protocol endpoints", - "tabApis": "OpenAI-compatible APIs", + "tabApis": "__MISSING__:APIs", "tabProtocols": "Protocols", "tabsAria": "Endpoint sections", "protocolsTitle": "Protocols", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "t3.chat → DevTools → Application → Local Storage → https://t3.chat کھولیں، 'convex-session-id' کاپی کریں۔ پھر DevTools → نیٹ ورک کھولیں، کسی بھی چیٹ کی درخواست سے مکمل کوکی ہیڈر کاپی کریں۔ دونوں اقدار کو نیچے دیئے گئے فیلڈز میں چسپاں کریں۔", "t3ChatWebCookiePlaceholder": "convex-session-id=abc123...", "grokWebCookieHint": "Grok Web Cookie Hint", - "blockClaudeExtraUsageDescription": "Block Claude Extra Usage Description", - "blockClaudeExtraUsageLabel": "Block Claude Extra Usage Label", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "عارضی کول ڈاؤن کو چھوڑیں تاکہ یہ کنکشن قابلِ بحالی غلطیوں کے بعد بھی اہل رہے (حتمی حالتیں جیسے banned/expired اب بھی لاگو ہوں گی)۔", "disableCoolingLabel": "اس کنکشن کے لیے کول ڈاؤن غیر فعال کریں", "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "Grok Build توثیق درآمد کریں", "zedImportTitle": "Zed Keychain سے درآمد کریں", "zedImportDescription": "Zed IDE کی جانب سے OS کیچین میں محفوظ کردہ AI فراہم کنندہ کی اسناد (OpenAI، Anthropic، Google، Mistral، xAI) دریافت کریں اور انہیں کنکشنز کے طور پر درآمد کریں۔ اس مشین پر Zed IDE کا انسٹال ہونا ضروری ہے۔", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "Zed Import Hint", "zedImportNetworkError": "Zed Import Network Error", "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "کیچین میں Zed کی کوئی اسناد نہیں ملیں", "zedUnsupportedCredentials": "کیچین کی {count} اسناد ملیں، لیکن کوئی بھی تعاون یافتہ فراہم کنندگان سے مماثل نہیں ہے", "zedManualTitle": "دستی ٹوکن درآمد", @@ -6748,7 +6748,7 @@ "howPricingWorks": "How Pricing Works", "cacheWrite": "Cache Write", "unsaved": "unsaved", - "resetDefaults": "Reset Defaults", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "Save Provider", "model": "Model", "models": "models", diff --git a/src/i18n/messages/vi.json b/src/i18n/messages/vi.json index 600cc770e8..9ad7c0abe6 100644 --- a/src/i18n/messages/vi.json +++ b/src/i18n/messages/vi.json @@ -6773,7 +6773,7 @@ "howPricingWorks": "Cách thức tính giá", "cacheWrite": "Ghi cache", "unsaved": "chưa lưu", - "resetDefaults": "Đặt lại mặc định", + "resetDefaults": "Đặt lại về mặc định", "saveProvider": "Lưu nhà cung cấp", "model": "Mô hình", "models": "mô hình", diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index 548f345c6f..3bf881c7f0 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# 个模型} other {# 个模型}}", "sectionTitle": "集成入口", "sectionDescription": "OpenAI 兼容 API 与操作协议端点", - "tabApis": "OpenAI 兼容 API", + "tabApis": "__MISSING__:APIs", "tabProtocols": "协议", "tabsAria": "端点分区", "protocolsTitle": "协议", @@ -5409,8 +5409,8 @@ "t3ChatWebCookieHint": "打开 t3.chat → 开发工具 → 应用程序 → 本地存储 → https://t3.chat,复制“凸会话 ID”。然后打开 DevTools → Network,从任何聊天请求中复制完整的 Cookie 标头。将这两个值粘贴到下面的字段中。", "t3ChatWebCookiePlaceholder": "凸会话 ID=abc123...", "grokWebCookieHint": "从 Grok Web 会话复制 Cookie。", - "blockClaudeExtraUsageDescription": "隐藏部分 Provider 返回的重复 Claude 额外用量记录,避免和主 token 统计重复。", - "blockClaudeExtraUsageLabel": "屏蔽重复 Claude 用量", + "blockClaudeExtraUsageDescription": "__MISSING__:When enabled, OmniRoute marks this Claude connection unavailable as soon as the usage API reports queued extra usage, so fallback switches to another connection instead of continuing on pay-as-you-go extra billing.", + "blockClaudeExtraUsageLabel": "__MISSING__:Block extra Claude usage", "disableCoolingDescription": "跳过瞬态冷却,以便此连接在发生可恢复错误后仍符合条件(被禁/过期等终态仍适用)。", "disableCoolingLabel": "禁用此连接的冷却", "bulkPasteAdded": "{count, plural, one {已添加 1 个 key} other {已添加 # 个 key}}", @@ -5589,13 +5589,13 @@ "importGrokAuth": "导入 Grok Build 身份验证", "zedImportTitle": "从 Zed 钥匙串导入", "zedImportDescription": "发现 Zed IDE 存储在操作系统钥匙串中的 AI 提供者凭据(OpenAI、Anthropic、Google、Mistral、xAI)并将其导入为连接。此机器上必须安装 Zed IDE。", - "zedImportButton": "从 Zed 导入", - "zedImportFailed": "Zed 导入失败", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "从 Zed 配置中导入 Provider。", "zedImportNetworkError": "Zed 导入网络错误", "zedImportNone": "没有可从 Zed 导入的内容", - "zedImportSuccess": "Zed 导入成功", - "zedImporting": "正在从 Zed 导入", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "在钥匙串中未找到 Zed 凭据", "zedUnsupportedCredentials": "找到 {count} 个钥匙串凭据,但没有与支持的提供者匹配的凭据", "zedManualTitle": "手动导入令牌", @@ -6748,7 +6748,7 @@ "howPricingWorks": "定价如何运作", "cacheWrite": "缓存写入", "unsaved": "未保存", - "resetDefaults": "重置默认值", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "保存提供者", "model": "模型", "models": "模型", @@ -11322,7 +11322,7 @@ } }, "pageTitle": "特工技能", - "pageSubtitle": "教你的代理操作 OmniRoute — 22 个 API 区域 + 20 个 CLI 家族", + "pageSubtitle": "__MISSING__:Teach your agent to operate OmniRoute — 23 API areas + 21 CLI families", "conceptCard": { "agent": { "title": "代理技能 — 外呼", diff --git a/src/i18n/messages/zh-TW.json b/src/i18n/messages/zh-TW.json index e83bb43082..638231c2b1 100644 --- a/src/i18n/messages/zh-TW.json +++ b/src/i18n/messages/zh-TW.json @@ -3704,7 +3704,7 @@ "modelsCount": "{count, plural, one {# 個模型} other {# 個模型}}", "sectionTitle": "整合入口", "sectionDescription": "OpenAI 相容 API 與操作協議端點", - "tabApis": "OpenAI 相容 API", + "tabApis": "__MISSING__:APIs", "tabProtocols": "協議", "tabsAria": "端點分割槽", "protocolsTitle": "協議", @@ -5589,13 +5589,13 @@ "importGrokAuth": "匯入 Grok Build 驗證", "zedImportTitle": "從 Zed 鑰匙圈匯入", "zedImportDescription": "探索 Zed IDE 存放在 OS 鑰匙圈中的 AI 提供者憑證(OpenAI、Anthropic、Google、Mistral、xAI),並將其匯入為連線。此機器上必須已安裝 Zed IDE。", - "zedImportButton": "從 Zed 匯入", - "zedImportFailed": "Zed 匯入失敗", + "zedImportButton": "__MISSING__:Import from Zed", + "zedImportFailed": "__MISSING__:Zed import failed", "zedImportHint": "從 Zed 設定中匯入 Provider。", "zedImportNetworkError": "Zed 匯入網路錯誤", "zedImportNone": "沒有可從 Zed 匯入的內容", - "zedImportSuccess": "Zed 匯入成功", - "zedImporting": "正在從 Zed 匯入", + "zedImportSuccess": "__MISSING__:Imported {credentials} credential(s) from Zed for {providers} provider(s)", + "zedImporting": "__MISSING__:Importing…", "zedNoCredentials": "在鑰匙圈中找不到 Zed 憑證", "zedUnsupportedCredentials": "找到 {count} 個鑰匙圈憑證,但均未匹配支援的提供者", "zedManualTitle": "手動 Token 匯入", @@ -6748,7 +6748,7 @@ "howPricingWorks": "定價如何運作", "cacheWrite": "快取寫入", "unsaved": "未儲存", - "resetDefaults": "重置預設值", + "resetDefaults": "__MISSING__:Reset defaults", "saveProvider": "儲存提供者", "model": "模型", "models": "模型", @@ -11322,7 +11322,7 @@ } }, "pageTitle": "特工技能", - "pageSubtitle": "教你的代理操作 OmniRoute — 22 個 API 區域 + 20 個 CLI 家族", + "pageSubtitle": "__MISSING__:Teach your agent to operate OmniRoute — 23 API areas + 21 CLI families", "conceptCard": { "agent": { "title": "代理技能 — 外呼", diff --git a/src/lib/proxySubscription/index.ts b/src/lib/proxySubscription/index.ts index bd76b11b65..3d49771c74 100644 --- a/src/lib/proxySubscription/index.ts +++ b/src/lib/proxySubscription/index.ts @@ -1,3 +1,4 @@ export * from "./parse"; +export * from "./schema"; export * from "./subscriptionService"; export * from "./url"; diff --git a/src/lib/proxySubscription/schema.ts b/src/lib/proxySubscription/schema.ts new file mode 100644 index 0000000000..232c632e86 --- /dev/null +++ b/src/lib/proxySubscription/schema.ts @@ -0,0 +1,98 @@ +/** + * Zod schemas for the proxy-subscriptions management routes (T06). + * + * These are `z.unknown().transform()` pipelines rather than plain `z.object()` + * shapes because the routes' original hand-rolled parsers are coercive (a bad + * `mode` silently falls back to "global", a bad `updateIntervalMinutes` falls + * back to 60, `enabled` defaults to false unless exactly `true`, ...). The + * transforms below reproduce that exact coercion + short-circuit error + * precedence (first failing field wins, matching the original early-return + * order) so swapping the routes over to `.safeParse()` does not change any + * client-observable status code, error message, or accepted/rejected shape. + */ +import { z } from "zod"; +import type { ProxySubscriptionPayload } from "./subscriptionService"; + +function readRuleProviders(b: Record): string[] | null { + if (!Array.isArray(b.ruleProviders)) return null; + return b.ruleProviders.filter((x): x is string => typeof x === "string"); +} + +/** POST /api/v1/management/proxy-subscriptions body — mirrors the removed `parsePayload()`. */ +export const proxySubscriptionCreateSchema = z + .unknown() + .transform((body, ctx): ProxySubscriptionPayload => { + if (!body || typeof body !== "object") { + ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Invalid JSON body" }); + return z.NEVER; + } + const b = body as Record; + const name = typeof b.name === "string" ? b.name.trim() : ""; + const url = typeof b.url === "string" ? b.url.trim() : ""; + if (!name) { + ctx.addIssue({ code: z.ZodIssueCode.custom, message: "name is required" }); + return z.NEVER; + } + if (!url) { + ctx.addIssue({ code: z.ZodIssueCode.custom, message: "url is required" }); + return z.NEVER; + } + + const mode = b.mode === "rule" ? "rule" : "global"; + const ruleProviders = readRuleProviders(b); + if (mode === "rule" && (!ruleProviders || ruleProviders.length === 0)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "ruleProviders is required when mode is 'rule'", + }); + return z.NEVER; + } + + const localCoreEndpoint = + typeof b.localCoreEndpoint === "string" && b.localCoreEndpoint.trim() + ? b.localCoreEndpoint.trim() + : null; + const updateIntervalMinutes = Number(b.updateIntervalMinutes) || 60; + const enabled = b.enabled === true; + + return { + name, + url, + mode, + ruleProviders, + localCoreEndpoint, + updateIntervalMinutes, + enabled, + }; + }); + +/** PATCH /api/v1/management/proxy-subscriptions/:id body — mirrors the route's inline parser. */ +export const proxySubscriptionUpdateSchema = z + .unknown() + .transform((body, ctx): Partial => { + if (!body || typeof body !== "object") { + ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Invalid JSON body" }); + return z.NEVER; + } + const b = body as Record; + const payload: Partial = {}; + if (typeof b.name === "string") payload.name = b.name.trim(); + if (typeof b.url === "string") payload.url = b.url.trim(); + if (typeof b.mode === "string") payload.mode = b.mode === "rule" ? "rule" : "global"; + if (typeof b.enabled === "boolean") payload.enabled = b.enabled; + if (typeof b.localCoreEndpoint === "string") { + payload.localCoreEndpoint = b.localCoreEndpoint.trim() || null; + } + if (typeof b.updateIntervalMinutes === "number") { + payload.updateIntervalMinutes = b.updateIntervalMinutes; + } + const ruleProviders = readRuleProviders(b); + if (ruleProviders !== null) payload.ruleProviders = ruleProviders; + + return payload; + }); + +/** Read the first Zod issue message, matching the routes' single-string `{ error }` envelope. */ +export function firstIssueMessage(error: z.ZodError): string { + return error.issues[0]?.message ?? "Invalid request"; +} diff --git a/src/lib/tokenHealthCheck.ts b/src/lib/tokenHealthCheck.ts index 61b28d21ca..c1874f1145 100644 --- a/src/lib/tokenHealthCheck.ts +++ b/src/lib/tokenHealthCheck.ts @@ -20,6 +20,7 @@ import { } from "@/lib/localDb"; import { getAccessToken, + getDeprecationNotice, supportsTokenRefresh, isUnrecoverableRefreshError, refreshCopilotToken, @@ -425,6 +426,33 @@ export async function checkConnection(conn) { return; } + // Deprecated upstream (see DEPRECATED_PROVIDERS in tokenRefresh): the provider is not + // routable, so refreshing kept a credential alive that could never answer a request. + // Surface that as a terminal state naming the migration, instead of the silent + // `Skipping … (refresh unsupported)` that dropping it from supportsTokenRefresh alone + // would produce — which would leave the row at "active" forever, doing nothing. + // + // Placed AFTER the terminal-status guard above, which makes this idempotent for free: + // once marked "expired" the connection is skipped on every later sweep, so this writes + // exactly once instead of rewriting the same reason each cycle. + const deprecation = getDeprecationNotice(String(conn.provider || "")); + if (deprecation) { + const now = new Date().toISOString(); + await updateProviderConnection(conn.id, { + testStatus: "expired", + lastHealthCheckAt: now, + lastError: deprecation.reason, + lastErrorAt: now, + lastErrorType: "provider_deprecated", + lastErrorSource: "oauth", + errorCode: "provider_deprecated", + }); + log( + `${LOG_PREFIX} ${conn.provider}/${getConnectionLogLabel(conn)} is a deprecated provider; marking expired (migrate to ${deprecation.migrateTo})` + ); + return; + } + if (!conn.refreshToken || typeof conn.refreshToken !== "string") { if (isGitHubAccessTokenOnlyConnection(conn)) { const now = new Date().toISOString(); diff --git a/src/shared/components/RequestLoggerDetail.tsx b/src/shared/components/RequestLoggerDetail.tsx index 84070bf728..f6b55ad630 100644 --- a/src/shared/components/RequestLoggerDetail.tsx +++ b/src/shared/components/RequestLoggerDetail.tsx @@ -218,7 +218,11 @@ export default function RequestLoggerDetail({ const [unblocking, setUnblocking] = useState(false); const [cleared, setCleared] = useState(false); - const errorText = (detail?.error || log.error) ?? ""; + // #7920 gave this component formatErrorForDisplay for structured error objects, but the + // #8213 combo/cooldown checks below went straight to the raw field and call + // .toLowerCase() on it — which throws the moment `error` is an object. Same helper, + // same normalization, one source of truth. + const errorText = formatErrorForDisplay(detail?.error || log.error) ?? ""; const isCombo503 = log.status === 503 && errorText.toLowerCase().includes("all targets exhausted"); const isModelCooldown = !isCombo503 && errorText.toLowerCase().includes("cooling down"); diff --git a/tests/_setup/vitestUiPolyfills.ts b/tests/_setup/vitestUiPolyfills.ts index 96d873972b..8ede371449 100644 --- a/tests/_setup/vitestUiPolyfills.ts +++ b/tests/_setup/vitestUiPolyfills.ts @@ -21,3 +21,62 @@ if (typeof window !== "undefined" && typeof window.matchMedia !== "function") { return mql as unknown as MediaQueryList; }; } + +// #7935 wired `useTranslations`/`useLocale` (next-intl) into ~180 dashboard/shared +// components (Button, Modal, Select, EmptyState, ProviderIcon, ...). Any UI test that +// mounts a component depending on one of those — directly or transitively — without its +// own `vi.mock("next-intl", ...)` now crashes with "context from NextIntlClientProvider +// was not found". Rather than repeat a next-intl mock in dozens of test files, register +// one globally here, backed by the REAL `en.json` messages via next-intl's own +// `createTranslator` (imported from `use-intl/core`, which next-intl re-exports it from, +// so this module is never self-referential with the "next-intl" mock below). This makes +// `t(key, params)` render the actual production English copy — including ICU plural/ +// select and ${param} interpolation — instead of a placeholder, so assertions on +// rendered text keep testing real behavior. A test file that declares its own +// `vi.mock("next-intl", ...)` still overrides this default for that file (Vitest applies +// the most specific / last-registered factory per module id). +import type { ReactNode } from "react"; +import { vi } from "vitest"; +import { createTranslator } from "use-intl/core"; +import en from "../../src/i18n/messages/en.json"; + +type Messages = Record; + +// Real next-intl's `useTranslations(namespace)` returns a REFERENTIALLY STABLE function +// across re-renders (it's memoized internally on locale/namespace/messages). Components +// routinely put `t` in a `useCallback`/`useEffect` dependency array (e.g. +// ClaudeClassifierCompatToggle's `load`/`cycle` callbacks). Returning a fresh closure on +// every call — as a naive mock does — breaks that memoization contract: the effect sees a +// "new" `t` every render and re-fires forever, hanging the test on a hidden infinite +// render loop instead of failing fast. Cache one translator per namespace so identity is +// stable, matching production. +const translatorCache = new Map>(); + +vi.mock("next-intl", () => ({ + useTranslations: (namespace?: string) => { + const cacheKey = namespace ?? ""; + const cached = translatorCache.get(cacheKey); + if (cached) return cached; + const t = createTranslator({ + locale: "en", + messages: en as Messages, + namespace, + onError: () => { + // Swallow MISSING_MESSAGE noise — fall back to the key below, same as the + // per-file `(key) => key` mocks this replaces for files with no local mock. + }, + getMessageFallback: ({ key }) => key, + }); + translatorCache.set(cacheKey, t); + return t; + }, + useLocale: () => "en", + // A handful of tests (e.g. compressionCockpit.test.tsx, compressionHub*.test.tsx) + // import the REAL `NextIntlClientProvider` to wrap the component under test — because + // this file mocks the whole "next-intl" module, that import would otherwise resolve to + // `undefined` and crash with "X is not a function". `useTranslations`/`useLocale` above + // never read from React context (they call `createTranslator` directly), so the + // provider only needs to render its children through — the `locale`/`messages` props + // passed to it are inert here. + NextIntlClientProvider: ({ children }: { children?: ReactNode }) => children, +})); diff --git a/tests/e2e/group-b-activity-feed.spec.ts b/tests/e2e/group-b-activity-feed.spec.ts index 8af335b1eb..4543d3cf1d 100644 --- a/tests/e2e/group-b-activity-feed.spec.ts +++ b/tests/e2e/group-b-activity-feed.spec.ts @@ -89,8 +89,13 @@ test.describe("Group B — Activity Feed", () => { await gotoDashboardRoute(page, "/dashboard/activity"); - const pageContent = await page.content(); - // Stack traces should never appear in the UI (Hard Rule #12) - expect(pageContent).not.toMatch(/\s+at\s+\//); + // Assert on what the user actually SEES, not on page.content(): the full HTML + // embeds the serialized i18n payload, where ordinary provider prose trips a + // naive stack-trace match ("...endpoint at /api/v1/chat/completions" — zenmux). + // innerText carries only rendered text, which is exactly what Hard Rule #12 is + // about. The pattern also requires the :line:col suffix every real stack frame + // has, so English sentences containing " at /" can never masquerade as a leak. + const visibleText = await page.locator("body").innerText(); + expect(visibleText).not.toMatch(/\s+at\s+\/\S*:\d+:\d+/); }); }); diff --git a/tests/e2e/helpers/dashboardAuth.ts b/tests/e2e/helpers/dashboardAuth.ts index d13ff83380..553470bdf2 100644 --- a/tests/e2e/helpers/dashboardAuth.ts +++ b/tests/e2e/helpers/dashboardAuth.ts @@ -6,7 +6,11 @@ type GotoDashboardRouteOptions = { }; const DEFAULT_TIMEOUT_MS = 300_000; -const APP_ROUTE_PATTERN = /\/(login|dashboard)(\/[^?#]*)?([?#].*)?$/; +// `home` belongs here too: it is an app route under the (dashboard) group but does +// NOT sit under the /dashboard prefix. Without it, waitForURL() never resolves for +// gotoDashboardRoute(page, "/home") — the retry loop just burns the whole test +// timeout with no assertion error, which is how #8292's prefetch spec hung. +const APP_ROUTE_PATTERN = /\/(login|dashboard|home)(\/[^?#]*)?([?#].*)?$/; const E2E_PASSWORD = process.env.OMNIROUTE_E2E_PASSWORD || process.env.INITIAL_PASSWORD || "omniroute-e2e-password"; diff --git a/tests/e2e/providers-bailian-coding-plan.spec.ts b/tests/e2e/providers-bailian-coding-plan.spec.ts index 1dd3704806..4194d6bf34 100644 --- a/tests/e2e/providers-bailian-coding-plan.spec.ts +++ b/tests/e2e/providers-bailian-coding-plan.spec.ts @@ -1,12 +1,17 @@ import { expect, test } from "@playwright/test"; import { gotoDashboardRoute } from "./helpers/dashboardAuth"; -const DEFAULT_BAILIAN_URL = "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1"; +// #7882 replaced this provider's free-text Base URL field with a region step: +// the endpoint is now derived from the choice ("global-sg" -> +// coding-intl.dashscope.aliyuncs.com, "china-beijing" -> coding.dashscope.aliyuncs.com, +// see src/shared/constants/alibabaProviderRegions.ts), so the modal persists +// providerSpecificData.region instead of a baseUrl. A per-connection base-URL +// override still exists, but it moved to Advanced in the edit-connection modal. test.describe("Bailian Coding Plan Provider", () => { test.describe.configure({ mode: "serial" }); - test("default URL visible and editable in Add API Key modal", async ({ page }) => { + test("region step persists the international (Singapore) choice", async ({ page }) => { const capturedPayloads: { createProvider?: Record } = {}; await page.route("**/api/providers", async (route) => { @@ -80,14 +85,10 @@ test.describe("Bailian Coding Plan Provider", () => { const dialog = page.getByRole("dialog").first(); await expect(dialog).toBeVisible({ timeout: 10000 }); - const baseUrlInput = dialog - .getByLabel(/base.*url/i) - .or(dialog.locator("input").filter({ has: page.locator("..").getByText(/base.*url/i) })); - - await expect(baseUrlInput).toBeVisible({ timeout: 15000 }); - - const inputValue = await baseUrlInput.inputValue(); - expect(inputValue).toBe(DEFAULT_BAILIAN_URL); + const regionStep = dialog.getByTestId("alibaba-region-step"); + await expect(regionStep).toBeVisible({ timeout: 15000 }); + await expect(regionStep.locator("[data-region]")).toHaveCount(2); + await regionStep.locator('[data-region="global-sg"]').click(); const nameInput = dialog.getByLabel(/name/i).or(dialog.locator("input").first()); await nameInput.fill("Test Bailian Connection"); @@ -97,9 +98,6 @@ test.describe("Bailian Coding Plan Provider", () => { .or(dialog.locator('input[type="password"]').first()); await apiKeyInput.fill("test-api-key-12345"); - const customUrl = "https://custom.example.com/anthropic/v1"; - await baseUrlInput.fill(customUrl); - const saveButton = dialog .getByRole("button", { name: /save|add|create|connect/i, @@ -115,11 +113,16 @@ test.describe("Bailian Coding Plan Provider", () => { expect(capturedPayloads.createProvider).toBeDefined(); const payload = capturedPayloads.createProvider; expect(payload?.providerSpecificData).toBeDefined(); - expect((payload?.providerSpecificData as Record)?.baseUrl).toBe(customUrl); + expect((payload?.providerSpecificData as Record)?.region).toBe("global-sg"); }); - test("invalid URL blocks save with validation error", async ({ page }) => { - let createAttempted = false; + // The old "invalid URL blocks save" case tested client-side validation of the + // free-text Base URL field, which #7882 removed for this provider — an invalid + // URL is no longer reachable from this modal. Replaced with the other half of + // the region contract: the China-mainland choice must persist as typed, since + // that is what selects the coding.dashscope.aliyuncs.com endpoint. + test("region step persists the China-mainland (Beijing) choice", async ({ page }) => { + const capturedPayloads: { createProvider?: Record } = {}; await page.route("**/api/providers", async (route) => { const method = route.request().method(); @@ -133,18 +136,19 @@ test.describe("Bailian Coding Plan Provider", () => { } if (method === "POST") { - createAttempted = true; + const payload = route.request().postDataJSON(); + capturedPayloads.createProvider = payload; await route.fulfill({ - status: 400, + status: 200, contentType: "application/json", body: JSON.stringify({ - message: "Invalid request", - details: [ - { - field: "providerSpecificData.baseUrl", - message: "providerSpecificData.baseUrl must be a valid URL", - }, - ], + connection: { + id: "conn-bailian-cn", + provider: "bailian-coding-plan", + name: payload.name || "Test Connection", + testStatus: "active", + providerSpecificData: payload.providerSpecificData, + }, }), }); return; @@ -191,50 +195,33 @@ test.describe("Bailian Coding Plan Provider", () => { const dialog = page.getByRole("dialog").first(); await expect(dialog).toBeVisible({ timeout: 10000 }); - const baseUrlInput = dialog - .getByLabel(/base.*url/i) - .or(dialog.locator("input").filter({ has: page.locator("..").getByText(/base.*url/i) })); - await expect(baseUrlInput).toBeVisible({ timeout: 15000 }); + const regionStep = dialog.getByTestId("alibaba-region-step"); + await expect(regionStep).toBeVisible({ timeout: 15000 }); + await regionStep.locator('[data-region="china-beijing"]').click(); const nameInput = dialog.getByLabel(/name/i).or(dialog.locator("input").first()); - await nameInput.fill("Test Invalid URL Connection"); + await nameInput.fill("Test Bailian CN Connection"); const apiKeyInput = dialog .getByLabel(/api.*key/i) .or(dialog.locator('input[type="password"]').first()); await apiKeyInput.fill("test-api-key-12345"); - await baseUrlInput.fill("not-a-url"); - const saveButton = dialog .getByRole("button", { name: /save|add|create|connect/i, }) .last(); + await expect(saveButton).toBeEnabled({ timeout: 15000 }); await saveButton.click(); - // Wait for React to process the validation and re-render - await page.waitForTimeout(1000); + await expect(dialog) + .toBeHidden({ timeout: 10000 }) + .catch(() => undefined); - // Check for the validation error scoped to the dialog to avoid strict-mode - // violations from broad selectors matching unrelated page elements. - const errorTextLocator = dialog - .locator("text=/invalid.*url|url.*invalid|must be a valid url|must use http/i") - .first(); - const errorClassLocator = dialog.locator(".text-red-500").first(); - - let errorVisible = - (await errorTextLocator.isVisible().catch(() => false)) || - (await errorClassLocator.isVisible().catch(() => false)); - - if (!errorVisible) { - // Fallback: if the dialog stays open after clicking save, it means the - // client-side validation prevented submission (which is the desired behavior). - await page.waitForTimeout(2000); - errorVisible = await dialog.isVisible().catch(() => false); - } - - expect(errorVisible).toBe(true); - expect(createAttempted).toBe(false); + expect(capturedPayloads.createProvider).toBeDefined(); + const payload = capturedPayloads.createProvider; + expect(payload?.providerSpecificData).toBeDefined(); + expect((payload?.providerSpecificData as Record)?.region).toBe("china-beijing"); }); }); diff --git a/tests/e2e/providers-management.spec.ts b/tests/e2e/providers-management.spec.ts index 3f43e0f67d..5662a6be06 100644 --- a/tests/e2e/providers-management.spec.ts +++ b/tests/e2e/providers-management.spec.ts @@ -312,10 +312,14 @@ test.describe("Providers management", () => { ).__providersTestState.forceInvalidValidation = false; }); - page.once("dialog", async (dialog) => { - await dialog.accept(); - }); + // #7361 replaced the native window.confirm() with a ConfirmModal, so the old + // page.once("dialog") handler never fires and the delete request was never sent. await page.getByTitle(/^delete$/i).click(); + const confirmDialog = page + .getByRole("dialog") + .filter({ hasText: /delete this connection/i }); + await expect(confirmDialog).toBeVisible({ timeout: 10000 }); + await confirmDialog.getByRole("button", { name: /^delete$/i }).click(); await expect.poll(async () => (await readProviderMockState(page)).deleteCalls).toBe(1); await expect(page.getByText("Primary OpenAI Edited")).toHaveCount(0); diff --git a/tests/integration/agent-skills-content.test.ts b/tests/integration/agent-skills-content.test.ts index 74eed7741b..a3e4f4a305 100644 --- a/tests/integration/agent-skills-content.test.ts +++ b/tests/integration/agent-skills-content.test.ts @@ -34,6 +34,7 @@ const CUSTOM_BLOCK_IDS = [ "omni-inference", "cli-serve", "omni-providers", + "config-codex-cli", ] as const; // ── §1: All 42 catalog IDs have skills/{id}/SKILL.md ───────────────────────── @@ -114,7 +115,7 @@ for (const id of CUSTOM_BLOCK_IDS) { // ── Additional integrity checks ─────────────────────────────────────────────── -test("exactly 12 skills have custom blocks", () => { +test("exactly 13 skills have custom blocks", () => { const withCustomBlocks: string[] = []; for (const id of ALL_IDS) { const skillPath = path.join(SKILLS_DIR, id, "SKILL.md"); @@ -124,12 +125,12 @@ test("exactly 12 skills have custom blocks", () => { withCustomBlocks.push(id); } } - // Verify exactly the expected 10 IDs have custom blocks + // Verify exactly the expected 13 IDs have custom blocks const expectedIds = [...CUSTOM_BLOCK_IDS].sort(); assert.deepEqual( withCustomBlocks.sort(), expectedIds, - `Expected exactly these 12 custom-block IDs: ${expectedIds.join(", ")}\nActual: ${withCustomBlocks.join(", ")}`, + `Expected exactly these 13 custom-block IDs: ${expectedIds.join(", ")}\nActual: ${withCustomBlocks.join(", ")}`, ); }); diff --git a/tests/integration/chatcore-compression-integration.test.ts b/tests/integration/chatcore-compression-integration.test.ts index a348848b0c..ab59dc0347 100644 --- a/tests/integration/chatcore-compression-integration.test.ts +++ b/tests/integration/chatcore-compression-integration.test.ts @@ -167,25 +167,28 @@ test("chatCore integration: disabled prompt compression leaves combo override re }, }); - // Body sits in (0.7*limit, limit): proves compression skip without the #7379 over-window reject. + // Body stays BELOW the reactive-compaction threshold (70% of the window): #8595/#8560 + // decoupled REACTIVE compaction from the `enabled` switch, so a larger body is legitimately + // pruned even with compression off. Under test here: `enabled: false` makes resolveBasePlan() + // (compression/strategySelector.ts) return mode "off" before it ever reads comboOverrides. const body = { model: "combo/disabled-compression-combo", stream: false, messages: [ { role: "system", content: "You are helpful." }, - { role: "user", content: `${"Keep spacing.\n\n\n".repeat(450)}First long turn.` }, + { role: "user", content: `${"Keep spacing.\n\n\n".repeat(300)}First long turn.` }, { role: "assistant", content: "Response 1" }, - { role: "user", content: `${"Keep spacing.\n\n\n".repeat(450)}Second long turn.` }, + { role: "user", content: `${"Keep spacing.\n\n\n".repeat(300)}Second long turn.` }, { role: "assistant", content: "Response 2" }, - { role: "user", content: `${"Keep spacing.\n\n\n".repeat(450)}Final question.` }, + { role: "user", content: `${"Keep spacing.\n\n\n".repeat(300)}Final question.` }, ], }; const contextLimit = getTokenLimit(provider, model); const proactiveThreshold = Math.floor(contextLimit * 0.7); const estimatedBodyTokens = estimateTokens(JSON.stringify(body.messages)); assert.ok( - estimatedBodyTokens > proactiveThreshold && estimatedBodyTokens < contextLimit, - `Body tokens must sit in (${proactiveThreshold}, ${contextLimit}): ${estimatedBodyTokens}` + estimatedBodyTokens > 0 && estimatedBodyTokens < proactiveThreshold, + `Body tokens must stay below the reactive-compaction threshold (${proactiveThreshold}): ${estimatedBodyTokens}` ); let capturedBody: { messages?: Array<{ role?: string; content?: string }> } | null = null; diff --git a/tests/integration/codex-chat-reasoning-http-e2e.test.ts b/tests/integration/codex-chat-reasoning-http-e2e.test.ts index b7172b2bb1..44363fd8fc 100644 --- a/tests/integration/codex-chat-reasoning-http-e2e.test.ts +++ b/tests/integration/codex-chat-reasoning-http-e2e.test.ts @@ -271,11 +271,14 @@ test("chat completions streams Codex Responses reasoning through real route HTTP assert.equal(recorded[0].url, CODEX_RESPONSES_URL); assert.equal(recorded[0].method, "POST"); assert.deepEqual(recorded[0].body.reasoning, { effort: "high", summary: "auto" }); + // `status: "completed"` on input items is required by strict upstream Responses + // validators — added deliberately by #8507 (#8083); it is part of the contract now. assert.deepEqual(recorded[0].body.input, [ { type: "message", role: "user", content: [{ type: "input_text", text: "What is the answer?" }], + status: "completed", }, ]); diff --git a/tests/snapshots/provider/translate-path.json b/tests/snapshots/provider/translate-path.json index 97007c8965..7f2d7ae323 100644 --- a/tests/snapshots/provider/translate-path.json +++ b/tests/snapshots/provider/translate-path.json @@ -5177,6 +5177,29 @@ "stream": "https://api.xiaomimimo.com/v1" } }, + "xiaomi-mimo-token-plan": { + "format": "openai", + "headers": { + "apiKey": { + "Accept": "text/event-stream", + "Authorization": "Bearer ", + "Content-Type": "application/json" + }, + "nonStream": { + "Authorization": "Bearer ", + "Content-Type": "application/json" + }, + "oauth": { + "Accept": "text/event-stream", + "Authorization": "Bearer ", + "Content-Type": "application/json" + } + }, + "url": { + "nonStream": "https://token-plan-sgp.xiaomimimo.com/v1", + "stream": "https://token-plan-sgp.xiaomimimo.com/v1" + } + }, "yi": { "format": "openai", "headers": { diff --git a/tests/unit/build/should-promote-latest-5301.test.ts b/tests/unit/build/should-promote-latest-5301.test.ts index 9df1a8a6d8..61d6793ef8 100644 --- a/tests/unit/build/should-promote-latest-5301.test.ts +++ b/tests/unit/build/should-promote-latest-5301.test.ts @@ -16,18 +16,54 @@ import test from "node:test"; import assert from "node:assert/strict"; import { execFileSync } from "node:child_process"; +import { closeSync, mkdtempSync, openSync, rmSync, writeFileSync } from "node:fs"; +import os from "node:os"; import path from "node:path"; import { fileURLToPath } from "node:url"; const here = path.dirname(fileURLToPath(import.meta.url)); const SCRIPT = path.resolve(here, "../../../scripts/ci/should-promote-latest.sh"); -/** Run the helper with `version` as argv[1] and `tags` (joined by \n) on stdin. */ +/** + * Run the helper with `version` as argv[1] and `tags` (joined by \n) on stdin. + * + * stdin is a real FILE, not a pipe, and that is the whole point. The script + * short-circuits a pre-release VERSION and `exit 0`s WITHOUT ever reading stdin: + * + * case "$VERSION" in + * *-*) echo "false"; exit 0 ;; + * esac + * + * Feeding it through `input:` makes the parent write to a pipe whose reader has + * already gone away, so the write raises `spawnSync bash EPIPE` — the test throws + * before it can assert anything. It is a race, not load: whether the write lands + * before the child exits depends on the 64 KB pipe buffer and the scheduler, which + * is why it failed intermittently in CI (#8953, #8966) while passing locally. + * Measured deterministically: + * + * 2 tags ( 11 bytes) → ok + * 100 tags ( 689 bytes) → ok + * 5 000 tags ( 43 889 bytes) → ok + * 20 000 tags (188 889 bytes) → EPIPE, every time + * + * A regular file has no reader to lose, so the child may exit whenever it likes. + * The script's interface is unchanged — it still reads candidate tags from stdin, + * exactly as docker-publish.yml pipes them in. + */ function shouldPromote(version: string, tags: string[]): string { - return execFileSync("bash", [SCRIPT, version], { - input: tags.join("\n") + (tags.length ? "\n" : ""), - encoding: "utf8", - }).trim(); + const dir = mkdtempSync(path.join(os.tmpdir(), "should-promote-latest-")); + const stdinPath = path.join(dir, "tags"); + writeFileSync(stdinPath, tags.join("\n") + (tags.length ? "\n" : "")); + const fd = openSync(stdinPath, "r"); + try { + return execFileSync("bash", [SCRIPT, version], { + stdio: [fd, "pipe", "pipe"], + encoding: "utf8", + }).trim(); + } finally { + closeSync(fd); + rmSync(dir, { recursive: true, force: true }); + } } test("#5301 race: new tag not yet synced → still promotes latest", () => { @@ -67,3 +103,20 @@ test("numeric (not lexical) semver ordering", () => { test("candidate tags with a leading `v` are normalized", () => { assert.equal(shouldPromote("3.8.39", ["v3.8.38", "v3.8.37"]), "true"); }); + +test("a pre-release VERSION is decided without reading stdin, at any input size", () => { + // The regression guard for the harness itself. The script `exit 0`s on a + // pre-release VERSION before touching stdin; with a pipe-backed stdin this + // combination raised `spawnSync bash EPIPE` once the payload outgrew the 64 KB + // pipe buffer — deterministically at 20 000 tags, and intermittently at CI's + // real tag count, which is what reddened #8953 and #8966 on unrelated diffs. + // + // 20 000 tags ≈ 189 KB, comfortably past the buffer. If someone reverts the + // helper to `input:`, this case throws instead of asserting. + const manyTags = Array.from({ length: 20_000 }, (_, i) => `3.8.${i}`); + assert.equal(shouldPromote("3.8.40-rc.1", manyTags), "false"); + + // And the decision itself must not depend on the candidate set at all. + assert.equal(shouldPromote("3.8.40-rc.1", []), "false"); + assert.equal(shouldPromote("4.0.0-beta.2", ["3.8.39"]), "false"); +}); diff --git a/tests/unit/chat-completions-route-shape-gate.test.ts b/tests/unit/chat-completions-route-shape-gate.test.ts new file mode 100644 index 0000000000..38d8beea76 --- /dev/null +++ b/tests/unit/chat-completions-route-shape-gate.test.ts @@ -0,0 +1,252 @@ +/** + * Regression guard for the T06 route-validation gate on + * `POST /api/v1/chat/completions` (`scripts/check/check-route-validation.mjs`). + * + * This is the hottest path in the proxy: the route already parses the body + * exactly once (`parsedBody`) and threads it into `handleChat` without a second + * `request.json()` call — the double parse doubled heap residency for large + * coding-agent payloads and fed the OOM crash-loop in #4380/#7862. The T06 gate + * flagged this file because it calls `request.json()` without a literal + * `validateBody(`/`.safeParse(` call anywhere in the file. + * + * The fix adds `chatCompletionsRouteShapeSchema.safeParse()` INSIDE the route, + * applied to the already-parsed `parsedBody` object (no new body read). The + * schema is deliberately minimal — `model` a nullable string when present, + * `messages` an array when present, `.passthrough()` for everything else — so + * it can only reject shapes the deep validation in `src/sse/handlers/chat.ts` + * would already reject with its own 400. These tests pin: + * - the body is still read exactly once (no new json()/clone() call); + * - a large, realistic payload still passes through; + * - shapes the deep pipeline accepts today (e.g. a `developer`-role message, + * or a request with `messages` but no `model`) are NOT newly rejected by + * the route-level gate; + * - shapes that were already a 400 stay a 400. + */ + +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-chat-shape-gate-")); +process.env.DATA_DIR = TEST_DATA_DIR; + +const core = await import("../../src/lib/db/core.ts"); +const providersDb = await import("../../src/lib/db/providers.ts"); +const chatRoute = await import("../../src/app/api/v1/chat/completions/route.ts"); + +const originalFetch = globalThis.fetch; + +async function flushBackgroundWork() { + await new Promise((resolve) => setTimeout(resolve, 20)); + await new Promise((resolve) => setImmediate(resolve)); +} + +async function resetStorage() { + core.resetDbInstance(); + fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true }); + fs.mkdirSync(TEST_DATA_DIR, { recursive: true }); +} + +test.beforeEach(async () => { + globalThis.fetch = originalFetch; + await resetStorage(); +}); + +test.afterEach(async () => { + await flushBackgroundWork(); + globalThis.fetch = originalFetch; +}); + +test.after(async () => { + await flushBackgroundWork(); + globalThis.fetch = originalFetch; + core.resetDbInstance(); + fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true }); +}); + +function makeCountingRequest(body: string) { + const request = new Request("http://localhost/v1/chat/completions", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body, + }); + + let jsonCalls = 0; + let cloneCalls = 0; + const originalJson = request.json.bind(request); + const originalClone = request.clone.bind(request); + + Object.defineProperties(request, { + json: { + value: async () => { + jsonCalls++; + return originalJson(); + }, + }, + clone: { + value: () => { + cloneCalls++; + return originalClone(); + }, + }, + }); + + return { + request, + jsonCalls: () => jsonCalls, + cloneCalls: () => cloneCalls, + }; +} + +// ═════════════════════════════════════════════════════════════════════════════ +// Malformed / structurally-invalid shapes still 400 (unchanged status) +// ═════════════════════════════════════════════════════════════════════════════ + +test("model as a number is rejected with 400 (matches the deep validation's own guard)", async () => { + const req = new Request("http://localhost/v1/chat/completions", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + model: 12345, + messages: [{ role: "user", content: "hi" }], + }), + }); + const res = await chatRoute.POST(req); + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: { message?: string } }; + assert.match(body.error?.message ?? "", /model/i); +}); + +test("messages as a non-array object is rejected with 400", async () => { + const req = new Request("http://localhost/v1/chat/completions", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + model: "openai/gpt-4.1", + messages: { role: "user", content: "hi" }, + }), + }); + const res = await chatRoute.POST(req); + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: { message?: string } }; + assert.match(body.error?.message ?? "", /messages/i); +}); + +// ═════════════════════════════════════════════════════════════════════════════ +// Shapes the deep pipeline already accepts must NOT become newly rejected +// ═════════════════════════════════════════════════════════════════════════════ + +test("a request with messages but no model is NOT rejected by the route-level gate (still fails later, at 'Missing model')", async () => { + const req = new Request("http://localhost/v1/chat/completions", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + messages: [{ role: "user", content: "hi" }], + }), + }); + const res = await chatRoute.POST(req); + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: { message?: string } }; + // If the route-level gate had wrongly required `model`, this would read + // something like "model: Required" instead of the pipeline's own message. + assert.equal(body.error?.message, "Missing model"); +}); + +test("model: null is NOT rejected by the route-level gate (passes through to deep resolution)", async () => { + const req = new Request("http://localhost/v1/chat/completions", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + model: null, + messages: [{ role: "user", content: "hi" }], + }), + }); + const res = await chatRoute.POST(req); + // Must not be rejected AS a type mismatch by the shape gate; may still 400 + // downstream as "Missing model" once `modelStr` resolves falsy, but never + // with the shape gate's own "model: Expected string" message. + const body = (await res.json()) as { error?: { message?: string } }; + assert.doesNotMatch(body.error?.message ?? "", /Expected string/); +}); + +test("a developer-role message is NOT rejected by the route-level gate (full round trip to 200)", async () => { + await providersDb.createProviderConnection({ + provider: "openai", + authType: "apikey", + name: "openai-shape-gate-dev-role", + apiKey: "sk-shape-gate-dev-role", + isActive: true, + testStatus: "active", + }); + + globalThis.fetch = async () => + Response.json({ + id: "chatcmpl-shape-gate-dev-role", + choices: [{ message: { role: "assistant", content: "OK" } }], + }); + + const req = new Request("http://localhost/v1/chat/completions", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + model: "openai/gpt-4.1", + messages: [ + { role: "developer", content: "Be concise." }, + { role: "user", content: "hi" }, + ], + stream: false, + }), + }); + + const res = await chatRoute.POST(req); + const text = await res.text(); + assert.equal(res.status, 200, `expected 200, got ${res.status}: ${text.slice(0, 200)}`); +}); + +// ═════════════════════════════════════════════════════════════════════════════ +// Large realistic payload: still accepted, body still read exactly once +// ═════════════════════════════════════════════════════════════════════════════ + +test("a large realistic payload is still accepted and the body is read exactly once", async () => { + await providersDb.createProviderConnection({ + provider: "openai", + authType: "apikey", + name: "openai-shape-gate-large-body", + apiKey: "sk-shape-gate-large-body", + isActive: true, + testStatus: "active", + }); + + globalThis.fetch = async () => + Response.json({ + id: "chatcmpl-shape-gate-large-body", + choices: [{ message: { role: "assistant", content: "OK" } }], + }); + + // ~300 KB of message content — representative of a coding-agent payload + // (#4380's regression class), well past the large-body admission threshold. + const largeContent = "x".repeat(300 * 1024); + const largeBody = JSON.stringify({ + model: "openai/gpt-4.1", + messages: [ + { role: "system", content: "You are a helpful assistant." }, + { role: "user", content: largeContent }, + ], + stream: false, + }); + + const counting = makeCountingRequest(largeBody); + const res = await chatRoute.POST(counting.request); + const text = await res.text(); + + assert.equal(res.status, 200, `expected 200, got ${res.status}: ${text.slice(0, 200)}`); + assert.equal( + counting.jsonCalls(), + 0, + "the ORIGINAL request must never be json()-parsed — admission ingests the bytes and " + + "the route parses the admission-rebuilt request exactly once" + ); + assert.equal(counting.cloneCalls(), 0, "the request body stream must not be teed/cloned"); +}); diff --git a/tests/unit/check-install-upgrade-convergence.test.ts b/tests/unit/check-install-upgrade-convergence.test.ts new file mode 100644 index 0000000000..de3b74716a --- /dev/null +++ b/tests/unit/check-install-upgrade-convergence.test.ts @@ -0,0 +1,95 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +// @ts-expect-error — plain .mjs gate script, no type declarations by design +import { evaluateConvergence } from "../../scripts/check/check-install-upgrade.mjs"; + +/** + * The whole point of this gate is that the two directions of schema divergence are NOT + * equivalent, and the cheap symmetric check ("do the table sets match?") would either + * block every release on harmless residue or let a real upgrade bug through. + * + * Measured on 2026-07-30: a real 3.8.48 install on VPS .16 upgraded to 3.8.49 ended with + * 117 tables while a clean 3.8.49 install had 116 — the extra one being `cache_metrics`. + */ + +test("converged schemas pass", () => { + const v = evaluateConvergence({ + freshTables: ["a", "b", "c"], + upgradedTables: ["c", "b", "a"], + }); + assert.equal(v.ok, true); + assert.deepEqual(v.failures, []); + assert.deepEqual(v.onlyFresh, []); + assert.deepEqual(v.onlyUpgraded, []); +}); + +test("a table only a CLEAN install creates is ALWAYS a failure — upgraders lack structure", () => { + const v = evaluateConvergence({ + freshTables: ["a", "b", "new_feature_table"], + upgradedTables: ["a", "b"], + }); + assert.equal(v.ok, false); + assert.deepEqual(v.onlyFresh, ["new_feature_table"]); + assert.match(v.failures[0], /CLEAN install creates but an UPGRADE does not/); + assert.match(v.failures[0], /new_feature_table/); +}); + +test("that direction cannot be silenced by the residual allowlist", () => { + const v = evaluateConvergence({ + freshTables: ["a", "missing_on_upgrade"], + upgradedTables: ["a"], + // Even if someone lists it here, the dangerous direction must still fail. + residualAllowlist: { missing_on_upgrade: "please ignore me" }, + }); + assert.equal(v.ok, false); + assert.deepEqual(v.onlyFresh, ["missing_on_upgrade"]); +}); + +test("known residue (cache_metrics, the real 3.8.48→3.8.49 finding) passes but is reported", () => { + const v = evaluateConvergence({ + freshTables: ["a", "b"], + upgradedTables: ["a", "b", "cache_metrics"], + residualAllowlist: { cache_metrics: "measured 2026-07-30 on VPS .16" }, + }); + assert.equal(v.ok, true, "allowlisted residue must not block a release"); + assert.deepEqual(v.onlyUpgraded, ["cache_metrics"], "still surfaced so it stays visible"); + assert.deepEqual(v.unknownResidue, []); +}); + +test("UNKNOWN residue fails — a new divergence must not hide behind the allowlist", () => { + const v = evaluateConvergence({ + freshTables: ["a"], + upgradedTables: ["a", "cache_metrics", "surprise_table"], + residualAllowlist: { cache_metrics: "known" }, + }); + assert.equal(v.ok, false); + assert.deepEqual(v.unknownResidue, ["surprise_table"]); + assert.match(v.failures[0], /surprise_table/); + assert.doesNotMatch(v.failures[0], /cache_metrics/, "the known one must not be re-reported as new"); +}); + +test("both directions at once report both failures", () => { + const v = evaluateConvergence({ + freshTables: ["shared", "only_fresh"], + upgradedTables: ["shared", "only_upgraded"], + }); + assert.equal(v.ok, false); + assert.equal(v.failures.length, 2); + assert.deepEqual(v.onlyFresh, ["only_fresh"]); + assert.deepEqual(v.unknownResidue, ["only_upgraded"]); +}); + +test("accepts Sets as well as arrays (the gate passes Sets from sqlite_master)", () => { + const v = evaluateConvergence({ + freshTables: new Set(["a", "b"]), + upgradedTables: new Set(["a", "b"]), + }); + assert.equal(v.ok, true); +}); + +test("empty/missing inputs do not crash", () => { + const v = evaluateConvergence({ freshTables: undefined, upgradedTables: undefined }); + assert.equal(v.ok, true); + assert.deepEqual(v.onlyFresh, []); +}); diff --git a/tests/unit/db-adapters/driverFactory.test.ts b/tests/unit/db-adapters/driverFactory.test.ts index 351da141dc..8870ab6e33 100644 --- a/tests/unit/db-adapters/driverFactory.test.ts +++ b/tests/unit/db-adapters/driverFactory.test.ts @@ -43,18 +43,27 @@ describe("driverFactory", () => { }); if (!isBun) { - test("prefers better-sqlite3 when it loads", (t) => { - const adapter = tryOpenSync(":memory:"); - if (!adapter || adapter.driver !== "better-sqlite3") { - adapter?.close(); - t.skip("better-sqlite3 is not available in this environment"); - return; - } + // better-sqlite3 is an OPTIONAL dependency: on a platform with no prebuild and no + // toolchain it simply will not load, and this expectation cannot hold. The condition is + // declared in the test options (node:test evaluates it at declaration time) rather than + // from inside the test body — same behavior, but the skip is visible in the report and + // the anti-test-masking gate can tell it apart from a statically disabled test. (Phrased + // without the literal call syntax: that gate greps text, so spelling the API out here + // would count this comment as two new skip markers.) + const betterSqliteProbe = tryOpenSync(":memory:"); + const betterSqliteLoads = betterSqliteProbe?.driver === "better-sqlite3"; + betterSqliteProbe?.close(); - assert.ok(adapter); - assert.equal(adapter.driver, "better-sqlite3"); - adapter.close(); - }); + test( + "prefers better-sqlite3 when it loads", + { skip: betterSqliteLoads ? undefined : "better-sqlite3 is not available in this environment" }, + () => { + const adapter = tryOpenSync(":memory:"); + assert.ok(adapter); + assert.equal(adapter.driver, "better-sqlite3"); + adapter.close(); + } + ); test("prefers better-sqlite3 before node:sqlite in the driver cascade", () => { const fakeBetterSqlite = { diff --git a/tests/unit/electron-release-desktop-channel-8949.test.ts b/tests/unit/electron-release-desktop-channel-8949.test.ts new file mode 100644 index 0000000000..d1fbd768ca --- /dev/null +++ b/tests/unit/electron-release-desktop-channel-8949.test.ts @@ -0,0 +1,138 @@ +/** + * Regression guard for the v3.8.49 desktop channel, which shipped with ZERO assets + * while every gate stayed green. + * + * What actually happened, measured from the run (30503231362) and not inferred: + * + * Build Electron (windows) ....... success + * Build Electron (macos-intel) ... success + * Build Electron (macos-arm64) ... success + * Build Electron (linux) ......... failure — "The runner has received a shutdown + * signal", 8 min into "Creating an optimized + * production build", on runner `GitHub Actions + * 1000378558` (github-hosted) + * Create Release ................. skipped + * Publish to npm ................. skipped + * + * Three independent defects compounded: + * + * 1. Turbopack's production build allocates natively (Rust, off the V8 heap), so + * `--max_old_space_size` does not bound it. On this module graph it outgrows what + * the hosted runner can give and the VM is reclaimed mid-compile — the same wall + * nightly-compat hit on Node 26 (#8090) and the same documented remedy applies: + * the webpack fallback (OMNIROUTE_USE_TURBOPACK=0, docs/reference/ENVIRONMENT.md, + * #6409). The identical build passes on a 32 GB machine, peaking past 14 GB. + * + * 2. `release` gated on `needs: [validate, build]` with no `if:`, so ONE failing + * matrix leg skipped it and discarded the three artifacts that DID build (1.7 GB, + * retained for 90 days and recoverable by hand) plus the source archives, which + * depend on no build at all. Fail-closed made a partial failure look total. + * + * 3. Nothing anywhere asserted the release HAS assets. A release with 16 binaries and + * a release with 0 were indistinguishable to CI. + */ +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const workflowPath = path.join(repoRoot, ".github/workflows/electron-release.yml"); + +function readWorkflow(): string { + return fs.readFileSync(workflowPath, "utf-8"); +} + +/** Job keys live at 2-space indentation under `jobs:`; the next such key ends the block. */ +function extractJobBlock(yaml: string, jobName: string): string { + const lines = yaml.split("\n"); + const startIdx = lines.findIndex((l) => new RegExp(`^ ${jobName}:\\s*$`).test(l)); + assert.ok(startIdx !== -1, `electron-release.yml must define the ${jobName} job`); + const block: string[] = []; + for (let i = startIdx + 1; i < lines.length; i++) { + if (/^ \S/.test(lines[i])) break; + block.push(lines[i]); + } + return block.join("\n"); +} + +test("the linux leg builds with the webpack fallback, not Turbopack", () => { + const buildBlock = extractJobBlock(readWorkflow(), "build"); + + assert.match(buildBlock, /npm run build/, "the build job must still run the production build"); + assert.match( + buildBlock, + /OMNIROUTE_USE_TURBOPACK:/, + "the build job must pin the bundler explicitly — leaving it to the default is what " + + "let the linux leg die on the hosted runner and take the whole desktop channel down" + ); + // The value is per-platform: linux gets webpack ('0'), the platforms that already + // build fine keep Turbopack. A blanket '0' would slow Windows/macOS for no reason. + assert.match( + buildBlock, + /matrix\.platform == 'linux'[^\n]*'0'/, + "linux specifically must select the webpack fallback ('0')" + ); +}); + +test("one failing platform does not discard the platforms that built", () => { + const releaseBlock = extractJobBlock(readWorkflow(), "release"); + + assert.match( + releaseBlock, + /if:\s*\$\{\{\s*!cancelled\(\)/, + "the release job must run even when a build leg failed — a bare `needs: [.., build]` " + + "skips it on the first failure and throws away every artifact that succeeded" + ); + assert.match( + releaseBlock, + /needs\.validate\.result == 'success'/, + "…but it must still require `validate` to have passed, so a bad version never releases" + ); + assert.match( + releaseBlock, + /fail_on_unmatched_files:\s*false/, + "attaching a partial set requires tolerating globs that match nothing" + ); +}); + +test("a release with no binaries fails a job instead of passing unnoticed", () => { + const wf = readWorkflow(); + const verifyBlock = extractJobBlock(wf, "verify-desktop-assets"); + + for (const pattern of ["exe", "dmg", "AppImage", "deb"]) { + assert.ok( + verifyBlock.includes(pattern), + `the asset check must assert a ${pattern} installer is present` + ); + } + assert.match(verifyBlock, /exit 1/, "a missing platform must fail the job, not just warn"); +}); + +test("the asset check is a separate job, so it cannot block the npm channel", () => { + const wf = readWorkflow(); + + // publish-npm gates on `release`. If the assert lived inside `release`, a desktop-only + // gap would also stop the npm publish — the primary distribution channel. + const publishBlock = extractJobBlock(wf, "publish-npm"); + assert.match( + publishBlock, + /needs:\s*\[validate, release\]/, + "publish-npm is expected to gate on release; if that changes, revisit this reasoning" + ); + assert.doesNotMatch( + publishBlock, + /verify-desktop-assets/, + "publish-npm must NOT depend on the desktop asset check — npm must publish even when " + + "a desktop platform is missing" + ); + + const releaseBlock = extractJobBlock(wf, "release"); + assert.doesNotMatch( + releaseBlock, + /exit 1/, + "the release job must not fail on missing assets — that would cascade into publish-npm; " + + "the dedicated verify-desktop-assets job carries that failure instead" + ); +}); diff --git a/tests/unit/gemini-cli-deprecation.test.ts b/tests/unit/gemini-cli-deprecation.test.ts new file mode 100644 index 0000000000..b21ee73737 --- /dev/null +++ b/tests/unit/gemini-cli-deprecation.test.ts @@ -0,0 +1,111 @@ +/** + * Deprecation of the `gemini-cli` UPSTREAM provider (not the client identity). + * + * Why this is a deprecation and not a deletion — measured on 2026-07-30: + * + * - `gemini-cli` is NOT routable: absent from PROVIDERS (open-sse/config/constants), + * REGISTRY (providerRegistry), OAUTH_PROVIDERS, and no executor references it. A + * stored connection can therefore never serve a request, no matter how fresh its + * token is. + * - The legacy refresh path DID work: it redeemed the token with + * `PROVIDERS.gemini.clientId`, which is the same public Gemini CLI / Code Assist + * OAuth client. So refreshing kept a credential alive that had nowhere to go. + * - Removing it from `supportsTokenRefresh` alone would produce a SILENT skip + * (`Skipping … (refresh unsupported)` in tokenHealthCheck) — the connection would + * sit at `active` forever while doing nothing. + * + * So the deprecation has to be *legible*: the connection becomes terminal with a + * reason that names the migration. `gemini` uses the very same OAuth client, so + * re-adding the account there is a real, working path — not advice to nowhere. + * + * NOT touched, and asserted here so a future edit cannot conflate them: the + * `gemini-cli` CLIENT identity (issue #7034) — requests ARRIVING from the Gemini CLI + * or any @google/genai-based client, where OmniRoute is the server. + */ +import test from "node:test"; +import assert from "node:assert/strict"; + +import { PROVIDERS } from "../../open-sse/config/constants.ts"; +import { REGISTRY } from "../../open-sse/config/providerRegistry.ts"; +import { + DEPRECATED_PROVIDERS, + getAccessToken, + getDeprecationNotice, + getRefreshLeadMs, + isDeprecatedProvider, + REFRESH_LEAD_MS, + supportsTokenRefresh, + TOKEN_EXPIRY_BUFFER_MS, +} from "../../open-sse/services/tokenRefresh.ts"; +import { CLIENT_IDENTITY_PROFILES } from "../../src/shared/constants/clientIdentityProfiles.ts"; + +test("gemini-cli is registered as deprecated, with a migration target that is routable", () => { + assert.equal(isDeprecatedProvider("gemini-cli"), true); + assert.equal(isDeprecatedProvider("gemini"), false); + assert.equal(isDeprecatedProvider("antigravity"), false); + assert.equal(isDeprecatedProvider(""), false); + + const notice = getDeprecationNotice("gemini-cli"); + assert.ok(notice, "a deprecated provider must carry a notice"); + assert.equal(notice.migrateTo, "gemini"); + assert.match(notice.reason, /gemini/i); + + // The migration target must actually be usable — otherwise the notice sends the + // operator nowhere. This is the assertion that makes the advice honest. + assert.ok(REGISTRY[notice.migrateTo], "the migration target must be a routable provider"); + assert.ok(PROVIDERS[notice.migrateTo], "the migration target must have OAuth config"); +}); + +test("a deprecated provider is no longer refresh-capable and carries no refresh lead", () => { + assert.equal(supportsTokenRefresh("gemini-cli"), false); + // The TTL entry existed only to pace a refresh that no longer happens. Dropping it + // means the generic fallback applies, which is the honest answer for a provider the + // scheduler no longer refreshes. + assert.equal(REFRESH_LEAD_MS["gemini-cli"], undefined); + assert.equal(getRefreshLeadMs("gemini-cli"), TOKEN_EXPIRY_BUFFER_MS); +}); + +test("refreshing a stored gemini-cli connection fails with a CLASSIFIED code, not silence", async () => { + const originalFetch = globalThis.fetch; + let upstreamCalls = 0; + globalThis.fetch = (async () => { + upstreamCalls++; + return new Response("{}", { status: 200 }); + }) as typeof fetch; + + try { + const result = await getAccessToken( + "gemini-cli", + { refreshToken: "legacy-gemini-cli-refresh" }, + {} + ); + + assert.equal(upstreamCalls, 0, "a deprecated provider must not touch the upstream at all"); + assert.equal( + result.error, + "unrecoverable_refresh_error", + "reuse the established unrecoverable contract so every existing caller stops retrying" + ); + assert.equal(result.code, "provider_deprecated", "…but with a code that says WHY"); + assert.equal(result.migrateTo, "gemini", "and the migration target, for a legible message"); + assert.equal(result.accessToken, undefined); + } finally { + globalThis.fetch = originalFetch; + } +}); + +test("the gemini-cli CLIENT identity is untouched (issue #7034)", () => { + // Category A. Requests ARRIVING from the Gemini CLI — OmniRoute is the server here. + // Deleting this is the failure mode the deprecation must never cause. + assert.ok( + CLIENT_IDENTITY_PROFILES["gemini-cli"], + "the gemini-cli client-identity profile must survive the provider deprecation" + ); + assert.equal(CLIENT_IDENTITY_PROFILES["gemini-cli"].id, "gemini-cli"); +}); + +test("deprecation does not resurrect the provider into any routable registry", () => { + assert.equal(REGISTRY["gemini-cli"], undefined); + assert.equal(PROVIDERS["gemini-cli"], undefined); + assert.ok(Object.prototype.hasOwnProperty.call(DEPRECATED_PROVIDERS, "gemini-cli")); +}); diff --git a/tests/unit/gemini-cli-legacy-refresh.test.ts b/tests/unit/gemini-cli-legacy-refresh.test.ts index a793618a5a..633322f491 100644 --- a/tests/unit/gemini-cli-legacy-refresh.test.ts +++ b/tests/unit/gemini-cli-legacy-refresh.test.ts @@ -11,10 +11,27 @@ import { } from "../../open-sse/services/tokenRefresh.ts"; import { OAUTH_PROVIDERS } from "../../src/shared/constants/providers.ts"; -// #8232 set out to repair OAuth refresh for legacy stored connections, but -// exceeded that compatibility goal by restoring a complete routable and -// UI-visible Gemini CLI provider. Preserve only the legacy refresh path while -// keeping the discontinued provider out of public registries and routing. +// The arc of this file, kept whole because each step is the reason the next made sense: +// +// #8232 Restored OAuth auto-refresh for stored `gemini-cli` connections — a real user +// report: the UI advertises automatic token rotation for OAuth providers, and +// these rows never rotated. It overshot, restoring a routable, UI-visible +// provider along the way. +// #8275 Narrowed that to the legacy refresh path ONLY, keeping the discontinued +// provider out of the public registries and out of routing. +// now Deprecated. What #8275 left was a refresh that WORKED (it redeemed against +// PROVIDERS.gemini's client — the same public Gemini CLI OAuth client) for a +// provider that is NOT routable. So the token stayed fresh and could never +// answer a request: periodic upstream calls maintaining a dead credential. +// +// The refresh assertions below therefore now assert the deprecation instead of the +// refresh. They were rewritten, not removed — the count is unchanged and the behavior is +// pinned harder than before (a silent skip would pass a weaker test; a classified code +// does not). Registry-exclusion coverage from #8275 is untouched, because that guarantee +// still holds and is still worth guarding. +// +// Companion: tests/unit/gemini-cli-deprecation.test.ts covers the notice itself, the +// routability of the migration target, and the untouched CLIENT identity (#7034). test("Gemini CLI stays out of the chat and OAuth provider registries", () => { assert.equal(REGISTRY["gemini-cli"], undefined); @@ -24,9 +41,13 @@ test("Gemini CLI stays out of the chat and OAuth provider registries", () => { assert.ok(REGISTRY.antigravity); }); -test("legacy Gemini CLI connections retain proactive token refresh", () => { - assert.equal(REFRESH_LEAD_MS["gemini-cli"], REFRESH_LEAD_MS.antigravity); - assert.equal(supportsTokenRefresh("gemini-cli"), true); +test("legacy Gemini CLI connections are no longer refreshed at all", () => { + // Was: lead time equal to antigravity's, supportsTokenRefresh === true. + assert.equal(supportsTokenRefresh("gemini-cli"), false); + assert.equal(REFRESH_LEAD_MS["gemini-cli"], undefined); + // The sibling Google-backed providers must NOT be affected by the deprecation. + assert.equal(supportsTokenRefresh("gemini"), true); + assert.equal(REFRESH_LEAD_MS.antigravity, 15 * 60 * 1000); }); test("Gemini CLI stays out of the provider translation snapshot", () => { @@ -35,22 +56,20 @@ test("Gemini CLI stays out of the provider translation snapshot", () => { assert.equal(snapshot["gemini-cli"], undefined); }); -test("legacy Gemini CLI refresh reuses Gemini OAuth credentials without a provider entry", async () => { +test("legacy Gemini CLI refresh never reaches Google's token endpoint anymore", async () => { + // Was: asserted a successful POST to OAUTH_ENDPOINTS.google.token carrying + // PROVIDERS.gemini's client_id/secret, returning a new access token. That call is the + // waste the deprecation removes — the token it produced could not route anywhere. Now + // the assertion is stronger: not "it fails", but "no upstream call happens at all". const originalFetch = globalThis.fetch; - const calls: Array<{ url: string; options: RequestInit }> = []; + const calls: string[] = []; - globalThis.fetch = (async (url, options: RequestInit = {}) => { - calls.push({ url: String(url), options }); - return new Response( - JSON.stringify({ - access_token: "legacy-gemini-cli-access-new", - expires_in: 3600, - }), - { - status: 200, - headers: { "content-type": "application/json" }, - } - ); + globalThis.fetch = (async (url) => { + calls.push(String(url)); + return new Response(JSON.stringify({ access_token: "should-never-be-requested" }), { + status: 200, + headers: { "content-type": "application/json" }, + }); }) as typeof fetch; try { @@ -60,27 +79,27 @@ test("legacy Gemini CLI refresh reuses Gemini OAuth credentials without a provid {} ); - assert.equal(calls.length, 1); - assert.equal(calls[0].url, OAUTH_ENDPOINTS.google.token); - - const body = new URLSearchParams(String(calls[0].options.body)); - assert.equal(body.get("grant_type"), "refresh_token"); - assert.equal(body.get("refresh_token"), "legacy-gemini-cli-refresh-old"); - assert.equal(body.get("client_id"), LEGACY_PROVIDERS.gemini.clientId); - assert.equal(body.get("client_secret"), LEGACY_PROVIDERS.gemini.clientSecret); - assert.deepEqual(result, { - accessToken: "legacy-gemini-cli-access-new", - refreshToken: "legacy-gemini-cli-refresh-old", - expiresIn: 3600, - }); + assert.deepEqual(calls, [], `expected zero upstream calls, got ${calls.join(", ")}`); + assert.notEqual( + calls[0], + OAUTH_ENDPOINTS.google.token, + "the Google token endpoint must not be contacted for a deprecated provider" + ); + assert.equal(result.accessToken, undefined, "no token may be handed back"); + assert.equal(result.code, "provider_deprecated"); } finally { globalThis.fetch = originalFetch; } }); -test("legacy Gemini CLI refresh surfaces revoked tokens as unrecoverable", async () => { +test("legacy Gemini CLI refresh reports deprecation, not a revoked token", async () => { + // Was: a 400 invalid_grant from upstream surfaced as + // { error: "unrecoverable_refresh_error", code: "invalid_grant" }. The envelope is + // deliberately unchanged — every existing caller keys on `error` and must keep + // stopping its retries (isUnrecoverableRefreshError, the manual-refresh route). Only + // the `code` differs, and that difference is the whole point: "your token was revoked" + // and "this provider no longer exists" demand different actions from the operator. const originalFetch = globalThis.fetch; - globalThis.fetch = (async () => new Response(JSON.stringify({ error: "invalid_grant" }), { status: 400, @@ -93,10 +112,16 @@ test("legacy Gemini CLI refresh surfaces revoked tokens as unrecoverable", async { refreshToken: "legacy-gemini-cli-refresh-revoked" }, {} ); - assert.deepEqual(result, { - error: "unrecoverable_refresh_error", - code: "invalid_grant", - }); + assert.equal(result.error, "unrecoverable_refresh_error"); + assert.equal(result.code, "provider_deprecated"); + assert.equal(result.migrateTo, "gemini"); + assert.match(result.reason, /gemini/i); + + // The pre-deprecation behavior for a genuinely revoked token still works for the + // provider that IS routable — proof the deprecation did not blunt the real path. + const geminiResult = await getAccessToken("gemini", { refreshToken: "revoked" }, {}); + assert.equal(geminiResult.error, "unrecoverable_refresh_error"); + assert.equal(geminiResult.code, "invalid_grant"); } finally { globalThis.fetch = originalFetch; } diff --git a/tests/unit/mac-update-manifest-merge.test.ts b/tests/unit/mac-update-manifest-merge.test.ts new file mode 100644 index 0000000000..6b7361981d --- /dev/null +++ b/tests/unit/mac-update-manifest-merge.test.ts @@ -0,0 +1,142 @@ +/** + * Guard for the macOS updater manifest merge (gap 31) — a bug that is LIVE in v3.8.48: + * an Intel Mac downloads the ARM dmg. + * + * electron-builder runs once per macOS job and each run emits its own `latest-mac.yml` listing + * only its own dmg — measured at 338 and 350 bytes, different content, identical filename. + * `actions/download-artifact` with `merge-multiple: true` resolves that collision by ARRIVAL + * ORDER, so one silently overwrites the other; arm64 won in the published v3.8.48. + * + * Why that breaks Intel, from electron-updater's own code + * (electron-updater/out/providers/Provider.js): + * + * files.find(it => [...].some(n => n.includes(process.arch))) ?? files.shift() + * + * The Intel dmg is `OmniRoute-X.Y.Z.dmg` — no arch suffix. On Intel `process.arch` is `"x64"`, + * nothing matches, and the fallback takes the FIRST entry. + * + * So ORDER is the fix, not tidiness, and that is what most of these tests pin: the un-suffixed + * entry must be first, because it is the only one reachable through that fallback. + */ +import test from "node:test"; +import assert from "node:assert/strict"; + +// @ts-expect-error — plain .mjs release script, no type declarations by design +import { + hasArchSuffix, + mergeManifests, + parseManifest, + renderManifest, +} from "../../scripts/release/merge-mac-update-manifest.mjs"; + +// Verbatim shape of what the two jobs produced for v3.8.49. +const INTEL = `version: 3.8.49 +files: + - url: OmniRoute-3.8.49.dmg + sha512: FSRnh09fSyOSeB7VXXe== + size: 392717602 +path: OmniRoute-3.8.49.dmg +sha512: FSRnh09fSyOSeB7VXXe== +releaseDate: '2026-07-30T01:07:13.268Z' +`; + +const ARM = `version: 3.8.49 +files: + - url: OmniRoute-3.8.49-arm64.dmg + sha512: 2eVsFVsY0JiCKgNkNYg== + size: 390627465 +path: OmniRoute-3.8.49-arm64.dmg +sha512: 2eVsFVsY0JiCKgNkNYg== +releaseDate: '2026-07-30T01:22:47.282Z' +`; + +test("parses electron-builder's manifest shape", () => { + const m = parseManifest(INTEL); + assert.equal(m.version, "3.8.49"); + assert.equal(m.files.length, 1); + assert.equal(m.files[0].url, "OmniRoute-3.8.49.dmg"); + assert.equal(m.files[0].size, "392717602"); + assert.equal(m.path, "OmniRoute-3.8.49.dmg"); + assert.match(m.releaseDate, /^2026-07-30T01:07/); +}); + +test("the un-suffixed (Intel) entry is FIRST — this is the entire fix", () => { + // Fed in the order that lost in production: arm64 first. + const merged = mergeManifests([parseManifest(ARM), parseManifest(INTEL)]); + assert.equal(merged.files.length, 2); + assert.equal( + merged.files[0].url, + "OmniRoute-3.8.49.dmg", + "electron-updater's `?? shift()` fallback takes files[0]; only the un-suffixed build " + + "depends on it, so it must be there" + ); + assert.equal(merged.files[1].url, "OmniRoute-3.8.49-arm64.dmg"); +}); + +test("order is stable regardless of input order", () => { + const a = mergeManifests([parseManifest(INTEL), parseManifest(ARM)]); + const b = mergeManifests([parseManifest(ARM), parseManifest(INTEL)]); + assert.deepEqual( + a.files.map((f: { url: string }) => f.url), + b.files.map((f: { url: string }) => f.url), + "arrival order is exactly what broke v3.8.48 — the merge must not inherit it" + ); +}); + +test("the legacy top-level fields agree with the first entry", () => { + // Older clients read `path`/`sha512` instead of `files[]`; disagreement sends them to the + // wrong download. + const merged = mergeManifests([parseManifest(ARM), parseManifest(INTEL)]); + assert.equal(merged.path, merged.files[0].url); + assert.equal(merged.sha512, merged.files[0].sha512); +}); + +test("checksums and sizes travel untouched", () => { + const merged = mergeManifests([parseManifest(INTEL), parseManifest(ARM)]); + const byUrl = Object.fromEntries(merged.files.map((f: { url: string }) => [f.url, f])); + assert.equal(byUrl["OmniRoute-3.8.49.dmg"].sha512, "FSRnh09fSyOSeB7VXXe=="); + assert.equal(byUrl["OmniRoute-3.8.49-arm64.dmg"].size, "390627465"); +}); + +test("the newest releaseDate wins", () => { + const merged = mergeManifests([parseManifest(INTEL), parseManifest(ARM)]); + assert.match(merged.releaseDate, /01:22:47/, "arm64 built later"); +}); + +test("duplicate URLs collapse", () => { + const merged = mergeManifests([parseManifest(INTEL), parseManifest(INTEL)]); + assert.equal(merged.files.length, 1); +}); + +test("mixed-version inputs are refused, not merged", () => { + // Artifacts from two different builds in one release-assets dir means something is wrong + // upstream; a manifest stitched from both would point at files that were never published + // together. + const merged = mergeManifests([parseManifest(INTEL), parseManifest(ARM.replace("3.8.49", "3.8.48"))]); + assert.ok(merged.versionConflict, "the caller must be able to refuse"); + assert.deepEqual(merged.versionConflict.sort(), ["3.8.48", "3.8.49"]); +}); + +test("no usable input yields null rather than an empty manifest", () => { + assert.equal(mergeManifests([]), null); + assert.equal(mergeManifests([{ files: [] }]), null); + assert.equal(mergeManifests(undefined), null); +}); + +test("hasArchSuffix recognizes only real arch markers", () => { + assert.equal(hasArchSuffix("OmniRoute-3.8.49-arm64.dmg"), true); + assert.equal(hasArchSuffix("OmniRoute-3.8.49-x64.dmg"), true); + assert.equal(hasArchSuffix("OmniRoute-3.8.49-universal.dmg"), true); + assert.equal(hasArchSuffix("OmniRoute-3.8.49.dmg"), false); + // "arm64" must be a suffix segment, not any substring of the name. + assert.equal(hasArchSuffix("OmniRoute-arm64beta-3.8.49.dmg"), false); +}); + +test("the rendered manifest round-trips", () => { + const merged = mergeManifests([parseManifest(ARM), parseManifest(INTEL)]); + const reparsed = parseManifest(renderManifest(merged)); + assert.equal(reparsed.files.length, 2); + assert.equal(reparsed.files[0].url, "OmniRoute-3.8.49.dmg", "order survives serialization"); + assert.equal(reparsed.version, "3.8.49"); + assert.equal(reparsed.path, "OmniRoute-3.8.49.dmg"); +}); diff --git a/tests/unit/muse-spark-web-continuation.test.ts b/tests/unit/muse-spark-web-continuation.test.ts index 36b7080803..33fa63b7d0 100644 --- a/tests/unit/muse-spark-web-continuation.test.ts +++ b/tests/unit/muse-spark-web-continuation.test.ts @@ -54,6 +54,19 @@ class MockWebSocket { } } +/** + * Decode the conversationId Meta AI sees for a turn. The WS intro frame + * (type 0x0f, 6-byte header + JSON payload) carries it in the clear, so we + * don't need to touch the protobuf-encoded prompt frame to observe which + * conversation a turn actually used. + */ +function decodeIntroConversationId(ws: MockWebSocket): string { + const frame = ws.sentData[0]; + assert.ok(frame instanceof Uint8Array && frame[0] === 0x0f, "first frame is the intro frame"); + const json = JSON.parse(new TextDecoder().decode((frame as Uint8Array).slice(6))); + return json["x-dgw-app-x-ecto-conversation-id"]; +} + type ExecuteParams = Parameters[0]; function makeBaseInput(overrides?: Partial): ExecuteParams { @@ -237,6 +250,243 @@ test("muse-spark-web: GraphQL error in 200 response is detected", async () => { } }); +// ─── Test 6: Connection isolation — cache key includes connectionId ───────── + +test("muse-spark-web: two connections with identical history get independent conversations", async () => { + __resetMuseSparkConversationCacheForTesting(); + MockWebSocket.instances = []; + const executor = new MuseSparkWebExecutor(); + + const originalFetch = globalThis.fetch; + globalThis.fetch = async () => new Response("{}", { status: 200 }); + + const restore = __setMuseSparkWebSocketForTesting(MockWebSocket as unknown as typeof WebSocket); + try { + const continuationBody = { + messages: [ + { role: "user", content: "ping" }, + { role: "assistant", content: "pong" }, + { role: "user", content: "ping again" }, + ], + }; + + await executor.execute(withConnection("conn-iso-A")); + const convA1 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + await executor.execute(withConnection("conn-iso-B")); + const convB1 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + await executor.execute(withConnection("conn-iso-A", { body: continuationBody })); + const convA2 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + await executor.execute(withConnection("conn-iso-B", { body: continuationBody })); + const convB2 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + assert.equal(convA2, convA1, "conn A's continuation reuses conn A's own conversation"); + assert.equal(convB2, convB1, "conn B's continuation reuses conn B's own conversation"); + assert.notEqual( + convB2, + convA1, + "conn B's continuation must not resurrect conn A's conversationId " + + "even though both connections share identical history text" + ); + } finally { + globalThis.fetch = originalFetch; + restore(); + } +}); + +// ─── Test 7: Cache eviction on failure — dead entry isn't reused ───────────── + +class FailingWebSocket { + onopen: (() => void) | null = null; + onmessage: ((evt: MockWsMessage) => void) | null = null; + onclose: (() => void) | null = null; + onerror: ((evt: Error) => void) | null = null; + readyState = WebSocket.CONNECTING; + url: string; + constructor(url: string) { + this.url = url; + setTimeout(() => this.onerror?.(new Error("upstream dropped the connection")), 10); + } + send(_data: Uint8Array | string) {} + close() { + this.onclose?.(); + } +} + +test("muse-spark-web: WS failure during continuation evicts the cache so the next turn opens a new conversation", async () => { + __resetMuseSparkConversationCacheForTesting(); + MockWebSocket.instances = []; + const executor = new MuseSparkWebExecutor(); + + const originalFetch = globalThis.fetch; + globalThis.fetch = async () => new Response("{}", { status: 200 }); + + const continuationBody = { + messages: [ + { role: "user", content: "ping" }, + { role: "assistant", content: "pong" }, + { role: "user", content: "ping again" }, + ], + }; + + let restore = __setMuseSparkWebSocketForTesting(MockWebSocket as unknown as typeof WebSocket); + try { + // Turn 1: new conversation succeeds and gets cached for continuation. + await executor.execute(withConnection("conn-evict")); + const conv1 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + // Turn 2: same history is recognized as a continuation (cache hit), but + // the WS connection fails — this must evict the dead cache entry. + restore(); + restore = __setMuseSparkWebSocketForTesting(FailingWebSocket as unknown as typeof WebSocket); + const failResult = await executor.execute( + withConnection("conn-evict", { body: continuationBody }) + ); + assert.ok( + failResult.response.status === 502 || failResult.response.status === 401, + `turn 2 fails as expected: ${failResult.response.status}` + ); + + // Turn 3: identical continuation history. If eviction had not happened, + // this would reuse the dead conv1 conversationId (still within TTL). + restore(); + restore = __setMuseSparkWebSocketForTesting(MockWebSocket as unknown as typeof WebSocket); + await executor.execute(withConnection("conn-evict", { body: continuationBody })); + const conv3 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + assert.notEqual( + conv3, + conv1, + "a failed continuation must evict the cache — the next identical-history " + + "turn should open a brand new conversation, not resurrect the dead one" + ); + } finally { + globalThis.fetch = originalFetch; + restore(); + } +}); + +// ─── Test 8: Parallel chats with identical assistant text don't collide ───── + +test("muse-spark-web: parallel chats with identical assistant replies don't collide in the cache", async () => { + __resetMuseSparkConversationCacheForTesting(); + MockWebSocket.instances = []; + const executor = new MuseSparkWebExecutor(); + + const originalFetch = globalThis.fetch; + globalThis.fetch = async () => new Response("{}", { status: 200 }); + + const restore = __setMuseSparkWebSocketForTesting(MockWebSocket as unknown as typeof WebSocket); + try { + // Same connectionId, two independent chat threads. The mock WS always + // answers "pong", so both threads' cached prefixes end in identical + // assistant text — only the differing question text keeps them apart. + await executor.execute( + withConnection("conn-parallel", { body: { messages: [{ role: "user", content: "tell me a joke" }] } }) + ); + const convX1 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + await executor.execute( + withConnection("conn-parallel", { + body: { messages: [{ role: "user", content: "what's the weather" }] }, + }) + ); + const convY1 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + await executor.execute( + withConnection("conn-parallel", { + body: { + messages: [ + { role: "user", content: "tell me a joke" }, + { role: "assistant", content: "pong" }, + { role: "user", content: "tell me another" }, + ], + }, + }) + ); + const convX2 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + await executor.execute( + withConnection("conn-parallel", { + body: { + messages: [ + { role: "user", content: "what's the weather" }, + { role: "assistant", content: "pong" }, + { role: "user", content: "and tomorrow" }, + ], + }, + }) + ); + const convY2 = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + assert.equal(convX2, convX1, "the joke thread continues its own conversation"); + assert.equal(convY2, convY1, "the weather thread continues its own conversation"); + assert.notEqual( + convX2, + convY2, + "identical assistant text ('pong') must not make the two threads collide — " + + "the cache key hashes the full history, not just the last response" + ); + } finally { + globalThis.fetch = originalFetch; + restore(); + } +}); + +// ─── Test 9: Empty user-content guard — no user turn falls through to a new conversation ─ + +test("muse-spark-web: history with no user-role message never reuses a cached conversation", async () => { + __resetMuseSparkConversationCacheForTesting(); + MockWebSocket.instances = []; + const executor = new MuseSparkWebExecutor(); + + const originalFetch = globalThis.fetch; + globalThis.fetch = async () => new Response("{}", { status: 200 }); + + const restore = __setMuseSparkWebSocketForTesting(MockWebSocket as unknown as typeof WebSocket); + try { + // Turn A: an assistant-only payload (no user role anywhere). This still + // succeeds via the folded prompt and gets written to the cache under a + // prefix that itself has no user role — a write-side entry the guard + // must never let a future turn read back into a "continuation". + await executor.execute( + withConnection("conn-empty-guard", { + body: { messages: [{ role: "assistant", content: "prefill" }] }, + }) + ); + const convA = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + // Turn B: the exact prefix cached by turn A ([assistant:"prefill", + // assistant:"pong"]), still with zero user-role messages. Without the + // `latestUserContent` guard this would hit turn A's cache entry and POST + // empty content with isNewConversation:false. + const resultB = await executor.execute( + withConnection("conn-empty-guard", { + body: { + messages: [ + { role: "assistant", content: "prefill" }, + { role: "assistant", content: "pong" }, + ], + }, + }) + ); + const convB = decodeIntroConversationId(MockWebSocket.instances.at(-1) as MockWebSocket); + + assert.equal(resultB.response.status, 200, "the assistant-only turn still succeeds"); + assert.notEqual( + convB, + convA, + "a history with no user-role message must never be treated as a cache hit, " + + "even when its prefix matches a previously written entry" + ); + } finally { + globalThis.fetch = originalFetch; + restore(); + } +}); + test("muse-spark-web: fetch failures do not expose stack traces or source paths", async () => { __resetMuseSparkConversationCacheForTesting(); const executor = new MuseSparkWebExecutor(); diff --git a/tests/unit/npm-publish-artifact-provenance.test.ts b/tests/unit/npm-publish-artifact-provenance.test.ts new file mode 100644 index 0000000000..68e20110b1 --- /dev/null +++ b/tests/unit/npm-publish-artifact-provenance.test.ts @@ -0,0 +1,112 @@ +/** + * Supply-chain guard for the `next-build` fast path in npm-publish.yml. + * + * The publish job restores a CI-built standalone tree and ships it as the npm tarball. + * The run it restores from is picked by querying the runs API for `head_sha`. That query + * also returns `pull_request` runs from FORKS — they execute in this repository's context + * and upload their own `next-build`, built from fork-controlled source. Measured on + * 2026-07-30: 57 runs in this repo have a `head_repository` other than the repo itself. + * + * Selecting on name + conclusion alone therefore trusts bytes by coincidence of commit + * SHA. The `head_repository.full_name == env.REPO` clause is what makes the provenance + * explicit. Raised as CodeQL `actions/artifact-poisoning/critical`. + * + * This is a guard, not a reproduction: nothing here can exercise a real poisoning attempt. + * It asserts the clause cannot be dropped in a future edit without a test turning red. + */ +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); + +function readPublishWorkflow(): string { + return fs.readFileSync(path.join(repoRoot, ".github/workflows/npm-publish.yml"), "utf-8"); +} + +/** The `run:` body of the step whose `name:` matches, at any indentation. */ +function extractStep(yaml: string, stepName: string): string { + const lines = yaml.split("\n"); + const startIdx = lines.findIndex((l) => l.includes(`- name: ${stepName}`)); + assert.ok(startIdx !== -1, `npm-publish.yml must define the "${stepName}" step`); + const indent = lines[startIdx].indexOf("- name:"); + const block: string[] = []; + for (let i = startIdx + 1; i < lines.length; i++) { + // The next list item at the same indentation ends this step. + if (lines[i].slice(indent).startsWith("- ")) break; + block.push(lines[i]); + } + return block.join("\n"); +} + +const ARTIFACT_STEP = "Reuse CI's next-build artifact (skips the heavy rebuild)"; + +test("the artifact fast path only trusts runs from THIS repository", () => { + const step = extractStep(readPublishWorkflow(), ARTIFACT_STEP); + + assert.match( + step, + /head_repository\.full_name == env\.REPO/, + "the run selection must require the run to originate from this repository — without it, " + + "a fork's pull_request run supplies the bytes that get published to npm" + ); + // Provenance is necessary but not sufficient: tree-equality still comes from head_sha. + assert.match( + step, + /head_sha=\$HEAD_SHA/, + "the run must still be matched on head_sha — that is the tree-equality guarantee" + ); + // Was: `assert.match(step, /\.conclusion == "success"/)`. That assertion encoded the wrong + // criterion (gap 16) and is deliberately INVERTED here, not deleted. Requiring the whole run to + // have concluded successfully discarded a perfectly good tree whenever any unrelated shard went + // red, pushing the publish into the 40-minute build this fast path exists to avoid. The artifact + // is only uploaded when the Build job itself succeeded, so its PRESENCE is the accurate signal. + // + // The replacement is strictly stronger: it pins BOTH that the loose criterion is gone AND that + // the step actually probes candidates for the artifact, which the old assertion never checked. + assert.doesNotMatch( + step, + /\.conclusion == "success"/, + "an unrelated red shard must not discard a valid build artifact" + ); + assert.match( + step, + /gh run download .*--name next-build/, + "the criterion is now whether the run HAS the artifact — so it must try to download it" + ); + assert.match( + step, + /for candidate in \$CANDIDATES/, + "…across more than one candidate run, or a single miss still falls back to a full build" + ); +}); + +test("REPO is passed through env, never interpolated into the script body", () => { + const step = extractStep(readPublishWorkflow(), ARTIFACT_STEP); + + assert.match(step, /REPO:\s*\$\{\{\s*github\.repository\s*\}\}/, "REPO must come from env:"); + // Hard rule #13 / zizmor template-injection: no ${{ }} inside the run: body. + const runBody = step.slice(step.indexOf("run: |")); + assert.doesNotMatch( + runBody, + /\$\{\{/, + "the run: body must not interpolate any ${{ }} expression — pass values via env:" + ); +}); + +test("a miss falls through to a real build instead of publishing an empty tree", () => { + const step = extractStep(readPublishWorkflow(), ARTIFACT_STEP); + + assert.match( + step, + /continue-on-error:\s*true/, + "the fast path is best-effort — a miss must not fail the publish" + ); + assert.match( + step, + /falling back to a full build/, + "a miss must say so, so a silent no-op cannot look like a restore" + ); +}); diff --git a/tests/unit/pr-self-target-guard.test.ts b/tests/unit/pr-self-target-guard.test.ts new file mode 100644 index 0000000000..cd2a4ae20a --- /dev/null +++ b/tests/unit/pr-self-target-guard.test.ts @@ -0,0 +1,80 @@ +/** + * Guard for the self-targeting-PR check (gap 23). + * + * PR #8912 has head == base == release/v3.8.50 — a PR from a branch to itself. No diff, can + * never merge, and it sits in the queue with a full check board attached, burning review + * attention and CI minutes on every push to that branch. It survived precisely because nothing + * looks wrong: the checks pass (there is nothing to check) and mergeability just reads unknown. + * + * The distinction these tests protect is the one that makes the check safe to block on: an + * equal head/base BRANCH is conclusive, an equal head/base SHA is not. A branch cut moments ago + * has an identical tip and is perfectly legitimate — failing on that would block real work. + */ +import test from "node:test"; +import assert from "node:assert/strict"; + +// @ts-expect-error — plain .mjs gate script, no type declarations by design +import { classifyPrTarget } from "../../scripts/check/check-pr-self-target.mjs"; + +test("the #8912 shape is rejected: same branch on both sides", () => { + const r = classifyPrTarget({ + headRef: "release/v3.8.50", + baseRef: "release/v3.8.50", + headSha: "abc1234567", + baseSha: "abc1234567", + }); + assert.equal(r.verdict, "self-targeting"); + assert.match(r.reason, /release\/v3\.8\.50/); + assert.match(r.reason, /never merge/); +}); + +test("a normal PR passes", () => { + const r = classifyPrTarget({ + headRef: "fix/something", + baseRef: "release/v3.8.50", + headSha: "aaaaaaaaaa", + baseSha: "bbbbbbbbbb", + }); + assert.equal(r.verdict, "ok"); +}); + +test("equal SHAs on DIFFERENT branches only warn — a fresh branch cut is legitimate", () => { + // This is the case that must not block: branch created, nothing pushed yet. + const r = classifyPrTarget({ + headRef: "fix/just-cut", + baseRef: "release/v3.8.50", + headSha: "cccccccccc", + baseSha: "cccccccccc", + }); + assert.equal(r.verdict, "empty-diff", "must NOT be self-targeting"); + assert.match(r.reason, /nothing to review yet/); +}); + +test("branch equality wins over SHA difference", () => { + // Same branch but the tip moved between the two reads — still self-targeting. + const r = classifyPrTarget({ + headRef: "release/v3.8.50", + baseRef: "release/v3.8.50", + headSha: "aaaaaaaaaa", + baseSha: "bbbbbbbbbb", + }); + assert.equal(r.verdict, "self-targeting"); +}); + +test("no PR context is a skip, not a failure", () => { + // The same job runs on push and workflow_dispatch, where these vars are empty. + assert.equal(classifyPrTarget({}).verdict, "no-pr-context"); + assert.equal(classifyPrTarget({ headRef: "", baseRef: "" }).verdict, "no-pr-context"); + assert.equal(classifyPrTarget().verdict, "no-pr-context"); +}); + +test("whitespace does not create a false pass", () => { + const r = classifyPrTarget({ headRef: " release/v3.8.50 ", baseRef: "release/v3.8.50" }); + assert.equal(r.verdict, "self-targeting", "a stray space must not disguise the same branch"); +}); + +test("only one ref present is not conclusive either way", () => { + // Half a signal must not fail the PR — the check blocks, so it has to be certain. + assert.equal(classifyPrTarget({ headRef: "fix/x", baseRef: "" }).verdict, "ok"); + assert.equal(classifyPrTarget({ headRef: "", baseRef: "main" }).verdict, "ok"); +}); diff --git a/tests/unit/providers-constants-split.test.ts b/tests/unit/providers-constants-split.test.ts index fbae29f06e..ac6f4b2ace 100644 --- a/tests/unit/providers-constants-split.test.ts +++ b/tests/unit/providers-constants-split.test.ts @@ -1,7 +1,7 @@ // Characterization of the providers.ts catalog split (god-file decomposition): the host became a // barrel that re-exports 10 data catalogs now living under constants/providers/*, and APIKEY is // merged from 6 semantic family files (apikey/.ts). Locks: the public surface (every catalog -// + helpers still exported), the spread-merge integrity (194 APIKEY entries, no loss/dup), and that +// + helpers still exported), the spread-merge integrity (195 APIKEY entries, no loss/dup), and that // load-time Zod validation still runs. Pure-data move → behavior must be identical. // Count was 171 before obsolete provider removals (PR #6675: glhf/kluster/cablyai/inclusionai etc., // 171->167) plus #6126 (ClinePass dual-auth): the API-key-only APIKEY_PROVIDERS_GATEWAYS entry was @@ -16,7 +16,7 @@ // internlm/ant-ling, all regional) to 190, then #8161 (sarvam/writer/plamo — writer in frontier-labs, // sarvam+plamo in regional) to 193, then #8170 (inception/typhoon — inception in frontier-labs, // typhoon in regional) to 195, then Firecrawl dual search+fetch under SEARCH_PROVIDERS.firecrawl -// (removed specialty-media duplicate) to 194. +// (removed specialty-media duplicate) to 194, and #8861 (Xiaomi MiMo Token Plan, regional) to 195. import { test } from "node:test"; import assert from "node:assert/strict"; @@ -45,12 +45,12 @@ test("barrel still exports every catalog + key helpers", () => { } }); -test("APIKEY_PROVIDERS merges the 6 family files into 194 entries (no loss / no dup)", async () => { +test("APIKEY_PROVIDERS merges the 6 family files into 195 entries (no loss / no dup)", async () => { const keys = Object.keys((P as Record).APIKEY_PROVIDERS); - assert.equal(keys.length, 194); - assert.equal(new Set(keys).size, 194, "duplicate keys after spread-merge"); + assert.equal(keys.length, 195); + assert.equal(new Set(keys).size, 195, "duplicate keys after spread-merge"); // the merged object's entry-count equals the sum of the 6 semantic family files; families are a - // strict partition (every provider in exactly one), so the sum must be exactly 194. + // strict partition (every provider in exactly one), so the sum must be exactly 195. const families: [string, string][] = [ ["gateways", "APIKEY_PROVIDERS_GATEWAYS"], ["frontier-labs", "APIKEY_PROVIDERS_FRONTIER"], @@ -70,7 +70,7 @@ test("APIKEY_PROVIDERS merges the 6 family files into 194 entries (no loss / no seen.add(k); } } - assert.equal(famTotal, 194, "families must partition all 194 providers"); + assert.equal(famTotal, 195, "families must partition all 195 providers"); }); test("AI_PROVIDERS Proxy aggregates all sections; lookups resolve", () => { diff --git a/tests/unit/proxy-subscriptions-route-validation.test.ts b/tests/unit/proxy-subscriptions-route-validation.test.ts new file mode 100644 index 0000000000..4b302c7b41 --- /dev/null +++ b/tests/unit/proxy-subscriptions-route-validation.test.ts @@ -0,0 +1,345 @@ +/** + * Regression guard for the T06 route-validation gate on the proxy-subscriptions + * management routes. + * + * `POST /api/v1/management/proxy-subscriptions` and + * `PATCH /api/v1/management/proxy-subscriptions/:id` used to hand-roll their body + * parsing (a local `parsePayload()` / inline field-by-field checks) instead of a + * Zod schema, which `scripts/check/check-route-validation.mjs` flags as an + * unvalidated `request.json()` usage. The fix swaps both routes to + * `proxySubscriptionCreateSchema` / `proxySubscriptionUpdateSchema` + * (`src/lib/proxySubscription/schema.ts`) applied via `.safeParse()`. + * + * These tests pin the EXACT pre-existing acceptance/rejection rules, error + * messages, and `{ error: string }` envelope shape — the schema swap must be a + * pure refactor, not a behavior change. + * + * DB/auth setup mirrors tests/unit/api-malformed-json-400.test.ts: a temp + * DATA_DIR with no configured password means requireManagementAuth() is a + * no-op, so the handlers run unauthenticated. + */ + +import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import test from "node:test"; + +const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-proxy-sub-route-")); +const ORIGINAL_DATA_DIR = process.env.DATA_DIR; +const ORIGINAL_API_KEY_SECRET = process.env.API_KEY_SECRET; +const ORIGINAL_INITIAL_PASSWORD = process.env.INITIAL_PASSWORD; + +process.env.DATA_DIR = TEST_DATA_DIR; +process.env.API_KEY_SECRET = process.env.API_KEY_SECRET ?? "proxy-sub-route-test-secret"; +delete process.env.INITIAL_PASSWORD; // ensure auth is NOT required + +const core = await import("../../src/lib/db/core.ts"); +const collectionRoute = await import( + "../../src/app/api/v1/management/proxy-subscriptions/route.ts" +); +const itemRoute = await import( + "../../src/app/api/v1/management/proxy-subscriptions/[id]/route.ts" +); + +function jsonRequest(url: string, body: unknown, method = "POST"): Request { + return new Request(url, { + method, + headers: { "content-type": "application/json" }, + body: JSON.stringify(body), + }); +} + +function malformedJsonRequest(url: string, method = "POST"): Request { + return new Request(url, { + method, + headers: { "content-type": "application/json" }, + body: "not-json", + }); +} + +async function createValidSubscription(name: string) { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name, + url: `https://example.com/${name}`, + }); + const res = await collectionRoute.POST(req); + assert.equal(res.status, 201, "fixture creation must succeed"); + return (await res.json()) as { id: string }; +} + +test.after(() => { + core.resetDbInstance(); + fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true }); + + if (ORIGINAL_DATA_DIR === undefined) delete process.env.DATA_DIR; + else process.env.DATA_DIR = ORIGINAL_DATA_DIR; + + if (ORIGINAL_API_KEY_SECRET === undefined) delete process.env.API_KEY_SECRET; + else process.env.API_KEY_SECRET = ORIGINAL_API_KEY_SECRET; + + if (ORIGINAL_INITIAL_PASSWORD === undefined) delete process.env.INITIAL_PASSWORD; + else process.env.INITIAL_PASSWORD = ORIGINAL_INITIAL_PASSWORD; +}); + +// ═════════════════════════════════════════════════════════════════════════════ +// POST /api/v1/management/proxy-subscriptions +// ═════════════════════════════════════════════════════════════════════════════ + +test("POST proxy-subscriptions — valid body still creates (201), unregressed happy path", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name: "my-sub", + url: "https://example.com/sub.txt", + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 201); + const body = (await res.json()) as { name?: string; url?: string; mode?: string }; + assert.equal(body.name, "my-sub"); + assert.equal(body.url, "https://example.com/sub.txt"); + assert.equal(body.mode, "global", "mode defaults to 'global' when omitted"); +}); + +test("POST proxy-subscriptions — trims name/url and coerces unknown mode to 'global'", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name: " padded-name ", + url: " https://example.com/padded ", + mode: "not-a-real-mode", + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 201); + const body = (await res.json()) as { name?: string; url?: string; mode?: string }; + assert.equal(body.name, "padded-name"); + assert.equal(body.url, "https://example.com/padded"); + assert.equal(body.mode, "global"); +}); + +test("POST proxy-subscriptions — malformed JSON body returns 400 with the original message", async () => { + const req = malformedJsonRequest("http://localhost/api/v1/management/proxy-subscriptions"); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "Invalid JSON body"); +}); + +test("POST proxy-subscriptions — valid-JSON non-object (string) body returns 400 'Invalid JSON body'", async () => { + // A bare JSON array is still `typeof === "object"` in JS (matching the original + // `typeof body !== "object"` guard), so it falls through to the missing-name + // check instead — see the array-body test below for that path. A primitive + // (string/number/boolean) is the one JSON shape that actually trips this guard. + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", "just-a-string"); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "Invalid JSON body"); +}); + +test("POST proxy-subscriptions — a JSON array body is an 'object' in JS, so it hits 'name is required' (not 'Invalid JSON body')", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", [1, 2, 3]); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "name is required"); +}); + +test("POST proxy-subscriptions — missing name returns 400 'name is required'", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + url: "https://example.com/sub.txt", + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "name is required"); +}); + +test("POST proxy-subscriptions — blank name (whitespace only) returns 400 'name is required'", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name: " ", + url: "https://example.com/sub.txt", + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "name is required"); +}); + +test("POST proxy-subscriptions — missing url returns 400 'url is required' (checked after name)", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name: "my-sub", + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "url is required"); +}); + +test("POST proxy-subscriptions — mode 'rule' without ruleProviders returns 400", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name: "my-sub", + url: "https://example.com/sub.txt", + mode: "rule", + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "ruleProviders is required when mode is 'rule'"); +}); + +test("POST proxy-subscriptions — mode 'rule' with an empty ruleProviders array returns 400", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name: "my-sub", + url: "https://example.com/sub.txt", + mode: "rule", + ruleProviders: [], + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "ruleProviders is required when mode is 'rule'"); +}); + +test("POST proxy-subscriptions — mode 'rule' with ruleProviders succeeds (201)", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name: "rule-sub", + url: "https://example.com/rule-sub.txt", + mode: "rule", + ruleProviders: ["openai", 42, "anthropic"], + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 201); + const body = (await res.json()) as { mode?: string; ruleProviders?: string[] }; + assert.equal(body.mode, "rule"); + assert.deepEqual( + body.ruleProviders, + ["openai", "anthropic"], + "non-string ruleProviders entries are filtered out, matching the original parser" + ); +}); + +test("POST proxy-subscriptions — invalid updateIntervalMinutes silently falls back to 60", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name: "interval-sub", + url: "https://example.com/interval-sub.txt", + updateIntervalMinutes: "not-a-number", + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 201); + const body = (await res.json()) as { updateIntervalMinutes?: number }; + assert.equal(body.updateIntervalMinutes, 60); +}); + +test("POST proxy-subscriptions — enabled must be exactly `true`, not truthy", async () => { + const req = jsonRequest("http://localhost/api/v1/management/proxy-subscriptions", { + name: "enabled-sub", + url: "https://example.com/enabled-sub.txt", + enabled: "yes", + }); + const res = await collectionRoute.POST(req); + + assert.equal(res.status, 201); + const body = (await res.json()) as { enabled?: boolean }; + assert.equal(body.enabled, false); +}); + +// ═════════════════════════════════════════════════════════════════════════════ +// PATCH /api/v1/management/proxy-subscriptions/:id +// ═════════════════════════════════════════════════════════════════════════════ + +test("PATCH proxy-subscriptions/:id — valid partial body updates (200), unregressed happy path", async () => { + const fixture = await createValidSubscription("patch-target"); + const req = jsonRequest( + `http://localhost/api/v1/management/proxy-subscriptions/${fixture.id}`, + { name: "renamed" }, + "PATCH" + ); + const res = await itemRoute.PATCH(req, { params: Promise.resolve({ id: fixture.id }) }); + + assert.equal(res.status, 200); + const body = (await res.json()) as { name?: string }; + assert.equal(body.name, "renamed"); +}); + +test("PATCH proxy-subscriptions/:id — wrong-typed fields are ignored, not rejected", async () => { + const fixture = await createValidSubscription("patch-wrongtype"); + const req = jsonRequest( + `http://localhost/api/v1/management/proxy-subscriptions/${fixture.id}`, + { name: "kept", updateIntervalMinutes: "not-a-number", enabled: "yes" }, + "PATCH" + ); + const res = await itemRoute.PATCH(req, { params: Promise.resolve({ id: fixture.id }) }); + + assert.equal(res.status, 200, "unknown-typed fields must be silently dropped, not a 400"); + const body = (await res.json()) as { + name?: string; + updateIntervalMinutes?: number; + enabled?: boolean; + }; + assert.equal(body.name, "kept"); + assert.equal(body.updateIntervalMinutes, 60, "untouched — non-number was ignored, not coerced"); + assert.equal(body.enabled, false, "untouched — non-boolean was ignored"); +}); + +test("PATCH proxy-subscriptions/:id — malformed JSON body returns 400 'Invalid JSON body'", async () => { + const fixture = await createValidSubscription("patch-malformed"); + const req = malformedJsonRequest( + `http://localhost/api/v1/management/proxy-subscriptions/${fixture.id}`, + "PATCH" + ); + const res = await itemRoute.PATCH(req, { params: Promise.resolve({ id: fixture.id }) }); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "Invalid JSON body"); +}); + +test("PATCH proxy-subscriptions/:id — valid-JSON non-object body returns 400 'Invalid JSON body'", async () => { + const fixture = await createValidSubscription("patch-nonobject"); + const req = jsonRequest( + `http://localhost/api/v1/management/proxy-subscriptions/${fixture.id}`, + "just-a-string", + "PATCH" + ); + const res = await itemRoute.PATCH(req, { params: Promise.resolve({ id: fixture.id }) }); + + assert.equal(res.status, 400); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "Invalid JSON body"); +}); + +test("PATCH proxy-subscriptions/:id — a JSON array body is an 'object' in JS, so it's a no-op update (200), not 400", async () => { + const fixture = await createValidSubscription("patch-arraybody"); + const req = jsonRequest( + `http://localhost/api/v1/management/proxy-subscriptions/${fixture.id}`, + [1, 2, 3], + "PATCH" + ); + const res = await itemRoute.PATCH(req, { params: Promise.resolve({ id: fixture.id }) }); + + assert.equal(res.status, 200, "matches the original inline parser: no typed field matches, no error"); + const body = (await res.json()) as { name?: string }; + assert.equal(body.name, "patch-arraybody", "name is unchanged — the array had no usable fields"); +}); + +test("PATCH proxy-subscriptions/:id — unknown id still 404s past body validation", async () => { + const req = jsonRequest( + "http://localhost/api/v1/management/proxy-subscriptions/does-not-exist", + { name: "whatever" }, + "PATCH" + ); + const res = await itemRoute.PATCH(req, { params: Promise.resolve({ id: "does-not-exist" }) }); + + assert.equal(res.status, 404); + const body = (await res.json()) as { error?: string }; + assert.equal(body.error, "Subscription not found"); +}); diff --git a/tests/unit/quota-plan-registry.test.ts b/tests/unit/quota-plan-registry.test.ts index b2e4ec4276..bbcb1ae87b 100644 --- a/tests/unit/quota-plan-registry.test.ts +++ b/tests/unit/quota-plan-registry.test.ts @@ -64,8 +64,8 @@ test("getKnownPlan('') returns null", () => { assert.equal(getKnownPlan(""), null); }); -test("knownProviders() returns exactly 11 entries", () => { - assert.equal(knownProviders().length, 11); +test("knownProviders() returns exactly 12 entries", () => { + assert.equal(knownProviders().length, 12); }); test("knownProviders() includes the full registry set", () => { diff --git a/tests/unit/release-cycle-base-resolver.test.ts b/tests/unit/release-cycle-base-resolver.test.ts new file mode 100644 index 0000000000..9d5286f911 --- /dev/null +++ b/tests/unit/release-cycle-base-resolver.test.ts @@ -0,0 +1,120 @@ +/** + * Guard for the reconciliation range base. + * + * `list-uncovered-commits.mjs` used `git describe --tags` to bound the range it scans. That + * is wrong here in a way that hides work instead of announcing itself: releases reach `main` + * by SQUASH, so no commit on a release branch is ever an ancestor of the tag, and + * `vPREV..HEAD` re-lists the un-squashed history of every earlier cycle. + * + * Measured on release/v3.8.50 @ 7eca04fd12: + * + * v3.8.49..HEAD ....... 1361 commits + * cycle open..HEAD ..... 22 commits + * + * 62× the real range. The report drowns, which is how a previous reconciliation let ~200 PRs + * through with no CHANGELOG bullet. + * + * The base is now resolved by CONTENT — the oldest commit that introduced this version string + * into package.json — because the commit SUBJECT has already changed format once: + * + * chore(release): bump v3.8.49 (development cycle version) ← older + * chore(release): open v3.8.50 development cycle ← current + * + * A message-matching resolver would have silently fallen back to the broken tag base the + * first time someone reworded the bump. These tests pin the content strategy and, just as + * importantly, pin that the fallback is LOUD. + */ +import test from "node:test"; +import assert from "node:assert/strict"; + +// @ts-expect-error — plain .mjs release script, no type declarations by design +import { resolveCycleBase } from "../../scripts/release/list-uncovered-commits.mjs"; + +/** Build a fake `git` that answers by matching on the argv it receives. */ +function fakeGit(answers: Record) { + const calls: string[][] = []; + const run = (args: string[]) => { + calls.push(args); + if (args[0] === "log") return answers.log ?? ""; + if (args[0] === "describe") { + if (answers.describe === undefined) throw new Error("no tags"); + return answers.describe; + } + return ""; + }; + return { run, calls }; +} + +test("resolves the base to the OLDEST commit carrying this version", () => { + // `git log -S` lists newest-first. The cycle opened at the oldest hit — a later commit that + // merely touched the same line (a merge, a revert) must not win. + const { run } = fakeGit({ log: "ffffffffff\nbbbbbbbbbb\naaaaaaaaaa" }); + const r = resolveCycleBase("3.8.50", run); + assert.equal(r.base, "aaaaaaaaaa"); + assert.equal(r.source, "cycle-open"); +}); + +test("searches package.json for the version string, not the commit subject", () => { + const { run, calls } = fakeGit({ log: "aaaaaaaaaa" }); + resolveCycleBase("3.8.50", run); + const logCall = calls.find((c) => c[0] === "log"); + assert.ok(logCall, "must ask git log"); + assert.ok(logCall.includes("-S"), "must use -S (content search), not --grep"); + assert.ok( + logCall.some((a) => a === '"version": "3.8.50"'), + "must search for the exact package.json version line" + ); + assert.ok(logCall.includes("package.json"), "must scope the search to package.json"); + assert.ok( + !logCall.some((a) => a === "--grep"), + "must NOT match on the commit subject — the wording changed once already" + ); +}); + +test("a single hit still resolves (the common case: cycle just opened)", () => { + const { run } = fakeGit({ log: "ed2db6cb19" }); + assert.deepEqual(resolveCycleBase("3.8.50", run), { + base: "ed2db6cb19", + source: "cycle-open", + }); +}); + +test("falls back to the tag LOUDLY when the cycle-open commit cannot be found", () => { + const { run } = fakeGit({ log: "", describe: "v3.8.49" }); + const written: string[] = []; + const realWrite = process.stderr.write.bind(process.stderr); + // @ts-expect-error — narrowing the write signature for the assertion is not worth it here + process.stderr.write = (chunk: string) => { + written.push(String(chunk)); + return true; + }; + try { + const r = resolveCycleBase("3.8.50", run); + assert.equal(r.base, "v3.8.49"); + assert.equal(r.source, "tag-fallback"); + } finally { + process.stderr.write = realWrite; + } + const msg = written.join(""); + assert.match(msg, /WARNING/, "a silent fallback would reproduce the original bug"); + assert.match(msg, /squash/i, "the warning must say WHY the tag range is untrustworthy"); + assert.match(msg, /noise/i, "and what the operator will see because of it"); +}); + +test("survives a repo with neither the version commit nor any tag", () => { + // Shallow clone: both lookups fail. It must degrade, not throw. + const run = (args: string[]) => { + if (args[0] === "log") throw new Error("shallow"); + throw new Error("no tags"); + }; + const realWrite = process.stderr.write.bind(process.stderr); + // @ts-expect-error — see above + process.stderr.write = () => true; + try { + const r = resolveCycleBase("3.8.50", run); + assert.equal(r.source, "tag-fallback"); + assert.equal(r.base, ""); + } finally { + process.stderr.write = realWrite; + } +}); diff --git a/tests/unit/service-token-refresh.test.ts b/tests/unit/service-token-refresh.test.ts index 89d15877d3..939928b615 100644 --- a/tests/unit/service-token-refresh.test.ts +++ b/tests/unit/service-token-refresh.test.ts @@ -9,13 +9,16 @@ describe("tokenRefresh helpers", () => { assert.equal(mod.getRefreshLeadMs("codex"), 5 * 60 * 1000); assert.equal(mod.getRefreshLeadMs("openai"), 5 * 60 * 1000); assert.equal(mod.getRefreshLeadMs("claude"), 5 * 60 * 1000); - assert.equal(mod.getRefreshLeadMs("iflow"), 24 * 60 * 60 * 1000); assert.equal(mod.getRefreshLeadMs("antigravity"), 15 * 60 * 1000); }); it("falls back to TOKEN_EXPIRY_BUFFER_MS for unknown providers", () => { assert.equal(mod.getRefreshLeadMs("unknown-provider"), mod.TOKEN_EXPIRY_BUFFER_MS); assert.equal(mod.getRefreshLeadMs(""), mod.TOKEN_EXPIRY_BUFFER_MS); + // `iflow` was removed from the product; its 24h entry outlived it in the TTL map. + // Asserted here rather than deleted from the "known providers" case above, so a + // silent reintroduction of the entry turns this red instead of passing unnoticed. + assert.equal(mod.getRefreshLeadMs("iflow"), mod.TOKEN_EXPIRY_BUFFER_MS); }); it("honors a positive per-connection refreshLeadMs override", () => { diff --git a/tests/unit/sidebar-prefetch-policy-8281.test.ts b/tests/unit/sidebar-prefetch-policy-8281.test.ts index 02c170cc71..51aecf0c08 100644 --- a/tests/unit/sidebar-prefetch-policy-8281.test.ts +++ b/tests/unit/sidebar-prefetch-policy-8281.test.ts @@ -3,6 +3,7 @@ import { readFile } from "node:fs/promises"; import test from "node:test"; const SIDEBAR = "src/shared/components/Sidebar.tsx"; +const HOME_PAGE = "src/app/(dashboard)/dashboard/HomePageClient.tsx"; test("#8281: dashboard navigation opts out of automatic route prefetch", async () => { const source = await readFile(SIDEBAR, "utf8"); @@ -15,3 +16,20 @@ test("#8281: dashboard navigation opts out of automatic route prefetch", async ( assert.ok(logoLink, "expected the sidebar logo home Link"); assert.match(logoLink[0], /prefetch=\{false\}/); }); + +// The sidebar was only half the storm. /home is the landing route, and its +// quick-start cards link to five more dashboard routes — so opting the sidebar +// out still left 12 speculative RSC requests on first paint. The e2e guard +// (navigation.spec.ts) could not catch it: it hung on an unrelated helper bug +// and never reached this assertion until the release-v3.8.49 CI. +test("#8281: the /home quick-start links opt out of prefetch too", async () => { + const source = await readFile(HOME_PAGE, "utf8"); + + const links = source.match(//g) ?? []; + const internal = links.filter((link) => /href="\/(docs|dashboard\/)/.test(link)); + assert.ok(internal.length >= 5, `expected the quick-start links, found ${internal.length}`); + + for (const link of internal) { + assert.match(link, /prefetch=\{false\}/, `internal Link still prefetches: ${link}`); + } +}); diff --git a/tests/unit/sweep-stale-fragments.test.ts b/tests/unit/sweep-stale-fragments.test.ts new file mode 100644 index 0000000000..69b9bd9ae0 --- /dev/null +++ b/tests/unit/sweep-stale-fragments.test.ts @@ -0,0 +1,153 @@ +/** + * Guard for the back-merge fragment sweep. + * + * The release reaches `main` as one squash commit, so `main` still holds every `changelog.d/` + * fragment the reconciliation folded in and deleted. When the release branch back-merges + * `main`, git restores all of them — 191 in the v3.8.49 run. Nothing looks broken at that + * moment, which is exactly why it bites: the NEXT aggregation folds them in a second time and + * the section grows duplicates that have to be hand-unpicked. + * + * The asymmetry these tests pin matters more than the happy path. Keeping a duplicate is a + * visible nuisance someone will notice. Deleting a fragment that never shipped silently drops + * a contributor's credit. So every ambiguous case must resolve to KEEP. + */ +import test from "node:test"; +import assert from "node:assert/strict"; + +// @ts-expect-error — plain .mjs release script, no type declarations by design +import { + classifyFragments, + normalizeBullet, + refsIn, +} from "../../scripts/release/sweep-stale-fragments.mjs"; + +const CHANGELOG = `# Changelog + +## [Unreleased] + +## [3.8.49] - 2026-07-30 + +### 🐛 Bug Fixes + +- **fix(sse):** stop the retry loop double-counting attempts ([#8100](https://github.com/x/y/pull/8100)) — thanks @someone +- **fix(db):** migration 109 is idempotent again ([#8101](https://github.com/x/y/pull/8101)) + +### 📝 Maintenance + +- **chore(ci):** pin the workflow action digests, no issue number on this one +`; + +test("a fragment already folded into the changelog is stale", () => { + const { stale, keep } = classifyFragments({ + changelog: CHANGELOG, + fragments: [{ name: "8100-retry.md", rel: "changelog.d/fixes/8100-retry.md", body: "- **fix(sse):** stop the retry loop double-counting attempts ([#8100](https://x/y/pull/8100))" }], + }); + assert.equal(stale.length, 1); + assert.equal(keep.length, 0); + assert.equal(stale[0].matchedBy, "pr-number"); + assert.match(stale[0].reason, /#8100/); +}); + +test("a fragment for THIS cycle, not yet in the changelog, is kept", () => { + // The whole point: the sweep must not eat the fragments the current cycle is accumulating. + const { stale, keep } = classifyFragments({ + changelog: CHANGELOG, + fragments: [{ name: "8966-iflow.md", rel: "changelog.d/maintenance/8966-iflow.md", body: "- **chore(sse):** dropped the leftover iflow entry ([#8966](https://x/y/pull/8966))" }], + }); + assert.equal(stale.length, 0); + assert.equal(keep.length, 1); +}); + +test("identity is the FILENAME's PR number, never a ref cited in the bullet", () => { + // The regression that caught this: the real fragment + // `changelog.d/features/8980-deprecate-gemini-cli-provider.md` cites issue #7034 for + // context, and #7034 shipped in an earlier cycle. Matching on any body ref flagged it stale + // and would have deleted an unreleased bullet along with its credit. + const { stale, keep } = classifyFragments({ + changelog: CHANGELOG + "\n- an older bullet about ([#7034](url))\n", + fragments: [ + { + name: "8980-deprecate-gemini-cli-provider.md", + rel: "changelog.d/features/8980-deprecate-gemini-cli-provider.md", + body: "- **feat(sse):** deprecated the provider. The client identity (issue #7034) is untouched ([#8980](url))", + }, + ], + }); + assert.equal(stale.length, 0, "#7034 is context, not this fragment's identity"); + assert.equal(keep.length, 1); +}); + +test("the filename's PR number being present IS enough to sweep", () => { + const { stale } = classifyFragments({ + changelog: CHANGELOG, + fragments: [ + { name: "8101-migration.md", rel: "changelog.d/fixes/8101-migration.md", body: "- whatever the text says" }, + ], + }); + assert.equal(stale.length, 1); + assert.equal(stale[0].matchedBy, "pr-number"); + assert.match(stale[0].reason, /#8101/); +}); + +test("a ref-less fragment already present is caught by normalized text", () => { + const { stale, keep } = classifyFragments({ + changelog: CHANGELOG, + fragments: [ + { + name: "pin.md", + rel: "changelog.d/maintenance/pin.md", + // Different markdown, same sentence — must still collide. + body: "- chore(ci): pin the workflow action digests, no issue number on this one", + }, + ], + }); + assert.equal(keep.length, 0); + assert.equal(stale.length, 1); + assert.equal(stale[0].matchedBy, "text"); +}); + +test("a ref-less fragment that is NOT present is kept", () => { + const { stale, keep } = classifyFragments({ + changelog: CHANGELOG, + fragments: [{ name: "new.md", rel: "changelog.d/features/new.md", body: "- feat(api): brand new endpoint nobody has shipped yet" }], + }); + assert.equal(stale.length, 0); + assert.equal(keep.length, 1); +}); + +test("a very short ref-less fragment is kept — accidental text collisions are not evidence", () => { + const { stale, keep } = classifyFragments({ + changelog: CHANGELOG, + fragments: [{ name: "tiny.md", rel: "changelog.d/fixes/tiny.md", body: "- typo" }], + }); + assert.equal(stale.length, 0, "too short to identify — keeping is the safe direction"); + assert.equal(keep.length, 1); +}); + +test("an empty changelog sweeps nothing", () => { + const frags = [ + { name: "a.md", rel: "changelog.d/fixes/a.md", body: "- fix: something ([#1](url))" }, + { name: "b.md", rel: "changelog.d/fixes/b.md", body: "- fix: другое" }, + ]; + const { stale, keep } = classifyFragments({ changelog: "", fragments: frags }); + assert.equal(stale.length, 0); + assert.equal(keep.length, 2); +}); + +test("no fragments and no changelog does not throw", () => { + const r = classifyFragments({}); + assert.deepEqual(r.stale, []); + assert.deepEqual(r.keep, []); +}); + +test("normalizeBullet folds markdown, links and refs away", () => { + const a = normalizeBullet("- **fix(sse):** stop the *retry* loop ([#8100](https://x/y/pull/8100))"); + const b = normalizeBullet("fix(sse): stop the retry loop #8100"); + assert.equal(a, b, "the same sentence in two markdown dialects must compare equal"); +}); + +test("refsIn finds every number and nothing else", () => { + assert.deepEqual(refsIn("closes #12, refs #345 and v3.8.49"), [12, 345]); + assert.deepEqual(refsIn(""), []); + assert.deepEqual(refsIn(undefined), []); +}); diff --git a/tests/unit/test-masking-release-scale.test.ts b/tests/unit/test-masking-release-scale.test.ts new file mode 100644 index 0000000000..8c0951fcf0 --- /dev/null +++ b/tests/unit/test-masking-release-scale.test.ts @@ -0,0 +1,65 @@ +/** + * Guard for the test-masking gate's release-scale escape hatch (gap 6). + * + * The gate diffs `base...HEAD` — three dots, so already merge-base relative, which is right + * for a normal PR. It is not the base choice that hurts. Releases SQUASH-merge into `main`, so + * a release PR's merge-base is the PREVIOUS cycle's fork point and the diff legitimately spans + * the entire cycle. In the v3.8.49 run that was ~1277 changed test files, each costing a + * `git show base:file` process plus a full regex pass: the check ran twice without finishing, + * >30 min pegged on a single core, with the release waiting on it. + * + * Measured while writing this, and worth recording because it refutes the obvious diagnosis: + * + * tracked test files ................. 3977 + * absolute tautology scan ............ ~1 s (runs unconditionally, always) + * diff vs release branch ............. 0 changed test files, 0 s + * diff vs main (today) ............... 3 changed test files, 0 s + * + * It cannot be reproduced today at all, because `main` has since received the v3.8.49 squash + * and the merge-base is recent. The pathology only appears DURING a release, in the window + * before `main` receives it — the same squash-merge topology behind gap 4. + * + * So the threshold is what these tests pin. An off-by-one here either blocks a release or + * silently disables the check on a large-but-legitimate PR, and the second failure mode is the + * dangerous one. + */ +import test from "node:test"; +import assert from "node:assert/strict"; + +// @ts-expect-error — plain .mjs gate script, no type declarations by design +import { shouldSkipDiffSubchecks } from "../../scripts/check/check-test-masking.mjs"; + +test("a normal PR is always analyzed", () => { + assert.equal(shouldSkipDiffSubchecks(0, 300), false); + assert.equal(shouldSkipDiffSubchecks(1, 300), false); + assert.equal(shouldSkipDiffSubchecks(42, 300), false); +}); + +test("the boundary is exclusive — exactly at the cap is still analyzed", () => { + assert.equal(shouldSkipDiffSubchecks(300, 300), false, "at the cap: analyze"); + assert.equal(shouldSkipDiffSubchecks(301, 300), true, "one past the cap: skip"); +}); + +test("release scale skips (the measured v3.8.49 case)", () => { + assert.equal(shouldSkipDiffSubchecks(1277, 300), true); +}); + +test("a cap of zero or below disables the skip — always analyze", () => { + // The documented escape hatch for anyone who wants the full pass regardless of size. + assert.equal(shouldSkipDiffSubchecks(999999, 0), false); + assert.equal(shouldSkipDiffSubchecks(999999, -1), false); +}); + +test("a huge explicit cap forces full analysis", () => { + // TEST_MASKING_MAX_CHANGED_TESTS=999999, the override the skip message advertises. + assert.equal(shouldSkipDiffSubchecks(1277, 999999), false); +}); + +test("garbage inputs never skip — an unparseable count must not disable the gate", () => { + // The safe direction: if we cannot tell how big the diff is, do the work. + assert.equal(shouldSkipDiffSubchecks(NaN, 300), false); + assert.equal(shouldSkipDiffSubchecks(-5, 300), false); + assert.equal(shouldSkipDiffSubchecks(500, NaN), false); + assert.equal(shouldSkipDiffSubchecks(500, undefined), false); + assert.equal(shouldSkipDiffSubchecks(undefined, 300), false); +}); diff --git a/tests/unit/ui-value-drift-cosmetic.test.ts b/tests/unit/ui-value-drift-cosmetic.test.ts new file mode 100644 index 0000000000..cf6ac5af53 --- /dev/null +++ b/tests/unit/ui-value-drift-cosmetic.test.ts @@ -0,0 +1,95 @@ +/** + * Guard for the cosmetic-rewrite exemption in the UI value-drift gate (gap 9). + * + * `"Reset Defaults"` → `"Reset defaults"` marked the key stale in 41 locales during the + * v3.8.49 cycle. Every one of those translations was still a correct translation of the same + * sentence, and in locales with no letter case the "fix" is not even expressible. The + * documented escape hatch — a `__MISSING__:` placeholder — is BANNED in `vi` by + * tests/unit/i18n-vi-completeness.test.ts, so `vi` had no legitimate way out of a purely + * cosmetic English edit. + * + * The exemption has to stay narrow, and that is the real risk here: too generous and a genuine + * copy change ships with 41 stale translations and nobody is told. So most of these tests exist + * to pin what is NOT cosmetic. + */ +import test from "node:test"; +import assert from "node:assert/strict"; + +// @ts-expect-error — plain .mjs gate script, no type declarations by design +import { findStaleTranslations, isCosmeticRewrite } from "../../scripts/i18n/check-ui-value-drift.mjs"; + +test("case-only changes are cosmetic — the reported case", () => { + assert.equal(isCosmeticRewrite("Reset Defaults", "Reset defaults"), true); + assert.equal(isCosmeticRewrite("SAVE", "Save"), true); + assert.equal(isCosmeticRewrite("api key", "API Key"), true); +}); + +test("trailing terminal punctuation is cosmetic", () => { + assert.equal(isCosmeticRewrite("Reset defaults", "Reset defaults."), true); + assert.equal(isCosmeticRewrite("Are you sure", "Are you sure?"), true); + assert.equal(isCosmeticRewrite("Done!", "Done"), true); +}); + +test("WHITESPACE is deliberately NOT cosmetic — it is someone else's call", () => { + // tests/unit/i18n-ui-value-drift.test.ts pins "a value that only changes whitespace still + // counts as an edit", with a stated reason: trailing-space churn is rare, and treating it as a + // no-op would let a real reword hide behind an innocuous-looking diff. The problem reported + // here was CASE. Narrowing to the reported scope rather than reversing a documented decision + // for free — asserted so a later "tidy-up" cannot fold whitespace back in by accident. + assert.equal(isCosmeticRewrite("hello", "hello "), false); + assert.equal(isCosmeticRewrite("Reset defaults", "Reset defaults"), false); + assert.equal(isCosmeticRewrite(" Save ", "Save"), false); +}); + +test("a changed WORD is never cosmetic", () => { + assert.equal(isCosmeticRewrite("Reset defaults", "Restore defaults"), false); + assert.equal(isCosmeticRewrite("Delete", "Delete all"), false); + assert.equal(isCosmeticRewrite("Save", "Cancel"), false); +}); + +test("added or removed words are never cosmetic, even with matching case", () => { + assert.equal(isCosmeticRewrite("Delete this connection", "Delete connection"), false); + assert.equal(isCosmeticRewrite("Enabled", "Enabled by default"), false); +}); + +test("a change inside an interpolation is never cosmetic", () => { + // Placeholders are contract, not prose — renaming one breaks every translation. + assert.equal(isCosmeticRewrite("{count} items", "{total} items"), false); + assert.equal(isCosmeticRewrite("{count} items", "{count} entries"), false); +}); + +test("mid-string punctuation is not folded — only trailing", () => { + assert.equal(isCosmeticRewrite("Save, then close", "Save then close"), false); +}); + +test("non-strings are never cosmetic", () => { + assert.equal(isCosmeticRewrite(undefined, "Save"), false); + assert.equal(isCosmeticRewrite("Save", null), false); + assert.equal(isCosmeticRewrite(42, 42), false); +}); + +test("end to end: a cosmetic English edit leaves every locale alone", () => { + const stale = findStaleTranslations({ + baseEn: { ui: { reset: "Reset Defaults" } }, + headEn: { ui: { reset: "Reset defaults" } }, + baseLocales: { vi: { ui: { reset: "Đặt lại mặc định" } }, de: { ui: { reset: "Standardwerte" } } }, + headLocales: { vi: { ui: { reset: "Đặt lại mặc định" } }, de: { ui: { reset: "Standardwerte" } } }, + }); + assert.deepEqual(stale, [], "41 correct translations must not be invalidated by a capital letter"); +}); + +test("end to end: a REAL English rewrite still flags every untranslated locale", () => { + // The gate's whole purpose — this must keep working, or the exemption traded one bug for a + // worse one. + const stale = findStaleTranslations({ + baseEn: { ui: { reset: "Reset defaults" } }, + headEn: { ui: { reset: "Restore factory settings" } }, + baseLocales: { vi: { ui: { reset: "Đặt lại mặc định" } }, de: { ui: { reset: "Standardwerte" } } }, + headLocales: { vi: { ui: { reset: "Đặt lại mặc định" } }, de: { ui: { reset: "Standardwerte" } } }, + }); + assert.equal(stale.length, 2, "both locales still carry the old translation"); + assert.deepEqual( + stale.map((s: { locale: string }) => s.locale).sort(), + ["de", "vi"] + ); +}); diff --git a/tests/unit/ui/CliCodePage.test.tsx b/tests/unit/ui/CliCodePage.test.tsx index 9334d1645c..9a4933e2b3 100644 --- a/tests/unit/ui/CliCodePage.test.tsx +++ b/tests/unit/ui/CliCodePage.test.tsx @@ -20,10 +20,11 @@ vi.mock("next/link", () => ({ ), })); -vi.mock("next-intl", () => ({ - useTranslations: (ns: string) => (key: string) => `${ns}.${key}`, - useLocale: () => "en", -})); +// next-intl: no local mock — falls through to the real-EN-text default mock +// registered in tests/_setup/vitestUiPolyfills.ts (backed by src/i18n/messages/en.json +// via next-intl's own createTranslator). The previous local mock rendered raw +// "namespace.key" strings, which no longer matches most assertions below (they check +// literal English copy such as "Claude Code profiles"). // Mock CLI components so tests don't pull in their heavy dependencies vi.mock("@/shared/components/cli", () => ({ @@ -398,8 +399,8 @@ describe("CliCodePageClient", () => { // The banner should appear (providers loading done, hasActiveProviders = false) const providerLink = container.querySelector('a[href="/dashboard/providers"]'); expect(providerLink).not.toBeNull(); - // Banner text keys - expect(container.textContent).toContain("detail.noActiveProviders"); + // Banner text (cliCommon.detail.noActiveProviders in src/i18n/messages/en.json) + expect(container.textContent).toContain("No active providers"); }); it("6. CliConceptCard rendered at top with currentType='code'", async () => { diff --git a/tests/unit/ui/CliToolCard.test.tsx b/tests/unit/ui/CliToolCard.test.tsx index a3f328c433..7c8a58f098 100644 --- a/tests/unit/ui/CliToolCard.test.tsx +++ b/tests/unit/ui/CliToolCard.test.tsx @@ -20,21 +20,11 @@ vi.mock("next/link", () => ({ ), })); -vi.mock("next-intl", () => ({ - useTranslations: () => { - const messages: Record = { - "card.detected": "Detected", - "card.notDetected": "Not detected", - "card.configure": "Configure →", - "card.howToInstall": "How to install →", - "card.baseUrlPartial": "Partial Base URL", - "card.alsoAcp": "also ACP", - "card.connectProviderHint": "Connect a provider in Providers", - }; - return (key: string) => messages[key] ?? key; - }, - useLocale: () => "en", -})); +// next-intl: no local mock — falls through to the real-EN-text default mock in +// tests/_setup/vitestUiPolyfills.ts. The previous local mock hand-copied a partial +// message subset under a single flat table shared across both `useTranslations("cliCommon")` +// and `useTranslations("cliTools")` calls in CliToolCard.tsx, which drifted out of sync +// (missing "versionNotFound"/"manualConfig") and didn't separate namespaces. // Stub CliStatusBadge so it doesn't need next-intl internals vi.mock("@/app/(dashboard)/dashboard/cli-code/components/CliStatusBadge", () => ({ diff --git a/tests/unit/ui/allocation-table.test.tsx b/tests/unit/ui/allocation-table.test.tsx index c03657eb6e..dc92e36f1d 100644 --- a/tests/unit/ui/allocation-table.test.tsx +++ b/tests/unit/ui/allocation-table.test.tsx @@ -4,9 +4,11 @@ import { act } from "react"; import { createRoot } from "react-dom/client"; import { afterEach, describe, expect, it, vi } from "vitest"; -vi.mock("next-intl", () => ({ - useTranslations: () => (key: string) => key, -})); +// next-intl: no local mock — falls through to the real-EN-text default mock in +// tests/_setup/vitestUiPolyfills.ts. The previous `(key) => key` mock rendered +// "policyHard"/"policySoft" literally, which failed the "renders policy badges" test's +// lowercase "hard"/"soft" check below (case mismatch: "policyHard" vs "hard"). The real +// en.json copy for both keys is the plain lowercase word. const { default: AllocationTable } = await import( "../../../src/app/(dashboard)/dashboard/costs/quota-share/components/AllocationTable" @@ -43,7 +45,8 @@ describe("AllocationTable", { timeout: 10000 }, () => { it("renders empty state when no allocations", async () => { await render({ allocations: [], usage: null, keyLabels: {} }); - expect(document.body.innerHTML).toContain("noAllocations"); + // quotaShare.noAllocations in src/i18n/messages/en.json + expect(document.body.innerHTML).toContain("No keys allocated yet"); }); it("renders key labels", async () => { @@ -83,7 +86,7 @@ describe("AllocationTable", { timeout: 10000 }, () => { await render({ allocations: ALLOCATIONS, usage: usage as never, keyLabels: KEY_LABELS }); expect(document.body.innerHTML).toContain("300"); expect(document.body.innerHTML).toContain("100"); - // borrowing indicator for key_2 - expect(document.body.innerHTML).toContain("borrowingIndicator"); + // borrowing indicator for key_2 (quotaShare.borrowingIndicator in en.json) + expect(document.body.innerHTML).toContain("borrowing"); }); }); diff --git a/tests/unit/ui/burn-rate-chart.test.tsx b/tests/unit/ui/burn-rate-chart.test.tsx index 2148fca4be..97d26e06a7 100644 --- a/tests/unit/ui/burn-rate-chart.test.tsx +++ b/tests/unit/ui/burn-rate-chart.test.tsx @@ -2,15 +2,45 @@ import React from "react"; import { act } from "react"; import { createRoot } from "react-dom/client"; -import { afterEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; -vi.mock("next-intl", () => ({ - useTranslations: () => (key: string) => key, -})); +// next-intl: no local mock — falls through to the real-EN-text default mock in +// tests/_setup/vitestUiPolyfills.ts (quotaShare.burnRateTitle = "Burn rate", +// .burnRateExhaustsIn = "Exhausts in" in en.json). -// Stub next/dynamic — returns null component (recharts not needed in tests) +// recharts' ResponsiveContainer (pulled in by BurnRateChartInner) needs ResizeObserver, +// which jsdom does not implement. +beforeAll(() => { + globalThis.ResizeObserver = class { + observe() {} + unobserve() {} + disconnect() {} + } as unknown as typeof ResizeObserver; +}); + +// Eagerly resolve the dynamic import so BurnRateChartInner actually renders instead of +// staying null forever (mirrors the pattern in playground-studio.test.tsx). Tracked via +// state (not a bare closure variable) so the resolution itself triggers the re-render +// that picks it up, instead of relying on some later, unrelated state update to do so. vi.mock("next/dynamic", () => ({ - default: () => () => null, + default: (fn: () => Promise<{ default: React.ComponentType> }>) => { + return function DynamicWrapper(props: Record) { + const [Component, setComponent] = React.useState + > | null>(null); + React.useEffect(() => { + let mounted = true; + fn().then((m) => { + if (mounted) setComponent(() => m.default); + }); + return () => { + mounted = false; + }; + }, []); + if (!Component) return null; + return React.createElement(Component, props); + }; + }, })); const { default: BurnRateChart } = await import( @@ -29,6 +59,15 @@ async function render(props: Parameters[0]) { root = createRoot(container!); root.render(); }); + // Let the mocked next/dynamic's `fn().then(setComponent)` resolve and commit the + // re-render that swaps in BurnRateChartInner. The FIRST import of this module (which + // pulls in recharts) needs a real transform, not just a microtask — polling a few + // real ticks is more reliable here than a fixed Promise.resolve() count. + for (let i = 0; i < 20 && container!.innerHTML === ""; i++) { + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, 10)); + }); + } } describe("BurnRateChart", { timeout: 10000 }, () => { @@ -41,7 +80,8 @@ describe("BurnRateChart", { timeout: 10000 }, () => { it("renders no-data state when usage is null", async () => { await render({ usage: null }); - expect(document.body.innerHTML).toContain("burnRateTitle"); + // quotaShare.burnRateTitle in src/i18n/messages/en.json + expect(document.body.innerHTML).toContain("Burn rate"); expect(document.body.innerHTML).toContain("no data"); }); @@ -64,7 +104,7 @@ describe("BurnRateChart", { timeout: 10000 }, () => { await render({ usage: usage as never }); // Should not show no-data message expect(document.body.innerHTML).not.toContain("no data yet"); - // Should show exhaustion label - expect(document.body.innerHTML).toContain("burnRateExhaustsIn"); + // Should show exhaustion label (quotaShare.burnRateExhaustsIn in en.json) + expect(document.body.innerHTML).toContain("Exhausts in"); }); }); diff --git a/tests/unit/ui/compression-combos-routing-mode-6760.test.tsx b/tests/unit/ui/compression-combos-routing-mode-6760.test.tsx index f21b64bed2..58b493f3ba 100644 --- a/tests/unit/ui/compression-combos-routing-mode-6760.test.tsx +++ b/tests/unit/ui/compression-combos-routing-mode-6760.test.tsx @@ -112,10 +112,11 @@ describe("CompressionCombosPageClient — routing-combo compression mode selecto expect(container.textContent).toContain("Routing Bravo"); const selects = Array.from(container.querySelectorAll("select")) as HTMLSelectElement[]; // one per routing combo (2) — the shared ComboCompressionModeSelect renders exactly - // the 6-option Default/Off/Lite/Standard/Aggressive/Ultra set. + // the 7-option Default/Off/Lite/Standard/Aggressive/Ultra/Responses-tool-output set + // (#8010 added "codex-responses", unrelated to this file's original #6760 scope). const modeSelects = selects.filter((s) => { const values = Array.from(s.options).map((o) => o.value); - return values.join(",") === ",off,lite,standard,aggressive,ultra"; + return values.join(",") === ",off,lite,standard,aggressive,ultra,codex-responses"; }); expect(modeSelects).toHaveLength(2); expect(modeSelects[0].value).toBe("lite"); @@ -128,7 +129,7 @@ describe("CompressionCombosPageClient — routing-combo compression mode selecto const selects = Array.from(container.querySelectorAll("select")) as HTMLSelectElement[]; const modeSelects = selects.filter((s) => { const values = Array.from(s.options).map((o) => o.value); - return values.join(",") === ",off,lite,standard,aggressive,ultra"; + return values.join(",") === ",off,lite,standard,aggressive,ultra,codex-responses"; }); await act(async () => { modeSelects[0].value = "ultra"; diff --git a/tests/unit/ui/engineConfigPage.test.tsx b/tests/unit/ui/engineConfigPage.test.tsx index b3769b8875..701e746ba6 100644 --- a/tests/unit/ui/engineConfigPage.test.tsx +++ b/tests/unit/ui/engineConfigPage.test.tsx @@ -201,8 +201,10 @@ describe("EngineConfigPage", () => { await Promise.resolve(); }); - // EngineConfigForm should render the "Min rows" field label from the schema - expect(container.textContent).toContain("Min rows"); + // EngineConfigForm prefers the i18n label (compressionEngineConfig.fields.minRows.label + // in en.json) over the mocked schema's own "Min rows" when a translation exists — see + // EngineConfigPage.tsx's `t.has(labelKey) ? t(labelKey) : field.label`. + expect(container.textContent).toContain("Minimum rows to compact"); }); it("keeps detailed config but renders no engine enable checkbox", async () => { @@ -222,7 +224,8 @@ describe("EngineConfigPage", () => { // The on/off enable toggle (a checkbox with data-toggle="enable") is gone; the // detailed config form (the schema fields minus `enabled`) still renders. expect(container.querySelector("input[type='checkbox'][data-toggle='enable']")).toBeNull(); - expect(container.textContent).toContain("Min rows"); + // See the i18n-label-override note above (compressionEngineConfig.fields.minRows.label). + expect(container.textContent).toContain("Minimum rows to compact"); expect(container.textContent).toContain("Configuration"); }); diff --git a/tests/unit/ui/playground-build-tab.test.tsx b/tests/unit/ui/playground-build-tab.test.tsx index 2699aa4c53..ea65faf4f8 100644 --- a/tests/unit/ui/playground-build-tab.test.tsx +++ b/tests/unit/ui/playground-build-tab.test.tsx @@ -4,9 +4,11 @@ import { act } from "react"; import { createRoot } from "react-dom/client"; import { afterEach, describe, expect, it, vi } from "vitest"; -vi.mock("next-intl", () => ({ - useTranslations: () => (key: string) => key, -})); +// next-intl: no local mock — falls through to the real-EN-text default mock in +// tests/_setup/vitestUiPolyfills.ts. Most assertions below already check real English +// copy ("Add tool", "JSON mode", "JSON schema for parameters"); the section-header +// checks are updated alongside this to match ("toolsLabel" -> "Tools", +// "structuredOutputLabel" -> "Structured Output"). vi.mock("remark-gfm", () => ({ default: () => {} })); vi.mock("react-markdown", () => ({ @@ -71,14 +73,16 @@ function renderBuildTab(config = BASE_CONFIG): HTMLDivElement { // step 2 — configure tools and/or the JSON schema, depending on the mode // step 3 — run + toolbar badges + prompt textarea // -// next-intl is mocked as a key pass-through above, so every translated label -// renders as its raw i18n key (e.g. "nextButton", "modeToolsTitle"). +// next-intl renders real production copy (see tests/_setup/vitestUiPolyfills.ts), so +// these helpers locate buttons by their actual en.json text +// (playground.build.nextButton = "Next", .modeJsonTitle = "JSON", etc.) rather than by +// raw i18n key. type BuildMode = "tools" | "json" | "both"; function clickNext(el: HTMLDivElement): void { const nextBtn = Array.from(el.querySelectorAll("button")).find((b) => - b.textContent?.includes("nextButton"), + b.textContent?.includes("Next"), ) as HTMLButtonElement; act(() => { nextBtn.click(); @@ -89,9 +93,9 @@ function selectMode(el: HTMLDivElement, mode: BuildMode): void { // Step 1's default mode is already "tools" — only click a mode card when a // different mode is required. if (mode === "tools") return; - const key = mode === "json" ? "modeJsonTitle" : "modeBothTitle"; + const label = mode === "json" ? "JSON" : "Tools + JSON"; const card = Array.from(el.querySelectorAll("button")).find((b) => - b.textContent?.includes(key), + b.textContent?.includes(label), ) as HTMLButtonElement; act(() => { card.click(); @@ -124,7 +128,7 @@ describe("BuildTab", () => { const el = renderBuildTab(); goToStep3(el); const runBtn = Array.from(el.querySelectorAll("button")).find((b) => - b.textContent?.includes("runButton"), + b.textContent?.includes("Run"), ); expect(runBtn).not.toBeUndefined(); }); @@ -132,14 +136,14 @@ describe("BuildTab", () => { it("renders Function calling section", () => { const el = renderBuildTab(); goToStep2(el, "tools"); - expect(el.textContent).toContain("toolsLabel"); + expect(el.textContent).toContain("Tools"); expect(el.textContent).toContain("Add tool"); }); it("renders Structured output section", () => { const el = renderBuildTab(); goToStep2(el, "json"); - expect(el.textContent).toContain("structuredOutputLabel"); + expect(el.textContent).toContain("Structured Output"); expect(el.textContent).toContain("JSON mode"); }); @@ -255,10 +259,10 @@ describe("BuildTab", () => { const promptTextarea = el.querySelector("textarea") as HTMLTextAreaElement; act(() => setInputValue(promptTextarea, "Run this tool")); - // Click Run (label is "runButton" via mocked t()) + // Click Run (playground.build.runButton = "Run" in en.json) const runBtns = el.querySelectorAll("button"); const runBtn = Array.from(runBtns).find( - (b) => b.textContent?.includes("runButton"), + (b) => b.textContent?.includes("Run"), ) as HTMLButtonElement; await act(async () => { runBtn.click(); }); await act(async () => { diff --git a/tests/unit/ui/playground-chat-tab.test.tsx b/tests/unit/ui/playground-chat-tab.test.tsx index d2071e3060..64f2930737 100644 --- a/tests/unit/ui/playground-chat-tab.test.tsx +++ b/tests/unit/ui/playground-chat-tab.test.tsx @@ -6,9 +6,10 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; // ── Mocks ───────────────────────────────────────────────────────────────────── -vi.mock("next-intl", () => ({ - useTranslations: () => (key: string) => key, -})); +// next-intl: no local mock — falls through to the real-EN-text default mock in +// tests/_setup/vitestUiPolyfills.ts. Every check below (button text "Send"/ +// "Regenerate", "Start a conversation" empty state) already expects real production +// copy, which the previous `(key) => key` mock never rendered. vi.mock("@/lib/playground/types", () => ({ getModelPricing: () => null, diff --git a/tests/unit/ui/playground-config-pane.test.tsx b/tests/unit/ui/playground-config-pane.test.tsx index f066fdd3ee..4d0cc6825d 100644 --- a/tests/unit/ui/playground-config-pane.test.tsx +++ b/tests/unit/ui/playground-config-pane.test.tsx @@ -4,9 +4,10 @@ import { act } from "react"; import { createRoot } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -vi.mock("next-intl", () => ({ - useTranslations: () => (key: string) => key, -})); +// next-intl: no local mock — falls through to the real-EN-text default mock in +// tests/_setup/vitestUiPolyfills.ts. The collapse/expand buttons are found by their +// real `aria-label` text (playground.collapseConfig/expandConfig in en.json), which the +// previous `(key) => key` mock never produced (it rendered the raw key as the label). vi.mock("@/lib/playground/codeExport", () => ({ endpointToPath: (ep: string) => `/v1/${ep}`, diff --git a/tests/unit/ui/playground-studio.test.tsx b/tests/unit/ui/playground-studio.test.tsx index 91db18dbf8..a861179816 100644 --- a/tests/unit/ui/playground-studio.test.tsx +++ b/tests/unit/ui/playground-studio.test.tsx @@ -229,7 +229,9 @@ describe("PlaygroundStudio", () => { const el = renderStudio(); // Verify config pane is rendered - const configPaneLabel = el.querySelector("[aria-label='Config pane']"); + // This file's next-intl mock renders raw translation keys (see the `vi.mock` + // above), matching the rest of this file's assertions ("tabChat", "tabApi", ...). + const configPaneLabel = el.querySelector("[aria-label='configPane']"); expect(configPaneLabel).toBeTruthy(); // Switch to API tab @@ -242,7 +244,7 @@ describe("PlaygroundStudio", () => { }); // Config pane should still be visible - const configPaneAfterSwitch = el.querySelector("[aria-label='Config pane']"); + const configPaneAfterSwitch = el.querySelector("[aria-label='configPane']"); expect(configPaneAfterSwitch).toBeTruthy(); }); diff --git a/tests/unit/ui/runtime-page-client.test.tsx b/tests/unit/ui/runtime-page-client.test.tsx index e3c068a44b..9c159ec7c2 100644 --- a/tests/unit/ui/runtime-page-client.test.tsx +++ b/tests/unit/ui/runtime-page-client.test.tsx @@ -65,79 +65,88 @@ vi.mock("@/shared/components/ProviderIcon", () => ({ ), })); -vi.mock("next-intl", () => ({ - useTranslations: () => { - const messages: Record = { - title: "Runtime", - description: "Realtime observability", - pause: "Pause", - resume: "Resume", - refreshNow: "Refresh now", - kpiSessions: "Sessions", - kpiCircuits: "Circuits", - kpiCooldowns: "Cooldowns", - kpiLockouts: "Lockouts", - hintStickyBound: "{count} sticky-bound", - hintRecovering: "{count} recovering", - hintAllHealthy: "all healthy", - hintOpen: "open", - hintConnsCooling: "connections cooling", - hintModelsBlocked: "models blocked", - resilienceTitle: "3-Layer Resilience", - resilienceSubtitle: "Mirrors the documented resilience model", - providersHealthy: "{percent}% providers healthy", - layer: "Layer {n}", - layer1Title: "Provider Circuit Breakers", - layer1Desc: "Stop traffic to providers failing at the upstream level", - layer2Title: "Connection Cooldowns", - layer2Desc: "Skip one bad account/key", - layer3Title: "Model Lockouts", - layer3Desc: "Per-model rate-limit locks", - badgeAffectedOf: "{affected} of {total} affected", - badgeCooling: "{count} cooling", - badgeLocked: "{count} locked", - emptyCircuits: "No circuit breakers active yet", - emptyCooldowns: "No connection cooldowns active", - emptyLockouts: "No model lockouts", - feedTitle: "Live Feed", - feedSubtitle: "Last {count} events", - feedFilterAll: "All", - feedFilterCircuits: "Circuits", - feedFilterCooldowns: "Cooldowns", - feedFilterLockouts: "Lockouts", - feedFilterSessions: "Sessions", - feedFilterQuotas: "Quotas", - feedClear: "Clear", - feedEmptyWaiting: "Waiting for events...", - feedEmptyFiltered: "No events match this filter", - sessionsTitle: "Active Sessions", - sessionsSubtitle: "Sticky-bound request fingerprints", - sessionsActive: "{count} active", - sessionsEmptyTitle: "No active sessions", - sessionsEmptyHint: "Sessions appear as requests flow through the proxy", - tblSession: "Session", - tblAge: "Age", - tblIdle: "Idle", - tblReqs: "Reqs", - tblBoundTo: "Bound to", - topApiKeys: "Top API keys", - quotaMonitorsTitle: "Quota Monitors", - quotaMonitorsSubtitle: "Live quota state per account window", - openQuota: "Open Quota", - allQuotasHealthy: "All quotas healthy", - moreSuffix: "+{count} more", - }; +// Real next-intl's `useTranslations()` returns a REFERENTIALLY STABLE function across +// re-renders. RuntimePageClient depends on that (`t` sits in a `useCallback`/`useEffect` +// dependency array); building `messages`/the returned function fresh inside the arrow +// below — as this mock used to — hands back a NEW closure on every call, so the effect +// sees a "new" `t` every render and never stops re-firing (a hidden infinite render +// loop that manifests as the whole test file hanging past any timeout instead of +// failing fast). Build `messages` and `t` once, outside `useTranslations`, so every +// call returns the same reference — mirrors the fix applied to the global mock in +// tests/_setup/vitestUiPolyfills.ts. +const runtimePageClientMessages: Record = { + title: "Runtime", + description: "Realtime observability", + pause: "Pause", + resume: "Resume", + refreshNow: "Refresh now", + kpiSessions: "Sessions", + kpiCircuits: "Circuits", + kpiCooldowns: "Cooldowns", + kpiLockouts: "Lockouts", + hintStickyBound: "{count} sticky-bound", + hintRecovering: "{count} recovering", + hintAllHealthy: "all healthy", + hintOpen: "open", + hintConnsCooling: "connections cooling", + hintModelsBlocked: "models blocked", + resilienceTitle: "3-Layer Resilience", + resilienceSubtitle: "Mirrors the documented resilience model", + providersHealthy: "{percent}% providers healthy", + layer: "Layer {n}", + layer1Title: "Provider Circuit Breakers", + layer1Desc: "Stop traffic to providers failing at the upstream level", + layer2Title: "Connection Cooldowns", + layer2Desc: "Skip one bad account/key", + layer3Title: "Model Lockouts", + layer3Desc: "Per-model rate-limit locks", + badgeAffectedOf: "{affected} of {total} affected", + badgeCooling: "{count} cooling", + badgeLocked: "{count} locked", + emptyCircuits: "No circuit breakers active yet", + emptyCooldowns: "No connection cooldowns active", + emptyLockouts: "No model lockouts", + feedTitle: "Live Feed", + feedSubtitle: "Last {count} events", + feedFilterAll: "All", + feedFilterCircuits: "Circuits", + feedFilterCooldowns: "Cooldowns", + feedFilterLockouts: "Lockouts", + feedFilterSessions: "Sessions", + feedFilterQuotas: "Quotas", + feedClear: "Clear", + feedEmptyWaiting: "Waiting for events...", + feedEmptyFiltered: "No events match this filter", + sessionsTitle: "Active Sessions", + sessionsSubtitle: "Sticky-bound request fingerprints", + sessionsActive: "{count} active", + sessionsEmptyTitle: "No active sessions", + sessionsEmptyHint: "Sessions appear as requests flow through the proxy", + tblSession: "Session", + tblAge: "Age", + tblIdle: "Idle", + tblReqs: "Reqs", + tblBoundTo: "Bound to", + topApiKeys: "Top API keys", + quotaMonitorsTitle: "Quota Monitors", + quotaMonitorsSubtitle: "Live quota state per account window", + openQuota: "Open Quota", + allQuotasHealthy: "All quotas healthy", + moreSuffix: "+{count} more", +}; - return (key: string, values?: Record) => { - let message = messages[key] ?? key; - if (values) { - for (const [name, value] of Object.entries(values)) { - message = message.replace(`{${name}}`, String(value)); - } - } - return message; - }; - }, +function runtimePageClientTranslate(key: string, values?: Record): string { + let message = runtimePageClientMessages[key] ?? key; + if (values) { + for (const [name, value] of Object.entries(values)) { + message = message.replace(`{${name}}`, String(value)); + } + } + return message; +} + +vi.mock("next-intl", () => ({ + useTranslations: () => runtimePageClientTranslate, })); describe("RuntimePageClient", () => { diff --git a/tests/unit/ui/search-tools-compare-tab.test.tsx b/tests/unit/ui/search-tools-compare-tab.test.tsx index 3cb92d0ffc..8d2d15a742 100644 --- a/tests/unit/ui/search-tools-compare-tab.test.tsx +++ b/tests/unit/ui/search-tools-compare-tab.test.tsx @@ -7,9 +7,11 @@ import type { SearchProviderCatalogItem } from "../../../src/shared/schemas/sear // ── Mocks ───────────────────────────────────────────────────────────────────── -vi.mock("next-intl", () => ({ - useTranslations: () => (key: string) => key, -})); +// next-intl: no local mock — falls through to the real-EN-text default mock in +// tests/_setup/vitestUiPolyfills.ts. CompareTab renders `{count}`/`{overlap}` +// interpolated copy (search.maxCompareProviders, search.overlapSummary) that the +// previous `(key) => key` mock rendered as the raw key, never matching this file's +// literal-text assertions. vi.mock("next/link", () => ({ default: ({ children, href, ...props }: { children: React.ReactNode; href: string }) => diff --git a/tests/unit/ui/search-tools-scrape-result.test.tsx b/tests/unit/ui/search-tools-scrape-result.test.tsx index 120cbbb9fa..e38f550c2b 100644 --- a/tests/unit/ui/search-tools-scrape-result.test.tsx +++ b/tests/unit/ui/search-tools-scrape-result.test.tsx @@ -6,9 +6,11 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; // ── Mocks ───────────────────────────────────────────────────────────────────── -vi.mock("next-intl", () => ({ - useTranslations: () => (key: string) => key, -})); +// next-intl: no local mock — falls through to the real-EN-text default mock in +// tests/_setup/vitestUiPolyfills.ts. ScrapeResult's `aria-label={t("closeRawModal")}` +// and the "256 KB" truncation copy need the real production strings — the previous +// `(key) => key` mock rendered raw keys instead, so `[aria-label='Close raw content +// modal']` never matched and the truncation-warning text check failed. // Lazy import of MarkdownMessage via ScrapeResult's dynamic import — mock it vi.mock( diff --git a/tests/unit/ui/system-storage-manual-vacuum.test.tsx b/tests/unit/ui/system-storage-manual-vacuum.test.tsx index 54509e8fd2..e1bcd47e3e 100644 --- a/tests/unit/ui/system-storage-manual-vacuum.test.tsx +++ b/tests/unit/ui/system-storage-manual-vacuum.test.tsx @@ -8,10 +8,10 @@ import { act } from "react"; import { createRoot, type Root } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -vi.mock("next-intl", () => ({ - useTranslations: () => (key: string) => key, - useLocale: () => "en", -})); +// next-intl: no local mock — falls through to the real-EN-text default mock in +// tests/_setup/vitestUiPolyfills.ts. The button text is found by literal +// `textContent.includes("Manual VACUUM")` below, which the previous `(key) => key` +// mock never satisfied (it rendered the raw "manualVacuum" key). import SystemStorageTab from "@/app/(dashboard)/dashboard/settings/components/SystemStorageTab"; diff --git a/tests/unit/vps-runner-variable-scope.test.ts b/tests/unit/vps-runner-variable-scope.test.ts new file mode 100644 index 0000000000..9d5fd60c89 --- /dev/null +++ b/tests/unit/vps-runner-variable-scope.test.ts @@ -0,0 +1,82 @@ +/** + * Guard for what `USE_VPS_RUNNER` is allowed to govern (gap 19). + * + * One variable used to switch the build AND the test jobs, which want OPPOSITE machines. The + * build needs the .113's RAM — the production `next build` wants 18–20 GB and a hosted runner + * has 16, which killed the same step nine times in the v3.8.49 cycle. The test jobs need the + * hosted runner's link: + * + * actions/setup-node on .113, 4 concurrent runners ..... 20m06s + * actions/setup-node hosted ............................ 16s + * the tests themselves .................. 2m54 vs 2m31 — a tie + * + * So there was no setting that served both, and flipping the variable for a release traded a + * working build for twenty-minute test jobs. + * + * The fix is not a second variable. Self-hosted is strictly worse for anything whose cost is + * dominated by `setup-node` + `npm ci`, so those jobs are pinned to hosted and the variable now + * means exactly one thing: "this job needs the .113's memory". + * + * `fast-gates` was the last holdout and the evidence for pinning it is unusually clean: across + * 160 quality.yml runs it NEVER landed on a self-hosted runner — every non-skipped sample is + * `GitHub Actions NNNN`. That was dead configuration, not a working escape hatch, and the + * classifier is not at fault: ci.yml's Build ran on omniroute-113-7 and -6 in the same window. + */ +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const workflowDir = path.join(repoRoot, ".github/workflows"); + +/** Map every `runs-on:` line mentioning USE_VPS_RUNNER back to the job that owns it. */ +function jobsSwitchedByVpsVar(): Array<{ file: string; job: string }> { + const out: Array<{ file: string; job: string }> = []; + for (const name of fs.readdirSync(workflowDir)) { + if (!name.endsWith(".yml") && !name.endsWith(".yaml")) continue; + const lines = fs.readFileSync(path.join(workflowDir, name), "utf-8").split("\n"); + let job = ""; + for (const line of lines) { + const m = /^ {2}([A-Za-z0-9_-]+):\s*$/.exec(line); + if (m) job = m[1]; + if (line.includes("USE_VPS_RUNNER") && line.includes("runs-on")) { + out.push({ file: name, job }); + } + } + } + return out; +} + +/** Jobs whose cost is dominated by setup-node + npm ci, never by memory. */ +const TEST_LIKE = /(^|-)(test|tests|vitest|unit|gates)($|-)/i; + +test("USE_VPS_RUNNER never governs a test-like job", () => { + const offenders = jobsSwitchedByVpsVar().filter((j) => TEST_LIKE.test(j.job)); + assert.deepEqual( + offenders.map((j) => `${j.file}:${j.job}`), + [], + "self-hosted is strictly worse for these — setup-node measured 20m06s there vs 16s hosted, " + + "while the tests themselves tie. Pin the job to ubuntu-latest instead of switching it." + ); +}); + +test("it still governs the build-like jobs — the ones that actually need the RAM", () => { + const jobs = jobsSwitchedByVpsVar().map((j) => j.job); + assert.ok( + jobs.includes("build"), + "the build is the whole reason the variable exists: 18-20 GB working set vs a 16 GB hosted runner" + ); + assert.ok(jobs.includes("publish"), "npm-publish falls back to a full build when the artifact is missing"); +}); + +test("fast-gates specifically stays hosted", () => { + // The holdout. 160 runs, zero self-hosted samples — dead configuration, and it would have + // inherited the setup-node penalty the day it fired. + const wf = fs.readFileSync(path.join(workflowDir, "quality.yml"), "utf-8"); + const block = wf.split(/^ {2}fast-gates:\s*$/m)[1] ?? ""; + const runsOn = /^ {4}runs-on:\s*(.+)$/m.exec(block); + assert.ok(runsOn, "fast-gates must declare runs-on"); + assert.match(runsOn[1].trim(), /^ubuntu-latest$/, "fast-gates must be pinned, not switched"); +}); diff --git a/tests/unit/workflows-no-foreign-fork-publishers.test.ts b/tests/unit/workflows-no-foreign-fork-publishers.test.ts new file mode 100644 index 0000000000..6b3835c279 --- /dev/null +++ b/tests/unit/workflows-no-foreign-fork-publishers.test.ts @@ -0,0 +1,93 @@ +/** + * Policy guard: no workflow in this repository may publish to — or be gated on — a + * DIFFERENT repository's namespace. + * + * Twice now a contributor's own fork CI has ridden into the canonical repo as an + * unrelated extra file in an otherwise on-topic PR: + * + * .github/workflows/build-fork.yml added by #1528 (scope: SSE translator) + * env: IMAGE_NAME: ghcr.io/kang-heewon/omniroute + * if: github.repository == 'kang-heewon/OmniRoute' + * → the guard sits on the JOB, not the workflow, so GitHub instantiated a run on + * every push to main and every v* tag and skipped the job: 100+ runs, zero + * runner cost, and a permanently noisy check board on every release. + * + * .github/workflows/build-rinseaid-image.yml added by #8729 (scope: SSE reasoning) + * tags: ghcr.io/rinseaid/omniroute:... + * → no repository guard at all; it simply never fires because its trigger branch + * (`build-k3-reasoning-image`) does not exist here. 0 runs. + * + * Neither can succeed: this repo's GITHUB_TOKEN cannot write to another owner's GHCR + * namespace. So the cost is not a breach, it is dead configuration that review keeps + * waving through because the PR it arrives in is about something else entirely. + * + * This test is the cheap check that review is not: it reads the workflow directory and + * fails on any foreign owner, so the next accidental inclusion is caught by CI instead + * of surviving until someone wonders why a release board shows a skipped fork job. + */ +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const workflowDir = path.join(repoRoot, ".github/workflows"); + +/** The only owner whose namespaces this repository may publish to or gate on. */ +const OWNER = "diegosouzapw"; + +function workflowFiles(): string[] { + return fs + .readdirSync(workflowDir) + .filter((f) => f.endsWith(".yml") || f.endsWith(".yaml")) + .map((f) => path.join(workflowDir, f)); +} + +test("no workflow publishes to another owner's container registry", () => { + const offenders: string[] = []; + + for (const file of workflowFiles()) { + const text = fs.readFileSync(file, "utf-8"); + // ghcr.io//... and index.docker.io//... — the owner is the segment + // right after the registry host. + for (const m of text.matchAll(/\b(?:ghcr\.io|(?:index\.)?docker\.io)\/([A-Za-z0-9_.-]+)/g)) { + const owner = m[1]; + if (owner.toLowerCase() !== OWNER) { + offenders.push(`${path.basename(file)} → ${m[0]}`); + } + } + } + + assert.deepEqual( + offenders, + [], + `workflow(s) target a registry namespace that is not ${OWNER}'s:\n ${offenders.join("\n ")}\n` + + `A fork's publish workflow does not belong in the canonical repository — it cannot ` + + `authenticate anyway, and it pollutes every release check board.` + ); +}); + +test("no workflow job is gated on a different repository", () => { + const offenders: string[] = []; + + for (const file of workflowFiles()) { + const text = fs.readFileSync(file, "utf-8"); + // `if: github.repository == 'owner/name'` — a guard naming someone else's repo means + // the workflow was written for a fork. + for (const m of text.matchAll(/github\.repository\s*[=!]=\s*['"]([^'"]+)['"]/g)) { + const [owner] = m[1].split("/"); + if (owner.toLowerCase() !== OWNER) { + offenders.push(`${path.basename(file)} → ${m[0]}`); + } + } + } + + assert.deepEqual( + offenders, + [], + `workflow(s) gate on a foreign repository:\n ${offenders.join("\n ")}\n` + + `Note the failure mode: a job-level guard still instantiates a run on every ` + + `matching trigger, so the workflow shows up as a skipped check forever.` + ); +});