Release v3.8.50 - #8875
Draft
diegosouzapw wants to merge 2297 commits into
Draft
Conversation
|
Hey, please if possible do a release, we are died behind v3.8.48 still |
6 tasks
Owner
Author
|
Thanks for sending this PR. Please resolve mandatory items and retest. Re-open after cleanup if scope/mergeability blocking is fixed. |
Owner
Author
|
Thanks for sending this PR. Please resolve mandatory items and retest. Re-open after cleanup if scope/mergeability blocking is fixed. |
Owner
Author
|
test step5 |
Owner
Author
|
Thanks for sending this PR. Please resolve mandatory items and retest. Re-open after cleanup if scope/mergeability blocking is fixed. |
1 similar comment
Owner
Author
|
Thanks for sending this PR. Please resolve mandatory items and retest. Re-open after cleanup if scope/mergeability blocking is fixed. |
This was referenced Aug 11, 2026
…oss-cumulative-integration
… language matrix (#10425) i-have-adhd shipped in #10271 with en + pt-BR only; it now covers vi/ja/id as well, matching ponytail. Every level keeps the SHARED_BOUNDARIES clause. Adds a per-MATRIX guard (output-styles-i18n-matrix.test.ts). Every existing test is per-style, which is how less-code stayed English-only since the 9router port without anyone noticing. The guard fails on: a new style without pt-BR, a style losing a translation it had, a translation missing an intensity level, a translation that dropped the boundaries clause, and a stale KNOWN_ENGLISH_ONLY entry. Proven by mutation, not just by passing: dropping less-code from the allowlist and renaming the vi key both turned it red with the expected messages. less-code stays English-only as declared debt (KNOWN_ENGLISH_ONLY + comment); the remaining coverage work is tracked in #10426.
…unded (#10423) * fix(db): prune pre-migration backups so db_backups stops growing unbounded createPreMigrationBackup() wrote a VACUUM INTO snapshot on every migration run and never pruned. On a long-lived instance db_backups/ reached 48.999 files / 204 GB against a 5,3 MB live database; a second devbox showed the same shape (5.711 files / 24 GB). The retention policy already existed in cleanupDbBackups() but nothing on the migration path reached it — its only callers are backup.ts and the /api/db-backups route, neither of which runs during a migration. migrationRunner.ts cannot import backup.ts: core.ts imports migrationRunner.ts and backup.ts imports core.ts, so that edge would close a cycle. The policy therefore moves to a new core-free module, backupRetention.ts, which both call sites share — cleanupDbBackups() now delegates to it rather than duplicating it. At the migration call site the operator's maxFiles/retentionDays are read through the adapter already open for the run; going through getDbInstance() would re-enter database initialization. Pruning never throws, so housekeeping cannot fail a migration. Closes #10421 * chore(db): declare backupRetention as an intentionally-internal db module check:db-rules requires every src/lib/db/ module to be either re-exported by localDb.ts or listed in INTENTIONALLY_INTERNAL. backupRetention.ts is a shared primitive consumed only by db/backup.ts and db/migrationRunner.ts — the same category as the migrationRunner entry — so it belongs in the allowlist rather than in the public re-export surface. * test(db): include backupRetention in the audited INTENTIONALLY_INTERNAL list check-db-rules-classification.test.ts freezes the exact membership of INTENTIONALLY_INTERNAL, so adding the 40th entry has to be reflected there too — the gate script and this test pin the same contract from opposite sides. --------- Co-authored-by: Xiangzhe <bakryun0718@proton.me>
…429/400/401) (#10112) * docs: add rate limiting guide for free providers (429/400/401) Community-reported troubleshooting for auto-discovered issues when rotating through free/no-auth providers (opencode, felo-web, auggie). Documents the verified env-var combo that eliminates intermittent 429/400/401 failures in cron/agent automation: OMNIROUTE_ROTATE_ON_400=true, OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT=4, OMNIROUTE_STRUCTURE_LIMIT=off Includes root-cause breakdown (provider quota vs passthrough 401 vs concurrency amplification), verification steps via /monitoring/health, and escalation for hard quota exhaustion. * docs(providers): fix fabricated env var and breaker states in rate-limit guide Replace OMNIROUTE_STRUCTURE_LIMIT (does not exist in the codebase) with OMNIROUTE_CHAT_ADMISSION_QUEUE_MS and document the real rate-limit knobs (RATE_LIMIT_MAX_WAIT_MS / RATE_LIMIT_MAX_QUEUE_DEPTH / RATE_LIMIT_AUTO_ENABLE). Correct the circuit breaker states to the actual enum (CLOSED/DEGRADED/OPEN/HALF_OPEN) and point the health-check note at circuitBreakers.providerBreakers[].state. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: Bruno <bruno@nousresearch.com> Co-authored-by: mrcram2021 <mrcram2021@users.noreply.github.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Co-authored-by: adevwithpurpose <adevwithpurpose@users.noreply.github.com>
…oss-cumulative-integration
…e the free-forever number (#10433) Audit of every numeric claim in the README, AGENTS.md and the README SVGs against live code, plus a changelog/credit reconciliation over the full v3.8.50 cycle. Corrected numbers (all measured, not estimated): - Provider circuit breaker thresholds were scaled up in code for 500+ connection deployments (`providerFailureThreshold`: OAuth 3 -> 10, API key 5 -> 15) but the docs still published the pre-scale values. Fixed in AGENTS.md (now a table that also separates the provider-level threshold from the per-connection one and lists the provider cooldowns), in the README alt text and inside resilience-layers.svg (visible label and aria-label). - "40+ free forever" was unsourced. Measured from the free-tier catalog as every provider whose free access renews or needs no key (recurring-monthly, -daily, -uncapped, -credit, keyless; one-time signup credits and discontinued pools excluded): 56. Updated in the README and promise-pillars.svg. - Cycle-evolution table: v3.8.49 shipped 290 providers, not 291, and the model row compared the v3.8.49 free-tier catalog (516) against today's full catalog. Both columns now use the same metric - distinct documented models, 1185 -> 1202. - Tech-stack row: 95 domain modules -> 117. The free-forever count is now enforced by check:docs-counts so it cannot drift again; it is derived from freeType in the live catalog, like every other gated number. Changelog reconciliation (`scripts/release/list-uncovered-commits.mjs`): uncovered cycle commits drop from 149 to 62. 75 user-facing commits gained a bullet with author attribution, the 45 ref-less direct pushes and 29 chore/ci/test/docs commits were consolidated into rollup bullets, and the contributors table grew from 147 to 161 rows - 14 contributors who had landed work with no credit at all (including @amartinawi, @pacocartones and @excessivechaos) are now credited. The remaining 62 carry no PR/issue ref, which is the ceiling of ref-based coverage. CHANGELOG.md and its i18n mirrors are added to .prettierignore: check:changelog- integrity compares base bullets as exact strings, and Prettier normalizes markdown emphasis inside them (*from* -> _from_), so any PR that staged the changelog turned the merge-integrity job red. scripts/release/* is the changelog's formatter of record, the same precedent already used for ENVIRONMENT.md and PROVIDER_REFERENCE.md. Co-authored-by: Xiangzhe <bakryun0718@proton.me>
…oss-cumulative-integration # Conflicts: # README.md # docs/diagrams/promise-pillars.svg
Integrates the reviewed F2-F7 and Radar hardening stack into release/v3.8.50 after exact-head CI and freeze gates.
Any process that opened the DB without setting DATA_DIR resolved to ~/.omniroute/storage.sqlite — the operator's live database, provider credentials included. tests/_setup/isolateDataDir.ts only covers the npm scripts; the documented single-file test command and ad-hoc probes bypassed it (one did exactly that during #10334). resolveWritableDataDir now redirects a test-context process with no DATA_DIR to a throwaway temp dir, stable per process. Redirect rather than throw, so the documented single-file command keeps working; OMNIROUTE_ALLOW_DEFAULT_DATA_DIR=1 opts back in and records the intent. Closes #10428
…10444) The packaged artifact stamped dist/BUILD_SHA but nothing verified the SHA belonged to the release line, so a tarball built from a feature branch installed and served traffic indistinguishably from a release build. That is how the internal gateway ended up running a build that predated #10373 and answered every request with 502 'Executor result must contain a Response' — identifying it required SSH plus grepping the compiled chunks. scripts/build/buildProvenance.ts classifies a build SHA against the release ref (pure functions, injected git probe). A missing SHA fails even with the canary override: an unidentifiable artifact cannot be vouched for. validate-pack-artifact enforces it on real packs (skipped under --policy-only, which runs without a build); OMNIROUTE_ALLOW_CANARY_BUILD=1 records a deliberate off-release-line build instead of failing it. /api/monitoring/health now exposes system.buildSha — absent when unknown, never fabricated. Closes #10427
…k anchor (#10446) Deploying the internal gateway was a manual build/pack/scp/npm-i/pm2-restart sequence with no record of what landed and no proof it served traffic. On 2026-08-14 that shipped a package built from a branch predating #10373: the process came up, health said 'healthy', and every request returned 502 until a human hit it. scripts/ops/deployCanary.ts holds the policy as pure functions — refuse an artifact that is not traceable to the release line (reusing #10427), and grade the deploy on health PLUS at least one real completion. Zero probes fails: 'no probe ran' must never read as 'everything is fine', which is exactly how a broken egress path hides behind a green health check. Remote steps are argv arrays, never shell strings (Hard Rule #13), ordered so the rollback anchor is captured before the install overwrites it. scripts/ops/deploy-canary.mjs performs the side effects, supports --dry-run, and prints the rollback command when the smoke fails. Closes #10429
) * feat(providers): add tencent-aistudio-web cookie provider (tasw) * fix(sse): remove orphaned DevinDesktopExecutor import from executor index The "devin-desktop" executor key is unused (devin-desktop provider config resolves to executor "devin-cli"); the imported ./devin-desktop.ts file was never present, so executors/index.ts failed to load (ERR_MODULE_NOT_FOUND) and broke every unit test that imports the executor registry (e.g. tests/unit/deepseek-web.test.ts). Stale base sync carried this into the branch. Remove the dead import/registration/export. * fix(providers): restore DevinDesktopExecutor registration in executor index The previous commit removed the devin-desktop executor import/registration/ export from open-sse/executors/index.ts, but the devin-desktop provider registry still resolves executor "devin-desktop" and tests/unit/devin-providers.test.ts asserts hasSpecializedExecutor("devin-desktop") is true. The removal broke 6 tests in that file. Restore the three lines so the live Devin Desktop executor keeps serving the provider. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * fix(providers): correct tencent-aistudio-web wrapper shape + provider count sync Return {response,url,headers,transformedBody} instead of a raw fetch Response (the executor contract every other executor in this file follows) and re-wrap the upstream body so it uses the local Response constructor, not the undici-patched one from globalThis.fetch. Regenerate docs/reference/PROVIDER_REFERENCE.md and sync the 339->340 provider-count claims (README, AGENTS.md, llm.txt + 42 i18n mirrors, package.json, promise-pillars/comparison-table/cli-terminal SVGs) that this PR's new provider invalidated. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * docs(providers): sync readme-hero.svg provider count claim (339->340) Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * fix(providers): register tencent-aistudio-web web-session credential metadata + golden Add the WEB_SESSION_CREDENTIAL_REQUIREMENTS entry for tencent-aistudio-web (cookie-based, matching the executor's raw Cookie-header credential) and regenerate the translate-path golden snapshot to include the new provider — both were failing CI unit tests that enumerate every registered provider. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * fix(providers): align tencent-aistudio-web test with the wrapper-shape contract The test asserted res.status/res.json() directly against executor.execute()'s return value, matching the pre-fix (broken) raw-Response shape. Update it to read res.response.status/res.response.json() — the {response,url,headers, transformedBody} contract every executor in this codebase follows. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: MeRezaRezaei <MeRezaRezaei@users.noreply.github.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Co-authored-by: adevwithpurpose <adevwithpurpose@users.noreply.github.com>
Co-authored-by: Xiangzhe <bakryun0718@proton.me>
Auto combos (virtual auto/* pools via virtualFactory and pure-auto named combos via expandAutoComboCandidatePool) expanded their candidate pool from the provider's STATIC registry catalog, which can include models the operator never synced or approved (e.g. openrouter/auto). The visibility filter (getHiddenModelsByProvider) only caught models explicitly flagged isHidden, so catalog-only models passed through and got routed upstream. Build the credentialed pool from the models the user actually has available (synced + custom non-hidden), falling back to the static catalog only when the operator has no synced/custom models for that provider. Applies to every provider uniformly (openai, kilocode, openrouter, ...), with per-connection scoping for synced models. Provider wildcards (providerWildcard.ts) already used the active synced catalog as the authoritative source. Regression coverage: tests/unit/combo-auto-pool-visible-only.test.ts Co-authored-by: herjarsa <herjarsa@users.noreply.github.com>
The upstream Messages API rejects directive-style messages (empty content array with a message-level output_config) when they sit at messages[0] — the initial system prompt position — while accepting the form at any other position. Measured in production: 122x 400 on the offical-claude combo in one hour. The mid-conversation-system passthrough (official provider + 1M-context beta models) keeps system-role messages inside messages[], so a directive that arrived first went upstream unchanged. relocateDirectiveOnlyMessages() moves the whole leading run of empty system messages: directive-only ones past the first real turn, plain empties dropped. extractSystemRoleMessages() now folds a directive's output_config into the top-level parameter instead of silently discarding it. Signed-off-by: Minxi Hou <houminxi@gmail.com>
…h (400 regression) (#10458) * fix(kilocode): strip unsupported response_format for DeepSeek (400 regression) kilocode's DeepSeek V4 Flash rejects ANY response_format — both json_schema AND json_object 400 with 'Invalid input: response_format' (verified live 2026-08-15 via the Hindsight fact-extraction path on kilocode/deepseek/deepseek-v4-flash). The default executor's applyJsonSchemaFallback only covered openai-compatible-* providers and only downgraded json_schema -> json_object, so kilocode forwarded the unsupported format raw. Same bug class as the opencode fix #9992. For kilocode: strip response_format entirely and inject the schema (or a plain 'valid JSON only' instruction for json_object) into the system prompt. openai-compatible-* keeps the existing json_schema downgrade and json_object passthrough (they accept both). Regression tests: kilocode json_schema is stripped + schema-injected; kilocode json_object is stripped + JSON-only instruction; both verified to fail without the fix (sabotage: 2 fail). All 49 executor-default-base tests pass. * fix(kilocode): drop as-any casts in new tests to clear the frozen ESLint baseline The file's frozen no-explicit-any baseline is count 42; the new kilocode strip tests added 3 net-new 'as any' casts, tripping the --max-warnings 0 lint-guard. Replace them with typed assertions that carry the same checks. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com> --------- Co-authored-by: benzntech <benzntech@users.noreply.github.com> Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
…exhausted lock (#10445) * fix(sse): let :free OpenRouter models bypass connection-wide credits_exhausted lock A 402 from one paid OpenRouter model correctly locks the whole connection as credits_exhausted for an hour (intentional, per #6842), but that lock was also blocking every :free model on the same connection even though OpenRouter bills free models separately from account credits. Reconstructed clean against release/v3.8.50 by the maintainer: the author's original branch predated a large auth.ts import refactor; the same delta was re-applied onto the current tip and the TDD test still passes. TDD: tests/unit/openrouter-free-model-credits-exhausted.test.ts reproduces the bug (fails before the fix, passes after) and covers the three guard cases above. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * test(mutation): register openrouter-free-model-credits-exhausted in stryker tap.testFiles The new unit test covers src/sse/services/auth.ts, which is one of the 31 stryker-mutated modules — per check-mutation-test-coverage every covering test must be listed in tap.testFiles or its mutant kills stop counting. Registered the file so the blocking mutation-test-coverage gate passes. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: killmonger2317-coder <282069920+killmonger2317-coder@users.noreply.github.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: Xiangzhe <bakryun0718@proton.me>
Implements the secure, opt-in Video Bridge for issue #9760, including bounded FFmpeg frame extraction, capability-aware routing, telemetry, settings UI, localization, documentation, and regression coverage.
resolvePortPid shelled out to lsof alone. On a host without it, spawn raises ENOENT, the error handler turned that into null, and the caller could not tell 'nothing holds this port' from 'I have no way to look' - so a service adopted on a supervisor restart kept pid: null forever, silently, which is the regression the adopt-branch test guards against. Probes lsof, then ss, then netstat, sharing one deadline so the whole lookup still costs at most PID_RESOLVE_TIMEOUT_MS. Output parsing for each is a pure exported function so the formats are unit-testable without the binary being installed. netstat cannot filter by port, so its parser matches the local-address column rather than scanning the line, keeping a foreign address that ends in the same number from being read as a listener.
…-status fix(video-bridge): restore runtime extraction and remote status
…lf-loop fix(video-bridge): route captions through provider connections
…nks (#10512) Co-authored-by: Xiangzhe <bakryun0718@proton.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🚀 Release v3.8.50
Living release notes — reconciled 2026-08-14 against the full cycle (cycle open
ed2db6cb19→ tip). Mirrors the## [3.8.50]CHANGELOG section 1:1.📊 What is in this release
830 commits since the cycle open (892 including merge commits) · 761 merged PRs · 161 credited contributors plus the maintainer.
Highlights: the OmniConductor integration (A2A inbound delegation, fleet skills on the Agent Card, dashboard Conductor panel with Faro push-to-talk voice chat — #8080/#8119/#8221/#8222/#8223), canonical provider-grouped
/v1/modelsordering (#9215), encrypted reasoning replay opt-in (#9601 via #9876), adaptive admission & overload protection with atomic RPM rolling leases (#9259/#9262), a provider wave (Novita catalog expanded to 19 curated models #8913, UnoRouter #8978, Regolo AI #9031, Openference OAuth #9722, DeepAI multimodal #6671), Electron remote server mode (#8799), the GHE Copilot OAuth lifecycle repair (#8970) plus OpenAI model lifecycle enforcement without silent reroutes (#8627), and the cycle-long TypeScript 7 typing campaign + measured quality-gate ceilings (#9529 and the TS7 series).🆕 Landed since the 2026-08-12 reconciliation
/v1/ocrwith a transformation layer and Azure Document Intelligence (feat(ocr): multi-provider /v1/ocr with transformation layer (Azure Document Intelligence) #10283), a Vertex AI DeepSeek-OCR provider (feat(ocr): Vertex AI DeepSeek-OCR provider #10398),imageToTextderived from the OCR registry with the chutesdots.ocrseed (feat(providers): derive imageToText from the OCR registry + chutes dots.ocr seed #10400), and theimageToTextserviceKind declared across the major vision providers (feat(providers): declare imageToText serviceKind on major vision providers #10275).i-have-adhdoutput style (feat(sse): add i-have-adhd output style to compression catalog #10271) and acountTextTokenscap at 50k chars that also strips base64 data URIs (perf(compression): cap countTextTokens at 50k chars and strip base64 data URIs #10118).nextpinned to an exact version so a fresh upstream release cannot break installs (fix(deps): pin next to an exact version (16.3.1 breaks every new install) #10340).✅ Reconciliation status — 2026-08-14
Re-reconciled after the cycle advanced by ~105 merged PRs since the 2026-08-12 pass:
75 user-facing commits gained a bullet with author attribution; the 45 ref-less direct pushes and 29 chore/ci/test/docs commits were consolidated into rollup bullets. The contributors table grew from 147 to 161 rows — 14 people who had landed work with no credit at all (among them @amartinawi, @pacocartones and @excessivechaos) are now credited. The remaining 62 commits carry no PR/issue ref, which is the ceiling of ref-based coverage.
CHANGELOG.mdand its i18n mirrors are now in.prettierignore:check:changelog-integritycompares base bullets as exact strings and Prettier rewrites markdown emphasis inside them (*from*→_from_), so any PR that staged the changelog turned the merge-integrity job red.🔎 Reconciliation notes (2026-08-12)
Coverage was measured over the real cycle range (
ed2db6cb19..HEAD, resolved by package.json content, notgit describe --tags) withscripts/release/list-uncovered-commits.mjs. The audit found 467 cycle commits with no CHANGELOG bullet and 224 external PRs with no credit (108 people). All closed that day:[Unreleased]placeholder had no emoji headings, so the fragment aggregator's first-heading match pointed inside the published[3.8.49]section — aggregating would have silently corrupted released notes. The## [3.8.50]living section was created first, position-proven with the aggregator's owninsertBullets, and only then were the 276 pendingchangelog.d/fragments folded in.8862— a prior-cycle PR by another author; real PR is Expand the Novita AI model catalog #8913 by @jax-novita) and the catalog provider-grouped ordering fragment (filename said8072— the umbrella issue; real PR is fix(models): canonical provider-grouped catalog ordering #9215 by @nguyenha935, confirmed against the PR body).cherry-pick(pr-N)/maint: follow-up #N) were re-attributed to the original contributor's own PR number, resolved via the GitHub GraphQL API rather than subject parsing.#ref-based coverage can reach.changelog.d/fragments were renamed to the canonical<PR>-<slug>.md(one kept unprefixed: a direct push with no PR).📖 Full per-PR changelog with author attribution:
CHANGELOG.md→[3.8.50]— 726 bullets, too large to inline, mirrored across the i18n copies.