Commit Graph

4754 Commits

Author SHA1 Message Date
Diego Rodrigues de Sa e Souza
7d67fc705c fix(resilience): fall back on a 200 masking in-body credit exhaustion (#6427) (#6616)
`validateResponseQuality()` only inspected a response's top-level `error`
field when `choices` was also missing/empty (the narrower #3424 case), so a
masked HTTP 200 that echoed a non-empty stub `choices` alongside a structured
error object — or a known exhaustion phrase like "insufficient credits" /
"quota exceeded" in the error envelope — slipped through as valid, and a
`priority` combo kept hammering the exhausted target instead of failing
over.

The check now inspects the error envelope (top-level `error` object, or a
bounded exhaustion-phrase match against error.message/code/type and
top-level message/detail) unconditionally, before any shape-specific
branch — never against `choices[].message.content`, so legitimate
completions that merely mention "quota" in prose are not misclassified.

Regression guard: tests/unit/masked-200-exhaustion-fallback-6427.test.ts
2026-07-07 22:41:25 -03:00
Diego Rodrigues de Sa e Souza
908e3bef38 fix(compression): add adaptive-ladder rankings for non-default catalog engines (#6533) (#6615) 2026-07-07 22:39:14 -03:00
Diego Rodrigues de Sa e Souza
533016af36 fix(providers): backfill #6454 CHANGELOG bullet + 11-member fusion regression guard (#6614)
The fusion quorum-clamp/failure-detail root cause reported in #6454 was
already fixed and merged via #6521 (open-sse/services/fusion.ts already
carries Math.max(1, cfg.minPanel) + per-member failure reasons on this
branch). That merge never landed a CHANGELOG bullet for #6454 itself.

Backfills the missing bullet and adds a regression test at the exact
repro scale (11-member fusion-free-style panel, 2 cooling / 9 healthy)
to lock in that a cooling minority no longer sinks a healthy majority,
while a genuinely all-failed panel still returns the documented 503.
2026-07-07 22:38:26 -03:00
Diego Rodrigues de Sa e Souza
f4cd3e8c80 fix(api): serialize tool-call args correctly through /anthropic translation (#6459) (#6609)
appendToolCallArgumentDelta() treated any non-string incoming fragment as
empty, silently dropping tool-call arguments delivered as an already-parsed
JSON object/array (a non-conformant shape some upstreams emit for
tool_calls[].function.arguments) instead of JSON-encoding them. This left
tool_use.input empty on the /anthropic streaming path and opened the door to
downstream [object Object] string coercion once buffers were concatenated.
Now JSON.stringify()s the non-string fragment instead of discarding it.
2026-07-07 21:48:27 -03:00
Diego Rodrigues de Sa e Souza
978e92e104 fix(providers): honor fusion config.judgeModel for final synthesis (#6455) (#6607)
The fusion single-survivor degrade path (added for #6454) returned the
lone panel answer directly whenever only one panelist succeeded, ignoring
an explicitly configured judgeModel. With default minPanel=2 and a 2-model
panel, any single flaky panelist forced this path every request, so the
configured judge never ran and the response .model reflected a panel member.

The judge is now still invoked to synthesize a lone surviving answer when
judgeModel is explicitly configured; the direct-answer shortcut is kept only
for the implicit case (no judgeModel, judge defaults to panel[0]).
2026-07-07 21:48:02 -03:00
Diego Rodrigues de Sa e Souza
c1e3590da7 fix(providers): keep image/diffusion models out of the chat models catalog (#6457) (#6606) 2026-07-07 21:45:15 -03:00
Diego Rodrigues de Sa e Souza
ebdfe727a6 fix(test): replace tautology in playground-api-tab + make test-masking catch it (#6404) (#6603)
playground-api-tab.test.tsx's SSE test always took the disabled-button branch
(the fetch mock returned an empty model list) and asserted a tautology instead
of exercising the SSE path it claims to verify. The test now selects a real
model to enable Send, asserts it is actually enabled, and asserts the streamed
SSE content reached the response editor.

check-test-masking.mjs's tautology subcheck only compares base-vs-HEAD counts
within a PR's own diff and no-ops entirely outside PR context (no
GITHUB_BASE_SHA/REF) -- so a tautology merged once, or checked with a bare
local run, stayed invisible forever after. Added an always-on absolute-floor
scan (scanBareTautologies/countBareTautologies) over every tracked test file,
scoped to the bare expect(true).toBe(true)/assert.equal(1,1) patterns that
have zero legitimate uses in this codebase -- deliberately excluding
assert.ok(true), which has ~15 pre-existing verified-legitimate
try/catch-fallback uses and stays on the lenient diff-only path.
2026-07-07 21:18:18 -03:00
Diego Rodrigues de Sa e Souza
f570960958 fix(oauth): persist and reuse rotated Codex OAuth refresh token (#6352) (#6602) 2026-07-07 21:08:37 -03:00
Diego Rodrigues de Sa e Souza
c51eed786c fix(resilience): thread connection snapshot into headroom Codex quota fetch (#6379) (#6600)
orderTargetsByHeadroom already loaded the per-connection DB snapshot (with
decrypted credentials) via expandTargetsByQuotaAwareConnections, but discarded
it before calling getSaturation. For Codex, fetchCodexSaturation forwards
straight to fetchCodexQuota(connectionId, connection), which needs the
connection object (or a prior registerCodexConnection() call that never
happens before headroom ranking runs) to read accessToken. Without it,
fetchCodexQuota returned null for every candidate, saturation failed open to
0 across the board, and headroom ranking fell back to the original combo
order regardless of actual free quota.

getSaturation() and the headroom SaturationFetcher seam now accept and thread
the loaded connection snapshot through to fetchCodexQuota.

Regression guard: tests/unit/headroom-codex-quota-snapshot-6379.test.ts
(seeds two real Codex connections in a throwaway SQLite DB with a fake
upstream fetch, confirms RED on unfixed code, GREEN after the fix).
2026-07-07 21:02:19 -03:00
Diego Rodrigues de Sa e Souza
6d649d3d3f fix(dashboard): size the web-session cookie modal to fit on 1080p (#6265) (#6601) 2026-07-07 21:01:45 -03:00
Diego Rodrigues de Sa e Souza
cc5f596b5f fix(logger): tolerate write to removed DATA_DIR so tests don't crash on teardown (#6360) (#6599) 2026-07-07 21:01:11 -03:00
Diego Rodrigues de Sa e Souza
c06392c533 fix(providers): include custom models in Free Provider Rankings filters (#6368) (#6598) 2026-07-07 21:00:41 -03:00
Diego Rodrigues de Sa e Souza
d76153c7bb fix(providers): stop cloudflare-ai from silently dropping image content parts (#6390) (#6597) 2026-07-07 20:59:24 -03:00
Diego Rodrigues de Sa e Souza
6812b62f4a docs(changelog): add missing #6304 and #6240 bug-fix bullets to v3.8.47 (#6596) 2026-07-07 20:50:11 -03:00
Chirag Singhal
687a5aefc0 fix(providers): reject image-only models on /v1/chat/completions with clear error (#6457) (#6525)
fix(providers): reject image-only models on /v1/chat/completions with a clear error (#6457) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:36:41 -03:00
Chirag Singhal
454d58a41d fix(providers): honor fusion minPanel=1 and surface per-member failures in fusion 503 (#6454) (#6521)
fix(providers): honor fusion minPanel=1 and surface per-member failures in fusion 503 (#6454) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:36:36 -03:00
Chirag Singhal
1b6a1f08c7 fix(api): return 415 when /v1/chat/completions receives non-JSON Content-Type (#6414) (#6513)
fix(api): return 415 on /v1/messages for non-JSON Content-Type via requireJsonContentType middleware (#6414) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:36:32 -03:00
Chirag Singhal
fc8459faa3 fix(autoCombo): exclude paid models from fusion candidate pools when hidePaidModels=true (#6328) (#6550)
fix(autoCombo): exclude paid-tier auto/* ids from the catalog when hidePaidModels=true (#6328). Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:19:43 -03:00
Chirag Singhal
d180ac1244 fix(dashboard-api): apply hidePaidModels to /api/models + openrouter-catalog + test endpoints (#6328) (#6552)
fix(dashboard-api): apply hidePaidModels to /api/models + openrouter-catalog + test endpoints (#6328). Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:19:17 -03:00
Chirag Singhal
e8b5aefb5a fix(compression): surface fallback reasons in preview response (#6461) (#6519)
fix(compression): surface fallback reasons in preview response (#6461). Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:17:34 -03:00
Chirag Singhal
8407a24aef fix(backup): exclude paid models from JSON export/backup when hidePaidModels=true (#6328) (#6551)
fix(backup): exclude paid models from JSON export/backup when hidePaidModels=true (#6328) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:10:41 -03:00
Chirag Singhal
1438bfb509 fix(models): apply hidePaidModels to synced/custom/alias-backed/managed-fallback loops (#6328) (#6549)
fix(models): apply hidePaidModels to synced/custom/alias-backed/managed-fallback loops (#6328) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:10:36 -03:00
Chirag Singhal
529ebde7a3 fix(api): add explicit HEAD handler for /v1/models to prevent ~6s hang (#6400) (#6517)
fix(api): add explicit HEAD handler for /v1/models to prevent ~6s hang (#6400) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:10:31 -03:00
Chirag Singhal
1a87c90ff7 fix(providers): fail fast on empty auto-combo pool instead of 15s timeout (#6458) (#6546)
fix(providers): fail fast on empty auto-combo pool instead of 15s timeout (#6458). Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:08:51 -03:00
Chirag Singhal
e242321f5c fix(compression): honor UI-toggled engines in stackedPipeline dispatch + surface substitution (#6463) (#6534)
fix(compression): honor UI-toggled engines in stackedPipeline dispatch + surface substitution (#6463). Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:08:27 -03:00
Diego Rodrigues de Sa e Souza
fd4133df82 fix(providers): spawn Auggie CLI with shell:true on win32 (#6304) (#6510)
* fix(providers): spawn Auggie CLI with shell:true on win32 (#6304)

* chore: sync CHANGELOG to release tip (#6510; bullet re-added at merge)
2026-07-07 20:08:16 -03:00
Chirag Singhal
3aeb87be7b fix(api): return 400 for missing/invalid messages before model resolution (#6402) (#6515)
fix(api): return 400 for missing/invalid messages before model resolution (#6402). Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:07:48 -03:00
Diego Rodrigues de Sa e Souza
9450e03b1e fix(api): exempt test-model requests from Output Styles injection (#6240) (#6511)
* fix(api): exempt test-model requests from Output Styles injection (#6240)

Root cause: handleChatCore's Phase 4A Output Styles injection (chatCore.ts)
was gated only by the operator's global compression.enabled switch,
independent of the per-request x-omniroute-compression header. The
dashboard 'Test model' action (modelTestRunner.ts) never sent that header,
so a globally-enabled Output Style (e.g. 'Ultra terse') always leaked its
system-prompt injection into a plain connection test.

Fix: skip Output Styles injection when the request explicitly opts out via
x-omniroute-compression: off, and always send that header from
buildInternalChatRequest / buildInternalRerankRequest.

Regression guard: tests/integration/test-model-compression-off-6240.test.ts,
tests/unit/model-test-runner-compression-off-6240.test.ts

* chore: sync CHANGELOG to release tip (#6511; bullet re-added at merge)
2026-07-07 20:07:30 -03:00
Chirag Singhal
8f0447a54d fix(providers): size AddApiKeyModal for 1080p — drop inner max-h cap, widen to lg (#6265) (#6526)
fix(providers): size AddApiKeyModal for 1080p (#6265). Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:07:07 -03:00
Chirag Singhal
1ba814799f fix(api): JSON 404 for unknown /anthropic/*, /v1beta/*, /openai/*, /metrics, /debug, /.env (#6405 follow-up) (#6516)
fix(api): JSON 404 for unknown root routes /anthropic/*, /openai/*, /metrics, /debug, /.env (#6405 follow-up) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 20:02:26 -03:00
Chirag Singhal
07eb2ecdd9 fix(providers): enrich model_cooldown 429 body with retry_after ISO + credential count (#6460) (#6523)
fix(providers): enrich model_cooldown 429 body with retry_after ISO + credential count (#6460). Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 19:49:57 -03:00
Chirag Singhal
5e5fb61fcc feat(plugins): add langfuse plugin (#6577)
feat(plugins): add langfuse example plugin Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 19:32:28 -03:00
Chirag Singhal
18d0659426 fix(tests): replace expect(true) tautology in playground-api-tab (#6404) (#6548)
fix(tests): replace expect(true) tautology in playground-api-tab (#6404) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 19:32:24 -03:00
Chirag Singhal
da841f1a16 docs(readme): cross-link CodeWebChat as editor-side companion (#6189) (#6547)
docs(readme): cross-link CodeWebChat as editor-side companion (#6189) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 19:32:19 -03:00
Chirag Singhal
5ab442fcd3 fix(providers): warn when config.judgeModel is set on a non-fusion combo (#6455) (#6532)
fix(providers): warn when config.judgeModel is set on a non-fusion combo (#6455) Integrated into release/v3.8.47. (thanks @chirag127)
2026-07-07 19:32:15 -03:00
Diego Rodrigues de Sa e Souza
58bd527bb9 fix(resilience): recoverable 403 for no-credential providers (#6315) (#6508)
fix(resilience): recoverable 403 for no-credential providers (#6315). Integrated into release/v3.8.47.
2026-07-07 18:34:34 -03:00
Diego Rodrigues de Sa e Souza
f686e97d6c fix(api): remove duplicate origin check causing LAN 403 on health-autopilot actions (#6277) (#6507)
fix(api): remove duplicate origin check causing LAN 403 on health-autopilot actions (#6277). Integrated into release/v3.8.47.
2026-07-07 18:14:40 -03:00
Diego Rodrigues de Sa e Souza
de9d748dac fix(pricing): persist sync status across module instances (#6325) (#6505)
fix(pricing): persist sync status across module instances (#6325). Integrated into release/v3.8.47.
2026-07-07 18:04:59 -03:00
Diego Rodrigues de Sa e Souza
318b0b01d2 fix(cli): surface a diagnostic instead of a silent hang on serve readiness timeout (#6321) (#6504)
fix(cli): surface a diagnostic instead of a silent hang on serve readiness timeout (#6321). Integrated into release/v3.8.47.
2026-07-07 17:46:07 -03:00
Diego Rodrigues de Sa e Souza
359fc03c22 fix(providers): strip reasoning_effort/reasoning from grok-cli requests (#6288) (#6503)
fix(providers): strip reasoning_effort/reasoning from grok-cli requests (#6288). Integrated into release/v3.8.47.
2026-07-07 17:20:25 -03:00
Diego Rodrigues de Sa e Souza
3a1658d070 fix(providers): stop Antigravity false quota-exhausted (#6295) (#6502)
fix(providers): stop Antigravity false quota-exhausted (#6295). Integrated into release/v3.8.47.
2026-07-07 17:07:13 -03:00
Diego Rodrigues de Sa e Souza
eefb5097f7 chore(release): sync main (v3.8.46 close) into release/v3.8.47 — parallel-cycle sync-back 2026-07-07 15:45:55 -03:00
Diego Rodrigues de Sa e Souza
1eae976b28 fix(release): v3.8.46 closing — proxy random via crypto.randomInt (CodeQL #698/#699) + date [3.8.46]
Post-release closing fixes: crypto.randomInt for proxy-pool random rotation (silences CodeQL js/insecure-randomness #698/#699) + date the [3.8.46] CHANGELOG section. See PR #6580.
2026-07-07 15:45:14 -03:00
Diego Rodrigues de Sa e Souza
9f66316c4e feat(quality): validate-release-green --full-ci — reproduce the ci.yml static gate set (P0) (#6583)
* feat(quality): validate-release-green --full-ci reproduces the ci.yml static gate set

The curated HARD/DRIFT lists in validate-release-green were a hand-maintained
subset — v3.8.46 leaked 11 static base-reds (route-validation:t06, docs-symbols,
bundle-size --ratchet, test-masking, file-size, …) to the release PR because they
live only in the ci.yml gate jobs, costing ~2h of layered CI. --full-ci reads
ci.yml itself and runs every npm run check:* / lint from the lint / quality-gate /
quality-extended / docs-sync-strict / pr-test-policy jobs (-- ratchet flags
preserved; test-masking against GITHUB_BASE_REF=main; skips pr-evidence +
codeql-ratchet which can't run in a local working-tree pre-flight). Reading from
ci.yml keeps the set current as gates are added. Also wired into
nightly-release-green so a static base-red opens a tracking issue the night it
lands. Regression guard: +5 extractCiGates cases (18/18 pass).

* chore(quality): add 3 covering tests to stryker tap.testFiles (pre-existing drift on release/v3.8.47)

check:mutation-test-coverage (fast-gates) flagged 3 unit tests that cover mutated
modules but were missing from stryker.conf.json tap.testFiles — pre-existing drift
on release/v3.8.47, surfaced by this PR's CI. Adds codex-quota-selection-hydration
(auth.ts), combo-roundrobin-compat-fallback-6238 (circuitBreaker.ts), and
combo-rr-fallback-advance-948 (rrState.ts) so their mutant kills count.
2026-07-07 15:44:59 -03:00
Diego Rodrigues de Sa e Souza
d545719956 chore(release): sync main (v3.8.46 close) into release/v3.8.47 — parallel-cycle sync-back 2026-07-07 14:41:00 -03:00
Diego Rodrigues de Sa e Souza
92715c8f2c Release v3.8.46
Release v3.8.46. Full changelog: CHANGELOG.md → [3.8.46]. Contributor attribution in the CHANGELOG entries.
v3.8.46
2026-07-07 13:14:06 -03:00
Diego Rodrigues de Sa e Souza
b1d5f202c7 chore(release): open v3.8.47 development cycle
Parallel-cycle model (2026-07-04): cut from the frozen release/v3.8.46 tip at the
v3.8.46 release freeze so development continues immediately on v3.8.47 while the
captain closes v3.8.46. Bumps package.json x3 + openapi + lockfile to 3.8.47, adds
the '## [3.8.47] — TBD' living CHANGELOG section, and syncs the 42 i18n mirrors.
Closing v3.8.46 fixes reach this branch via the Phase 5 sync-back.
2026-07-07 07:58:13 -03:00
Diego Rodrigues de Sa e Souza
8fb3a2c379 chore(quality): v3.8.46 pre-flight — type test anys, rebaseline cycle drift, allowlist #6303 test consolidation
- Type 12 no-explicit-any errors in 3 new test files (real types, no masking):
  chat-early-schema-validation-6412, models-catalog-envkey-6406, zed-provider.
- Suppress MitmProxyTab.tsx no-html-link-for-pages (false positive: the link is
  an /api/settings/mitm cert download, an API route not a Next page).
- Allowlist tests/integration/v1-contracts-behavior.test.ts net -2 asserts: #6303
  moved embedding/image shape coverage to models-catalog-route + specialty tests.
- Rebaseline cycle drift measured on the release tip (captain fixes are net-zero,
  verified): cognitive 877->882, cyclomatic 2035->2050, file-size proxies/chat/
  ApiManagerPageClient/ProxyRegistryManager + models-catalog-route testcap +5.
- Fix stale CLAUDE.md: no-explicit-any is error (not warn) in tests/ since #6218.
2026-07-07 07:42:42 -03:00
Diego Rodrigues de Sa e Souza
ceff7054b1 fix(security): unbiased crypto digits for the doubao synthetic device id (CodeQL js/biased-cryptographic-random)
randomNumericId builds a non-secret synthetic device/web id. The v3.8.45 switch
to crypto.getRandomValues closed js/insecure-randomness but 'cryptoByte % 10' is
biased (256 is not a multiple of 10), tripping js/biased-cryptographic-random.
Draw each digit by rejection sampling — discard bytes in the biased tail so the
remaining range divides evenly — giving a uniform distribution (verified) while
staying crypto-backed.
2026-07-07 07:42:12 -03:00
Diego Rodrigues de Sa e Souza
a533a312df fix(agentSkills): generator honors an absolute outputDir (#6366 regression)
#6366 switched the output base from path.resolve to path.join(process.cwd(),
outputDir) to keep Turbopack's static analyzer from tracing the project root.
path.join mangles an absolute outputDir (a tmp dir in the generator tests) into
cwd/tmp/…, so apply mode reported success while writing nothing at the expected
path. Guard with path.isAbsolute — absolute paths pass through, the relative
production case ('skills') keeps the Turbopack-friendly join form. The existing
agentSkills-generator suite is the regression guard (now 21/21).
2026-07-07 07:41:53 -03:00