Commit Graph

824 Commits

Author SHA1 Message Date
Brandon Bennett
8d78e3dfd3 fix: per-connection virtual admission lanes (#9654) (#9940)
* fix: add per-connection virtual admission lanes (#9654)

Worst-day-ever analysis to harden AdaptiveAdmissionController:

- Guard expireEntry() against null entry (CRITICAL null deref)
- Add deleteLane() to drain+reject on LRU eviction (HIGH orphaned promises)
- Fix Map mutation during evictIdleLanes iteration (MEDIUM safety)
- Add ADMISSION_LANE_EVICTED reject code (MEDIUM clarity)
- Pass sessionId to admitChatRequest in route.ts
- virtualLanes defaults to false in validateConfig
- 7 new controller tests + 14 new byte-level admission tests
- Assertions tightened from >= to === (Matt Pocock methodology)

Debunked 2 false positives: concurrency race (single-threaded JS)
and memory amplification (FairCostQueue bounds per-lane).

Fixes #9654

* fix(admission): restore bounded queue-wait on per-connection lanes (#9654)

The per-connection lane refactor dropped the bounded queue-wait
(acquireHeavyWithin / #waiters / queueMs). #9654's acceptance criteria and
#9608 section C prefer server-side wait/pacing up to defaultMaxWaitMs over
an instant retryable 503.

- ChatAdmissionController: re-add #waiters FIFO + acquireHeavyWithin(timeoutMs);
  queueMs: 0 preserves the instant-503 path
- admitChatStructure and admitChatRequest.reserve are async again and take queueMs
- route: pass CHAT_ADMISSION_QUEUE_MAX_MS and await the admission calls
- per-connection lane tests await the async admitChatStructure

Admission suite: 114/114 pass (bun test, 7 files).

* chore: re-trigger CI after dast-smoke infra cancellation (#9654)

* feat(admission): cancel queue-wait on client abort (#9654)

U2 from KC plan 2026-08-09-001. Thread the request AbortSignal through
acquireHeavyWithin so a disconnected client stops parking in the FIFO
for the full queueMs.

- acquireHeavyWithin(timeoutMs, signal?): on abort the waiter is removed
  from the FIFO immediately and the promise resolves null early;
  pre-aborted signals never park; the deadline timer is cleared when
  abort/release wins the race
- admitChatRequest reserve() passes request.signal; admitChatStructure
  gains options.signal; the route threads request.signal
- 5 exact-assertion tests (settle-early, pre-aborted, byte-heavy,
  structural, FIFO-preservation): 119/119 across the 7-file suite

* fix(admission): bound queued bytes for the queue-wait heap valve (#9654)

U3 from KC plan 2026-08-09-001. The restored queue-wait parks fully-buffered
bodies; without a cap, several large coding-agent bodies (~750 KB) waiting at
once recreates the #4380 heap amplification this module was built to stop.

- acquireHeavyWithin(timeoutMs, signal?, queuedBytes): each parked waiter is
  charged its buffered size against CHAT_ADMISSION_MAX_QUEUED_BYTES (default
  4 MB); over-budget waits reject immediately with a retryable 503 and never
  park. The charge is released on wake, abort, or timeout.
- Real sizes threaded from admitChatRequest (declared length / sniffed bytes);
  structural waits charge the conservative 256 KB weight.
- Lower default OMNIROUTE_CHAT_ADMISSION_QUEUE_MS to 2000ms (was 5000ms).
- Env vars documented in .env.example; 6 exact-assertion tests: 125/125 across
  the 7-file admission suite (was 119).

* docs: map the two admission-lane systems for operators (#9654)

U5 from KC plan 2026-08-09-001. Verifies lane metrics are exposed by the health
payload (GET /api/monitoring/health -> adaptiveAdmission -> lane* fields) and
records which lane system reports where: byte-level per-connection lanes (always
on, memory scope) vs adaptive virtual lanes (opt-in via OMNIROUTE_CHAT_VIRTUAL_LANES,
dispatch scope) plus the explicit opt-in ops note.

* docs: add required frontmatter to admission-lanes doc (dast-smoke build fix)

* docs: sync env vars with .env.example and ENVIRONMENT.md (docs gate fix)

* fix(admission): complete REJECT_MAP, literal lane env read, split oversized test file

Three CI-gate fixes surfaced by the post-merge check run (head 3de77166e):

1. open-sse-typecheck (TS2741): REJECT_MAP was missing the ADMISSION_LANE_EVICTED
   entry that controller.ts:662 emits on lane eviction. Add the 503 mapping so the
   Record<AdmissionRejectCode, RejectHttpMapping> is total.
2. Docs Gates fabricated-claim: OMNIROUTE_CHAT_VIRTUAL_LANES was read dynamically
   via ENV_KEYS.virtualLanes (env[key]), invisible to the literal env.X scanner.
   Read it literally — behavior-identical, doc claim now verifiable.
3. check:file-size: chat-body-admission.test.ts (1307 lines) exceeded the 1000-line
   new-file cap. Split the queue-wait/abort/heap-valve section into
   chat-body-admission-queue.test.ts (818 + 513 lines, both under cap).

Suite: 125/125 across 8 files. All three checkers pass locally.

* refactor(admission): drop dead ENV_KEYS.virtualLanes entry + lock lane-evicted mapping test

Code-review follow-up on 50c93d266:

1. ENV_KEYS.virtualLanes is now unreferenced since the literal env read landed;
   remove it so the config map only lists keys actually read through the map.
2. Add an exact-assertion runtime test for the ADMISSION_LANE_EVICTED mapping:
   a queued lane waiter evicted by the 60s idle TTL rejects with 503 /
   admission_lane_evicted / Retry-After 1 / sanitized body (no raw tenant key).
   Proves the REJECT_MAP entry end-to-end through buildAdmissionRejectResponse.

Suite: 126/126 (17 in runtime file, 125 in the 8-file admission suite).

---------

Co-authored-by: Brandon Bennett <brandonbennett@macbookair.myfiosgateway.com>
2026-08-10 03:25:13 -03:00
Vasily Larin
40f9709071 fix(executors): preserve non-strict Codex tool semantics (#9931)
* fix(executors): preserve non-strict Codex tool semantics

* docs(changelog): add Codex strict semantics fix
2026-08-10 03:25:07 -03:00
Aman
ee0073dc4a fix(db): invalidate stale LKGP pins on connection delete (#9936) 2026-08-10 02:54:59 -03:00
Rakibul Hasan
4938a435ea fix(memory): env-configurable strict system-message-first providers (#9924)
* fix(memory): allow OMNIROUTE_STRICT_SYSTEM_PROVIDERS to extend the system-first provider list

PROVIDERS_SYSTEM_MUST_BE_FIRST (added in #6225 for #6135) gates both the
memory-injection placement fix and the #7293 hoistLeadingSystemMessage
translator fix, but was hardcoded to xiaomi-mimo/mimo only. Self-hosted
deployments routing other strict backends (e.g. a custom OpenAI-compatible
connection in front of a self-hosted Qwen3.5+/3.6 model, whose chat template
rejects any non-leading system message the same way) had no way to opt in
without forking and rebuilding the image.

Adds OMNIROUTE_STRICT_SYSTEM_PROVIDERS (comma-separated, case-insensitive
provider ids) to extend the built-in set at read time, mirroring the
injectable-env pattern already used in src/lib/memory/typedDecay.ts. No
behavior change for anyone who doesn't set it.

* chore: fix changelog fragment PR number
2026-08-10 00:27:47 -03:00
diegosouzapw
44fd0edd85 chore(quality): file-size baseline +30% (DRIFT rebaseline for v3.8.51)
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-08-10 00:24:13 -03:00
Diego Rodrigues de Sa e Souza
6553ba31f2 feat(dashboard): Modality Bridge settings page (vision tabs, model selector, stats, test button) (#9782)
* feat(i18n): modality bridge page strings (en + synced locales)

* feat(dashboard): ModalityBridgeVisionTab + stats row + test button

* feat(dashboard): Modality Bridge settings page with vision/audio/video tabs + sidebar entry

* feat(dashboard): relocate vision bridge card to link + media-providers shortcuts

* docs(guardrails): document Modality Bridge dashboard

* chore: preserve upstream formatting after base merge

* fix(modality-bridge): satisfy i18n quality gates

* fix(i18n): preserve canonical Chinese glossary terms

* fix(modality-bridge): clear dashboard quality regressions

* fix(settings): use catalog-only modality labels

* fix(i18n): isolate modality bridge availability copy

* chore(i18n): prepare conflict-free Modality Bridge base sync

* docs(modality-bridge): align migration note with dead-code decision

* fix(i18n): sync capability filter locales after release merge

* fix(i18n): restore canonical Traditional Chinese glossary

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-10 00:16:06 -03:00
Diego Rodrigues de Sa e Souza
06a691f8fe Merge pull request #9424 from diegosouzapw/feat/5696-layer-a-capability-filter
feat(core): add Layer A capability filter at router (#5696)
2026-08-09 20:51:28 -03:00
SB Yoon
40e1562850 fix(i18n): re-escape CC discovery-alias angle brackets for next-intl (#9917)
* fix(i18n): re-escape CC discovery-alias angle brackets for next-intl

Restore #8747 HTML-entity escaping for claude/<provider>/<model> in the
three CC discovery-alias message keys so next-intl stops logging
INVALID_MESSAGE: UNCLOSED_TAG on provider detail pages after the bulk
entity-unescape regression.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(i18n): align conflict context with release

* fix(i18n): cover localized CC alias placeholders

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
2026-08-09 20:27:18 -03:00
diegosouzapw
63bf4b909d Merge remote-tracking branch 'origin/release/v3.8.50' into codex/wave3b-9424
# Conflicts:
#	config/quality/file-size-baseline.json
2026-08-09 20:02:17 -03:00
Diego Rodrigues de Sa e Souza
fade1cbab3 Merge pull request #9341 from diegosouzapw/feat/9268-gemini-schema-recursive-type-empty-choices
feat(gemini): recursive schema type:object + empty choices interceptor (#9268)
2026-08-09 20:01:44 -03:00
Diego Rodrigues de Sa e Souza
3aa0a7306f Merge pull request #9337 from diegosouzapw/feat/9322-nanogpt-endpoint-surface
feat: expose full NanoGPT endpoint surface (#9322)
2026-08-09 20:01:41 -03:00
Diego Rodrigues de Sa e Souza
9d06dcfd6c Merge pull request #9493 from diegosouzapw/feat/8468-bun-windows-ci-coverage
feat(ci): add windows-latest leg to test-bun-sqlite job (#8468)
2026-08-09 20:01:39 -03:00
Diego Rodrigues de Sa e Souza
ab8f3e83b7 fix(ci): allow test-masking to finish in release preflight (#9964)
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-09 19:41:03 -03:00
diegosouzapw
493cae2ed9 Merge remote-tracking branch 'origin/release/v3.8.50' into codex/wave3b-9424
# Conflicts:
#	config/quality/file-size-baseline.json
#	src/i18n/messages/en.json
#	src/i18n/messages/pt-BR.json
#	src/shared/constants/featureFlagDefinitions.ts
#	stryker.conf.json
2026-08-09 18:25:44 -03:00
diegosouzapw
a6f095c583 Merge remote-tracking branch 'origin/release/v3.8.50' into codex/wave3b-9341
# Conflicts:
#	config/quality/file-size-baseline.json
2026-08-09 18:25:42 -03:00
diegosouzapw
26daeabcf2 Merge remote-tracking branch 'origin/release/v3.8.50' into codex/wave3b-9337
# Conflicts:
#	open-sse/config/providers/registry/nanogpt/index.ts
2026-08-09 18:25:16 -03:00
diegosouzapw
5560b90322 Merge remote-tracking branch 'origin/release/v3.8.50' into codex/wave3b-9493 2026-08-09 18:23:15 -03:00
diegosouzapw
0d36801f20 Merge remote-tracking branch 'origin/release/v3.8.50' into fix/release-v3.8.50-post-sweep-base-red
# Conflicts:
#	src/i18n/messages/vi.json
2026-08-09 15:21:37 -03:00
diegosouzapw
754ba0fa86 fix(release): repair post-sweep base regressions 2026-08-09 15:16:55 -03:00
Diego Rodrigues de Sa e Souza
2afaab52a1 maint: final follow-up cherry-pick #9619 (#9901)
* fix(quality): clears two release/v3.8.50 base-red gates

Unblocks Merge integrity and Docs Gates for every PR against
release/v3.8.50, not just this branch:

- changelog.d/features/9415-newapi-sub2api-aggregator-balance.md had a
  non-standard YAML frontmatter header that no other fragment in the
  tree uses. check-changelog-integrity.mjs reads a fragment's first
  non-blank line to validate it starts with a markdown bullet; the
  frontmatter's leading `---` made that check fail regardless of the
  actual bullet content further down. Removed the frontmatter and
  reformatted the body to match the documented changelog.d/README.md
  bullet convention.
- docs/ops/VM_DEPLOYMENT_GUIDE.md documented OMNIROUTE_MAX_POOL_SIZE
  and OMNIROUTE_DB_POOL_SIZE as tunable env vars, but neither is read
  anywhere in the codebase (confirmed via full-repo grep) — this repo
  uses SQLite, which has no connection-pool concept these vars could
  plausibly control. check:fabricated-docs --strict correctly flags
  fabricated env-var claims; removed the bullet rather than
  implementing a feature to match invented documentation.

* fix(i18n): completes Vietnamese parity, fixes empty migration query

Two more release/v3.8.50 base-red items, both surfaced while chasing
CI failures on unrelated PRs:

- vi.json was missing 8 keys that #9539 (NewAPI/Sub2API aggregator
  balance) added to en.json without a matching i18n:sync-ui run —
  pt-BR.json already had all 8, only Vietnamese drifted. Added
  translations for the 6 provider-settings strings, the feature-flag
  description, and the quota tooltip; verified against
  tests/unit/i18n-vi-completeness.test.ts (parity, placeholder
  preservation, ICU parse — all 5 assertions pass).

- src/lib/db/migrations/120_interception_rules.sql was pure comments
  documenting a no-schema-change key_value namespace, with no
  executable SQL statement — the migration runner logged
  "FAILED: 120_interception_rules — Query contained no valid SQL
  statement" on every fresh DB init. 118_provider_param_filters.sql
  (same pattern, two migrations earlier) already ends with a bare
  `SELECT 1;` no-op for exactly this reason; 120 was just missing it.
  Verified directly against better-sqlite3 that the file now executes
  without error.

* fix(types): clears 6 pre-existing release/v3.8.50 typecheck errors

typecheck:core is its own blocking CI job (quality.yml), separate from
Docs Gates/Merge integrity. Confirmed pre-existing and unrelated to
any current work by branching this worktree directly from
upstream/release/v3.8.50 with no other merges applied.

- accountSemaphore.ts: isBypassed() already excludes null/<=0
  maxConcurrency before ensureGate() is called, but a boolean-
  returning helper isn't a type predicate TS can narrow through.
  Added a targeted `as number` at the one call site, with a comment
  explaining why it's safe.

- combo/comboStructure.ts: two module-scope `const HARD_COMPAT_REASONS`
  declarations with different values — a genuine "can't redeclare"
  compile error, not a narrowing gap. The first (4-item set including
  "output_tokens") had zero usages between its own declaration and the
  second; the second (3-item set, matching the CompatFilterOptions doc
  comment exactly) is what hasHardCapabilityFailure/
  describeCapabilityFilterExhaustion/the third call site all actually
  use. Removed the dead first declaration.

- combo/comboStructure.ts + combo/fusionPanel.ts: both accessed
  `.prompt`/`.model` on a `ComboModelStep | ComboProviderWildcardStep`
  union after only excluding `combo-ref`, but `ComboProviderWildcardStep`
  has neither field — a real latent bug (fusionPanel would have pushed
  `undefined` into a fusion panel for a wildcard step). Narrowed to
  `step.kind === "model"` in comboStructure, and switched to the
  already-existing `getComboModelString()` helper in fusionPanel (which
  correctly resolves to null for unsupported step kinds, mirroring how
  combo-ref is already skipped there). Verified directly via a
  standalone script exercising both branches (wildcard vs. model step).

- combo/quotaStrategies.ts: imported `preferAntigravityConnectionsWithStoredProject`
  from a module that never existed (`../antigravityProjectPersistence.ts`,
  distinct from the real `antigravityProjectPersist.ts`) — the function
  itself was referenced nowhere else in the codebase. Wrote the missing
  implementation: prefers Antigravity connections with a discovered
  `projectId` for reset-aware routing, failing open to the full list
  when none have one yet (per the file's own "Exclude... from reset-aware
  pool" changelog note, softened to a preference — strict exclusion
  would empty the pool entirely for a fleet of freshly-added accounts).
  Verified directly via a standalone script.

- compression/engines/ccr/index.ts: `enforceGlobalBudget(owner, bytes)`
  was called with only `bytes` at one of its two call sites, missing the
  `owner` argument the other call site (and the function's own doc
  comment on preferring the calling principal's LRU eviction) already
  uses correctly. Added the missing `entry.principalId` argument.

- firecrawlQuotaFetcher.ts: `fetchFirecrawlQuota` was annotated to
  return `Promise<QuotaInfo | null>` but every return path constructs a
  `FirecrawlQuota` (QuotaInfo extended with remainingCredits/planCredits/
  extraCreditsInferred/overPlan) — the type the file already defines and
  the type `parseFirecrawlCreditUsage` already correctly returns.
  Widened the annotation to match; `FirecrawlQuota extends QuotaInfo` so
  this stays compatible with the `QuotaFetcher` contract.

npm run typecheck:core and npm run check:dashboard-typecheck both pass
cleanly. A subset of DB-backed tests in this area also fail, but 100%
attributably to an already-tracked, unrelated migration version
collision (134 -> [ccr_blocks, proxy_logs_egress_ip], see
_tasks/features-v3.8.4/9route/POST-MERGE-AUDIT.md) — confirmed by every
failure's stack trace bottoming out at that exact error, not at
anything touched here.

* fix(sse): update stale ALL_ACCOUNTS_INACTIVE test assertions to ALL_TARGETS_SKIPPED

Two combo-routing-engine.test.ts cases assert the pre-dispatch-skip scenario (isModelAvailable always false, zero dispatch attempts) returns ALL_ACCOUNTS_INACTIVE. Production code already distinguishes this case via the recordedAttempts === 0 branch and returns the more precise ALL_TARGETS_SKIPPED -- the tests were never updated when that branch shipped upstream, so they fail on a clean release/v3.8.50 checkout independent of this PR's changes.

* fix(sse): update second stale ALL_ACCOUNTS_INACTIVE assertion (T24)

Same pre-existing upstream test-drift as 038035f93: t23-t24-fallback-resilience.test.ts's T24 case asserts the pre-dispatch-skip scenario returns ALL_ACCOUNTS_INACTIVE, but production code returns the more precise ALL_TARGETS_SKIPPED when recordedAttempts === 0. Caught by this PR's own fresh CI run after the dirty-mergeable-state fix.

* fix(quality): rebaseline combo-routing-engine.test.ts own-comment growth

The ALL_ACCOUNTS_INACTIVE->ALL_TARGETS_SKIPPED fix (58ab721fe) added explanatory comments (+7 lines), pushing the file past its frozen 3457 cap. CI's PR-mode check:file-size caught it; local check-file-size.mjs was not re-run after that specific commit.

* chore(tests): drop explanatory comments on ALL_TARGETS_SKIPPED assertions

Kept the assertion value fix (ALL_ACCOUNTS_INACTIVE -> ALL_TARGETS_SKIPPED); the comments were unnecessary. Reverts the file-size baseline bump these comments caused (combo-routing-engine.test.ts back to its original 3457).

---------

Co-authored-by: Will Gordon <wgordon@redhat.com>
2026-08-09 14:15:53 -03:00
Diego Rodrigues de Sa e Souza
06727f0e74 cherry-pick(pr-9556): fix(translator): preserve Kimi K3 Responses reasoning (#9879)
* fix(translator): preserve Kimi K3 Responses reasoning

* fix(translator): make K3 reasoning preservation model-driven

* fix(translator): replay cached Kimi reasoning before fallback

* fix(translator): keep authentic K3 reasoning through cleanup

* refactor(reasoning): use replay policy for K3

---------

Co-authored-by: jackjinke <jack.kejin@gmail.com>
2026-08-09 10:07:03 -03:00
Diego Rodrigues de Sa e Souza
5f75abe4a2 cherry-pick(pr-9634): fix(test): reconcile base-drifted test expectations on release/v3.8.50 (#9874)
* fix(combo): restore routing module load

* fix(db): resolve ccr migration version collision

Renumber the CCR block-store migration from 134 to 139, reconcile databases that already applied the legacy slot, and add regression coverage for both upgrade paths.

Co-Authored-By: GPT-5 <noreply@openai.com>

* fix(changelog): format the aggregator balance fragment as a bullet

The fragment landed with YAML frontmatter rather than the bullet the
aggregator reads, so check:changelog-integrity exits 1 on every branch and
takes the merge-integrity job down with it regardless of what the branch
changed.

Only the format changes. The entry text is the author's, unedited, and now
carries the link to the pull request that shipped it.

* fix(test): update expected auth/vision/provider schema for base-drifted expectations

* fix(test): narrow this branch to the drifted test expectations

Three other PRs already cover what this one was carrying. #9618 renumbers the
colliding ccr_blocks migration, #9632 repairs the malformed aggregator changelog
fragment, and #9676 restores the combo module load by implementing the selection
helper the import was reaching for, rather than deleting the caller the way this
branch did. Keeping any of it here would put two files back on the same migration
slot and overwrite a better fix with a worse one.

What survives is the part none of them touch. Once the combo barrel loads again,
three assertions in the context-window filter suite start failing: they demand
that catalog-too-small targets be dropped, while the file's own header and its
four neighbouring tests say those targets stay available as runtime fallback.
The unresolved import was masking them. A new case pins the output-token limit
as a genuine hard requirement so the relaxation cannot drift further.

The provider count assertion kept one literal at the old value after the rest of
the file moved to 198, so the partition check failed on a sum that was correct.

* chore(quality): re-time migrationRunner for the 139 guard on the new tip

---------

Co-authored-by: alexey.nazarov@softmg.ru <alexey.nazarov@softmg.ru>
Co-authored-by: GPT-5 <noreply@openai.com>
Co-authored-by: Minxi Hou <houminxi@gmail.com>
2026-08-09 10:06:57 -03:00
Diego Rodrigues de Sa e Souza
58f0ff1b41 cherry-pick(pr-9675): fix(providers): per-provider opt-out for anonymous no-auth fallback (opencode-go/zen 401s) (#9873)
* fix(providers): add per-provider opt-out for anonymous no-auth fallback

API-key providers with anonymousFallback: true (opencode-go, opencode-zen,
pollinations, kilocode) receive a synthetic "noauth" connection whenever all
real connections are terminal (credits_exhausted/banned/expired) or
unavailable. The opencode upstream now rejects anonymous requests with
401 Missing API key, so the fallback adds a guaranteed-failing round trip
and health/reconnect noise before the combo moves on.

Add a noAuthFallbackDisabledProviders settings array (zod-validated,
persisted via /api/settings, following the blockedProviders pattern).
When a provider is listed, maybeSyntheticNoAuthFallback returns null for
anonymousFallback-only providers, so exhausted providers are skipped
immediately as allExpired/allRateLimited while real keyed connections keep
working and recover automatically once quota state clears. True no-auth
providers are unaffected; blockedProviders remains their disable mechanism.
Default (absent/empty list) preserves current behavior.

Provider detail pages for anonymousFallback providers gain an
"Anonymous fallback" toggle (default ON) backed by the new setting.

Refs #9674

* fix(auth): reduce file size

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Hermes Agent <hermes@hermes-chloe.hyades.io>
2026-08-09 10:06:50 -03:00
Diego Rodrigues de Sa e Souza
740e16c3e2 cherry-pick(pr-9601): feat(responses): add encrypted reasoning replay opt-in (#9876)
* feat(codex): add encrypted reasoning replay opt-in

* feat(responses): generalize encrypted reasoning replay

* docs: clarify encrypted reasoning provider scope

* fix(ui): group reasoning replay with connection controls

* fix(logs): omit encrypted reasoning payloads

* fix(chat): reduce file size

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(chat): reduce combined file size

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: jackjinke <jack.kejin@gmail.com>
2026-08-09 09:55:02 -03:00
Diego Rodrigues de Sa e Souza
be9f43e1ee cherry-pick(pr-9695): fix(docker): make the webpack build-arg escape hatch actually work (#9872)
* build(docker): make the bundler build-arg actually take effect

A bare ENV shadows a same-named ARG for the rest of the stage, so
--build-arg OMNIROUTE_USE_TURBOPACK=0 was silently ignored and the
webpack escape hatch the surrounding comment advertises only ever
worked through -e at runtime, never at build time.

That mattered because Turbopack compiles in native Rust memory living
outside the V8 heap, so OMNIROUTE_BUILD_MEMORY_MB cannot bound it. A
build host with a memory ceiling gets SIGKILLed by the cgroup OOM
killer with no error text at all, which reads like a hung build rather
than an out-of-memory one.

* docs(docker): correct the builder stage facts and document its cost

The stage table described a builder that no longer exists: it named
node:24.15.0-trixie-slim where every stage now derives from
node:26-trixie-slim, and said the stage runs `npm run build -- --webpack`
where it runs plain `npm run build`, which is Turbopack by default.

That second one is worse than stale. A reader who needs the webpack
fallback would conclude the Docker build already uses it and never look
for the switch.

Adds a Build-time resources section covering the two build args, why the
V8 heap arg cannot bound Turbopack, and measured ceilings for both
bundlers. The runtime paragraphs that followed get their own heading so
they no longer read as part of the build-time story.

* docs(docker): correct the runtime heap defaults

Same drift as the builder stage, in the paragraphs just below it. The
image exports OMNIROUTE_MEMORY_MB=1024 and derives NODE_OPTIONS from it,
but the guide reported 512 in three places, including the environment
variable table.

The "if unset, the launcher uses 512" line was misleading in both
readings: the image always sets the variable so that branch cannot fire
under Docker, and outside Docker the launcher calibrates from host RAM
rather than using a flat 512.

* docs(changelog): add fragment for #9695

---------

Co-authored-by: Minxi Hou <houminxi@gmail.com>
2026-08-09 09:54:34 -03:00
Diego Rodrigues de Sa e Souza
ed7a68e1a9 maint: follow-up cherry-pick fix-in-place #9719 (conflict-resolved fallback) (#9893)
* fix(db): clear combo pins when connections are deleted

* docs: add changelog entry for #9719

---------

Co-authored-by: Zartharas <1402357+Zartharas@users.noreply.github.com>
2026-08-09 09:54:07 -03:00
Diego Rodrigues de Sa e Souza
04b4690f84 cherry-pick(pr-9730): fix(compression): persist RTK renderer configuration (#9867)
* fix(compression): persist RTK renderer configuration

* docs(changelog): add fragment for #9730

Adds the changelog.d/fixes/9730-persist-rtk-renderers.md fragment
required by check:changelog-integrity for the RTK enableRenderers
persistence fix in PR #9730.

---------

Co-authored-by: Isaac <isaaclyons98@gmail.com>
2026-08-09 09:53:45 -03:00
Diego Rodrigues de Sa e Souza
48d43240f4 fix(api): enforce model permissions on gateway mirrors (#9854)
Co-authored-by: Xiangzhe <xiangzhedev@gmail.com>
2026-08-09 09:52:09 -03:00
Diego Rodrigues de Sa e Souza
714a36cf99 cherry-pick(pr-9826): fix(executors): preserve Command Code usage in Responses streams (#9842)
* fix(executors): preserve Command Code usage in Responses streams

* fix(executors): add Command Code usage changelog fragment

---------

Co-authored-by: MrShitFox <qwert2006gleb@gmail.com>
2026-08-09 09:47:37 -03:00
Diego Rodrigues de Sa e Souza
bbe5c78f4d cherry-pick(pr-9828): fix(executors): strip redundant oneOf matching sibling enum (#9841)
* fix(executors): strip redundant oneOf matching sibling enum

The Codex private Responses endpoint intermittently returns a 502 upstream_empty_response for tool parameters that combine oneOf:[{const,...}] with a sibling enum containing the same value set.

When the const and enum sets match exactly, oneOf adds no constraint beyond enum. Add stripRedundantOneOfConstEnum to normalizeCodexTools to remove only this semantically redundant form.

The schema-aware recursive walker requires non-empty, unique string const branches containing annotations only, string enum values, and an exact set match. It preserves bare oneOf[const], narrowing or non-matching sets, type-discriminated oneOf, empty oneOf, non-string values, and anyOf/allOf.

Run the normalization after stripUnsupportedRegexPatterns and before assigning tool.parameters. Add focused regression coverage for matching, non-matching, nested, immutable, and Chat-to-Responses cases.

* docs(changelog): update PR number in changelog fragment

---------

Co-authored-by: Vasily Larin <larin.vas@outlook.com>
2026-08-09 09:47:28 -03:00
Diego Rodrigues de Sa e Souza
d11b99f6cc cherry-pick(pr-9834): fix(cursor): SelectedImage blobIdWithData + JPEG soft-cap prep (#9840)
* fix(cursor): hydrate SelectedImage via blobIdWithData + JPEG soft-cap

Cursor vision expects SelectedImage.blob_id_with_data (field 9) backed by
the session blobStore, and large clipboard PNGs need JPEG soft-cap prep
rather than a hard 1 MiB reject before encode.

* docs(changelog): add fragment for Cursor SelectedImage blobIdWithData fix

* refactor(cursor): split image protobuf encoding

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: SB Yoon <44089734+yansigit@users.noreply.github.com>
2026-08-09 09:47:07 -03:00
Diego Rodrigues de Sa e Souza
065fa67f63 chore(quality): reconcile final v3.8.50 ratchets (#9839)
* chore(quality): reconcile final v3.8.50 ratchets

* chore(changelog): record v3.8.50 ratchet reconciliation

* chore(ci): retrigger base-reds reconciliation checks for #9839

* chore(ci): retrigger base-red sweep run for #9839

* chore(ci): retrigger base-red checks after queued-cancel

* chore(ci): retrigger base-reds checks #9839 (queue clear)

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-09 09:28:12 -03:00
Diego Rodrigues de Sa e Souza
4d8506c2c5 fix(i18n): restore Vietnamese locale parity (#9925)
* fix(i18n): restore Vietnamese locale parity

* fix(changelog): follow fragment convention

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-08-09 09:06:05 -03:00
diegosouzapw
25e8a27045 Merge remote-tracking branch 'origin/release/v3.8.50' into HEAD 2026-08-09 00:29:30 -03:00
Diego Rodrigues de Sa e Souza
00b79b5507 test(combo): guard auto/best-free never leaks the combo name as a model (#7754)
Refs: base-red #9737
2026-08-08 13:52:44 -03:00
Diego Rodrigues de Sa e Souza
b5e17bdbde fix(resilience): set rateLimitedUntil on connection test failure for recovery (#9623)
Refs: base-red #9737
2026-08-08 13:52:37 -03:00
Diego Rodrigues de Sa e Souza
aefa2b665b fix(playground): surface provider model loading errors in LlmChatCard (#9626)
Refs: base-red #9737
2026-08-08 13:52:30 -03:00
Diego Rodrigues de Sa e Souza
df1ea5bd77 fix(db): align domain_cost_history cleanup cutoff with millisecond column (#9625)
Refs: base-red #9737
2026-08-08 13:52:23 -03:00
Diego Rodrigues de Sa e Souza
a90c5e5aba fix(db): wire telemetry cleanup scheduler in Next.js startup path (#9624)
Refs: base-red #9737
2026-08-08 13:52:17 -03:00
Diego Rodrigues de Sa e Souza
c88b96244f fix(providers): classify 400 out of extra usage as quota_exhausted for Anthropic OAuth (#9486)
Refs: base-red #9737
2026-08-08 13:52:11 -03:00
Diego Rodrigues de Sa e Souza
93ee4dce9f fix(build): add build-next-isolated.mjs sibling imports to package.json files array (#9633)
Refs: base-red #9737
2026-08-08 13:52:04 -03:00
Diego Rodrigues de Sa e Souza
6c95e2b354 fix(build): include better-sqlite3 prebuilds in standalone bun bundle (#8847)
Refs: base-red #9737
2026-08-08 13:51:57 -03:00
Diego Rodrigues de Sa e Souza
3835f318d0 fix(cli): use process.execPath for macOS launchd autostart (#9156)
Refs: base-red #9737
2026-08-08 13:51:51 -03:00
小妍儿 ✨
064a19b2d1 fix(quota): clean managed combos when deleting pools (#8906)
Merge-train validated
2026-08-08 12:45:00 -03:00
Diego Rodrigues de Sa e Souza
492f9ddc4a fix: buffer and normalize Responses tool-call argument deltas, stripping optional null before reaching the client (#9168)
Refs: base-red #9737
2026-08-08 12:07:24 -03:00
Diego Rodrigues de Sa e Souza
e7d9055314 fix(translator): avoid double-normalizing tool names in Gemini-to-Claude response path (#9177)
Refs: base-red #9737
2026-08-08 12:07:14 -03:00
Diego Rodrigues de Sa e Souza
2ed487583b fix(model-discovery): ingest capabilities.effort_tiers for synced models (#9160)
Refs: base-red #9737
2026-08-08 12:03:24 -03:00
Diego Rodrigues de Sa e Souza
cf31b795b7 fix(background): detect Anthropic top-level system prompts for background task detection (#9142)
Refs: base-red #9737
2026-08-08 11:45:54 -03:00
diegosouzapw
a5dc8731de Merge remote-tracking branch 'origin/release/v3.8.50' into feat/8468-bun-windows-ci-coverage
# Conflicts:
#	CLAUDE.md
2026-08-08 11:37:35 -03:00
Diego Rodrigues de Sa e Souza
6b706f6b5e fix(sse): broaden OMNIROUTE_SSE_COMMENTS to accept 'false','0','no' and gate metadata comment emission (#9305)
Refs: base-red #9737
2026-08-08 11:35:46 -03:00