Commit Graph

1199 Commits

Author SHA1 Message Date
Alex Chan
0fe1bb2390 fix(routing): preserve combo precedence and skip hidden models in alias resolver (#11107)
Validated on the combined batch board over tip 8a42aeeb: static gates clean (changelog, file-size 159 frozen, complexity 2621<=2774, cognitive 1181<=1223, dead-code 408<=416), typecheck:core clean, 107 focused tests green.

Combo precedence preserved when a requested name matches an existing combo or combo/* prefix, and hidden/disabled models are skipped during alias resolution (wildcard + mapped). model-alias-seed-fallback green. Related to #10124. Thank you @SCys!
2026-08-23 07:01:07 -03:00
Bob.Hou
1f6e781c4f feat(search): add context7 as a library-docs search and fetch provider (#11140)
Validated on the combined batch board + this branch: context7-provider 33/33 + search-registry 45/45 (propagated to 17 providers), docs-counts green (350 everywhere: PROVIDER_REFERENCE regenerated, SVGs, README, AGENTS.md, package.json, llm.txt + 42 mirrors synced), provider-consistency OK. Hardening reviewed: canonical isValidContext7LibraryId shared by normalizer+executor, byte-capped error bodies, validated baseUrl with public fallback, anonymous-tier quota sentinel, excluded from auto-select walks. Thank you @HouMinXi — 15 forge-review cycles show!
2026-08-23 02:24:01 -03:00
Bob.Hou
a255488817 fix(oauth): recover connections stuck on upstream 400 after token staleness (#11141)
Validated on the combined batch board + this branch: oauth-400-recovery + quota-connection-recovery 22/22; file-size gate green with the test/route.ts 1215 frozen entry (dated annotation for the +190 rebuilt-probe lines, owner-authorized). Unknown expiry + refresh token now means proactive refresh before probing, a hard 400 gets exactly one refresh+retry with fresh-token assertion, and the recovery tick clears stale error labels — the four dead-for-weeks antigravity connections from the production report would have self-healed. TDD with bug-injection proof on each leg. Thank you @HouMinXi!
2026-08-23 02:20:12 -03:00
Bob.Hou
dea5345397 fix(mcp): honor the mcp:connect carve-out in transport route guards (#11139)
Validated on the combined batch board over tip 17897cc3: gates clean (changelog, file-size 159 frozen, complexity 2628<=2774, cognitive 1184<=1223, dead-code 409<=416, provider-consistency 267/350/0), typecheck:core clean, 83/83 PR suites + neighbors green (mcp-route-scope-carveout 15 tests with bug-injection proof, management-auth-hardening per-route call-shape pinning). The route layer now honors the #9159 mcp:connect carve-out exactly like the policy layer — audit/audit-stats deliberately stay manage-only, oma_ tokens still require admin. Thank you @HouMinXi!
2026-08-23 02:18:06 -03:00
Paco Cartones
8d6870f96e fix(analytics): classify opencode-go as a flat-rate subscription (#11199)
Validated on the combined batch board over tip c92bd40b: static gates clean (changelog, file-size 158 frozen, complexity 2626<=2774, cognitive 1183<=1223, dead-code 409<=416), typecheck:core clean, 70 focused tests green (PR suites 49/49 + auth/combo neighbors 21/21).

opencode-go joins FLAT_RATE_SUBSCRIPTION_PROVIDER_IDS — cost analytics stop pricing a flat 0 subscription at metered aggregator rates (3.35 reported vs 0 actual). Same pattern as #10774. Fixes #11149. Thank you @pacocartones!
2026-08-23 01:24:28 -03:00
Rouzbeh†
c92bd40b88 perf(proxy): implement non-blocking async proxy log batching and performance optimizations (A, B, C, D) (#11182)
Validated on the combined batch board + this branch: perf-a-b-c-d + account-fallback-service 93/93, gates + typecheck clean. Owner approved the full bundle including item A (async proxy-log batching, 1s/100-item flush with an unref'd timer — reviewed the implementation: flush helper exists for shutdown wiring, buffered logs are the accepted tradeoff). B (lazy modals), C (O(1) alias maps), D (pre-compiled regex — this is also the entire content of #11187, being closed as subsumed) ride along. Conflict with the tip was only stale provider-count docs. Thank you @rqzbeh!
2026-08-23 01:07:32 -03:00
backryun
79c5bdf681 fix(release): repair v3.8.50 base-red tail after latest root lift (#10964)
Merged after conflict triage: the six base-red repair files (vi.json, opencode.ts JSDoc, context-manager test, the three webhook dispatcher tests, the uncloseai orphan-test rename) were already drained on the tip by today's #11130/#11157/#11160/#11113 — those hunks resolved to the tip shape. What lands is the production-fix set: GLM transport-aware Anthropic headers, Claude Code-compatible model-listing rejection, combo live-test single-probe, zero-cost Auto-Combo interval normalization, recovery-clearing union handling, LLMLingua real-path compare, macOS netstat PID discovery, AI Horde R2 strict public-host validation. Sweep of every touched test file: 243/243 green; typecheck + file-size clean. (guide-settings-route's 4 reds reproduce on the pure tip — pre-existing drift from #11079, not from here.) Thank you @backryun!
2026-08-22 23:09:16 -03:00
Xiangzhe
c018bb41a7 fix(catalog): declare GLM reasoning effort tiers (#10963)
Merged after conflict resolution in modelMetadataRegistry.ts: the tip's effortTiers chain (declared efforts → declared tiers → undefined-if-thinking-declared → codex extension) now carries this PR's GLM guard as the final-fallback override — GLM-family models without a provider-declared contract get the authoritative empty tier list instead of generic OpenAI tiers. GLM/ZCode suites 40/40 on the resolved branch. Closes #10962. Thank you @xz-dev!
2026-08-22 22:54:49 -03:00
Diego Rodrigues de Sa e Souza
3ef54fc55b feat(api): return every connection's snapshot under providers[] in om-usage json (#11192)
* feat(api): structured ?format=json for the self-service usage endpoint

GET /api/usage/om-usage already let any key read its own usage — personal
daily/weekly USD limits and the provider quota snapshot — but only as
text/plain, which a UI cannot parse safely. OmniCopilot issue #8 asks exactly
for this surface.

Adds ?format=json, returning the ApiKeyUsageLimitStatus + UsageSnapshot the
text is rendered from. Text and JSON share the same collectors
(collectUsageSnapshots, getApiKeyUsageLimitStatus), so the two can never
disagree about a number. The response is a discriminated union: a key without
allowUsageCommand (403) or an invalid key (401) returns
{ allowed:false, error:{message} }, distinct from allowed:true with empty
sections — the state a panel must render as "nothing learned yet", not a
refusal. Text form unchanged; without ?format the contract is untouched.

The endpoint was previously missing from API_REFERENCE.md; it now has a
section documenting both forms, the allowUsageCommand gate, and the
self-service auth model (caller's own key, not requireManagementAuth).

Regression guards in tests/unit/usage-command-json-format.test.ts (4 tests:
json shape, text default preserved, structured 403, sanitized 401 with no
stack trace). Existing internal-usage-command suite still 12/12.

* chore(changelog): correct the fragment to the real PR number (#11190)

* feat(api): return every connection's snapshot under providers[] in om-usage json

Closes #11191. buildUsageCommandJson picked a single snapshot via selectUsageSnapshot, so a panel could only ever show one provider. The collector already had them all — the single-pick is a presentation choice for a terminal. The JSON form now also returns the full UsageSnapshot[] alongside the selected provider, so a UI can render Codex / Claude / OpenCode side by side. The text form is untouched.

---------

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-22 22:39:56 -03:00
Diego Rodrigues de Sa e Souza
eb9fa33ee7 feat(api): structured ?format=json for the self-service usage endpoint (#11190)
* feat(api): structured ?format=json for the self-service usage endpoint

GET /api/usage/om-usage already let any key read its own usage — personal
daily/weekly USD limits and the provider quota snapshot — but only as
text/plain, which a UI cannot parse safely. OmniCopilot issue #8 asks exactly
for this surface.

Adds ?format=json, returning the ApiKeyUsageLimitStatus + UsageSnapshot the
text is rendered from. Text and JSON share the same collectors
(collectUsageSnapshots, getApiKeyUsageLimitStatus), so the two can never
disagree about a number. The response is a discriminated union: a key without
allowUsageCommand (403) or an invalid key (401) returns
{ allowed:false, error:{message} }, distinct from allowed:true with empty
sections — the state a panel must render as "nothing learned yet", not a
refusal. Text form unchanged; without ?format the contract is untouched.

The endpoint was previously missing from API_REFERENCE.md; it now has a
section documenting both forms, the allowUsageCommand gate, and the
self-service auth model (caller's own key, not requireManagementAuth).

Regression guards in tests/unit/usage-command-json-format.test.ts (4 tests:
json shape, text default preserved, structured 403, sanitized 401 with no
stack trace). Existing internal-usage-command suite still 12/12.

* chore(changelog): correct the fragment to the real PR number (#11190)

---------

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-22 22:23:17 -03:00
ggdayup
f3875759ac fix(memory): treat TokenRouter as system-must-be-first (live HTTP 400 confirmed) (#11114)
Validated on the combined batch board over tip 92ef3c71: static gates clean (changelog, file-size, complexity 2624<=2774, cognitive 1182<=1223, dead-code 411<=416), typecheck:core clean, focused tests green.

Companion to #11113 (consumer side): tokenrouter joins BUILTIN_PROVIDERS_SYSTEM_MUST_BE_FIRST — memory-system-first-6135 suite green. Live-confirmed 400 class documented in the body. Thank you @ggdayup!
2026-08-22 21:51:16 -03:00
Rouzbeh†
7246e5ac2d fix(bun): update Dockerfile.bun entrypoint and native bun:sqlite instantiation (#11039) (#11163)
Cherry-picked onto the current tip (authorship preserved), noise stripped. Validated on BOTH runtimes: bun test tests/unit/db-adapters/ 44/44 under the pinned Bun 1.3.14 (native bun:sqlite path), and node --test on the same suite 52 pass / 0 fail / 1 skip (Bun-only adapter skips under Node, as designed). Dockerfile.bun entrypoint now matches the standalone runner shape. Follow-up to #11039. Thank you @rqzbeh!
2026-08-22 20:24:21 -03:00
Rouzbeh†
5818cfb80f docs(cli): update opencode.ts JSDoc to reflect 128k context fallback (#11035) (#11157)
Cherry-picked the JSDoc commit onto the current tip (authorship preserved), stripping the stale generated-count noise files. Focused: opencode-v2-config-11070 2/2. Comments now match the 128k fallback shipped in #11035/#11054. Thank you @rqzbeh!
2026-08-22 20:07:11 -03:00
Reza Rezaei
7360ca4242 feat(redis): add configurable key namespace prefix (#11042)
Validated on the combined board over tip 80d931ae: quota-redis-store (incl. the KEY_PREFIX derivation test), local-redis-status and rate-limiter-redis-optional green, typecheck:core clean. One pre-merge fix pushed to the branch: docs/reference/ENVIRONMENT.md gained the REDIS_KEY_PREFIX row (env-doc-sync gate requires every .env.example var documented). Board note: the redis tests leave an ioredis retry handle open and hang the runner exit locally — assertions all pass; pre-existing pattern, not from this PR. Thank you @MeRezaRezaei!
2026-08-22 18:56:45 -03:00
Reza Rezaei
e15af18d17 fix(kimi): point kimi-web to international www.kimi.ai (#11045)
Validated on the combined board over tip 80d931ae: kimi suites green (executor-kimi-web, kimi-partner-aff-links, token-health-check-kimi 33 assertions), vitest providerPageHeaderKimiPartnerLink green, typecheck:core clean. Audited the diff: only kimi-web switches to the international www.kimi.ai (Connect-RPC base, website, auth hints); kimi-coding / kimi-coding-apikey affiliate links stay on kimi.com as intended — asserted by the updated tests. Owner approved merge without the VPS smoke. Thank you @MeRezaRezaei!
2026-08-22 18:55:23 -03:00
Rouzbeh†
aa12873686 fix(providers): remove Hack Club AI provider (#11118) (#11123)
Cherry-picked the author's cleaned single-commit head onto the current tip. One fix applied pre-merge: the removal migration collided at number 161 with today's config_audit_log migration (#11103) — renumbered to 162_remove_hackclub_provider.sql. Focused tests: remove-hackclub-11118 + provider-metrics-deleted-provider green; check:provider-consistency OK (266/348/0). Provider removal requested by Hack Club maintainers (#11118). Thank you @rqzbeh!
2026-08-22 16:26:38 -03:00
Dizzle
c89fc6ba2a feat(providers): let operators add per-provider error rules via settings (#11104)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Operator-declared per-provider error rules via settings, consulted before the built-ins; the allowlist bypass is correct — declaring a rule is itself the opt-in, and no provider-specific rule is hardcoded. Thank you @maxmad64bis!
2026-08-22 14:40:35 -03:00
Dizzle
84c9dfdd2c fix(config-audit): persist config audit log to SQLite with retention (#11103)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Config-audit survives restarts with bounded growth (migration 161 + OR IGNORE seed, retention wired into runAutoCleanup); route cabling deliberately out of scope. Thank you @maxmad64bis!
2026-08-22 14:40:09 -03:00
Dizzle
f3b190ba3e fix(providers): reject silent validation degradation with 400 and rejected keys (#11101)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Strict schema + {sanitized, rejected} DB boundary — silent validation degradation now answers 400 with the offending keys. Caller audit done: only the providers write path consumes the sanitizers. Thank you @maxmad64bis!
2026-08-22 14:39:58 -03:00
Dizzle
78b4082361 fix(autopilot): show real suggestion count and link dashboard (#11102)
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.

Real suggestionCount replaces the conflated link count (deprecated alias kept), dashboard deep-link fixed. Thank you @maxmad64bis!
2026-08-22 14:39:22 -03:00
Diego Rodrigues de Sa e Souza
b6412c6fed fix(command-code): use the documented /provider/v1 chat endpoint (#10265) (#11072)
5 — Fecha #10265: chat do command-code migra do endpoint CLI-only /alpha/generate (version-gated + proxy-blocked para callers externos) para o documentado /provider/v1/chat/completions (OpenAI format). Removido o envelope CLI reverse-engineered (config/memory/taste/skills + headers CLI-impersonation), substituído por passthrough OpenAI plano com normalização de model id vendor-prefixed (#10809), clamp de max_tokens (#5166), sanitização de reasoning_effort. commandCode.ts 1037→171 linhas.
Validado no worktree board sobre tip: typecheck:core limpo; 175/175 testes focados (command-code executor/vision/usage/maxtokens/user-array/validation-specialty/responses-handler/provider-models-scoping); changelog-integrity/file-size/complexity/cognitive todos OK. TDD RED→GREEN documentado.
2026-08-21 22:16:45 -03:00
Rouzbeh†
7ddbaf69a4 feat(cli): add native Bun backend support and Dockerfile.bun (#11039)
4 — Suporte de backend nativo Bun + Dockerfile.bun multi-stage + fallback dinâmico de driver SQLite (better-sqlite3 prioritário sob Bun, bun:sqlite fallback; Node preservado) + correção de estabilidade do DAST CI smoke.
Validado a fundo (worktree board sobre tip): bun-support 4/4, typecheck:core limpo, dashboard-typecheck OK (220 dentro do baseline), open-sse-typecheck OK (5 pré-existentes), gate de runtime OK sob Node, changelog-integrity OK, file-size/complexity/cognitive/dead-code OK. Verificado que o driver preserva a cadeia Node/falback conforme AGENTS.md; teste bun-support presente. Baselines de typecheck removidos são ratchet honesto (erros não existem mais).
OBS: destravei 2 base-reds do tip neste turno (push direto 7ffa3ef): movi o changelog fragment da #11050 da seção inválida breaking/ para fixes/, e rebaselinei AddApiKeyModal 1067->1073 (crescimento da #11056). Sem isso a #11039 e o resto da fila ficariam vermelhos.
2026-08-21 21:28:43 -03:00
Rouzbeh†
8643e0f57c fix(cli): default limit.context to 128k when unknown in OpenCode configs (#11035, #11032) (#11054)
5 — OpenCode config: limit.context default 128k quando metadata de catálogo desconhecida (#11035/#11032); limit emitido por model entry. TDD, suíte aberta limpa.
2026-08-21 21:06:21 -03:00
Paco Cartones
f968496cc6 fix(gamification): validate leaderboard limit/offset before the SQLite bind (#11059)
5 — LIMIT negativo = "sem limite" no SQLite: ?limit=-1 retornava a leaderboard inteira em endpoint management autenticado; ceil por Math.min só no upper. Duas camadas: route rejeita não-inteiro/fora de range com 400 (mesmo contrato de parseListLimit), getTopN clampeia como backstop defense-in-depth + exporta LEADERBOARD_MAX_LIMIT. TDD red→green, 5 casos novos, 84/84 suíte gamification. Fecha #11058.
2026-08-21 20:59:57 -03:00
Dizzle
1c920eb8b8 fix(webhooks): remove 3 declared-but-never-emitted ghost events (#11050)
5 — Remove 3 webhook events declarados mas nunca emitidos (provider.error/recovered, combo.switched): union 7→4, z.enum com 400 em ghost values (era z.string pass-through). Breaking intencional + testado. TDD 3/3, i18n B-pattern (42 __MISSING__). Base-red #9985 inherited.
2026-08-21 20:54:51 -03:00
Diego Rodrigues de Sa e Souza
eb4fd74b13 fix(security): close remaining v3.8.50 advisories (batch 2 — 11 findings) (#11040)
5 — Fecha 11 achados restantes das advisories de segurança do v3.8.50 (batch 2), TDD. UNSTABLE é o base-red #9985 já rastreado.
2026-08-21 20:28:16 -03:00
Diego Rodrigues de Sa e Souza
861ac69e4b fix(providers): validate Dify keys against native /v1/chat-messages endpoint (#11002) (#11065)
5 — Fix do dono com TDD. Estado committed+pushed limpo (hold-vivo cedido por instrução direta do operador).
2026-08-21 20:27:36 -03:00
Diego Rodrigues de Sa e Souza
484cb6e562 fix: add static model catalog for v0-vercel-web web-cookie provider (#10990) (#11066)
5 — Fix do dono com TDD. Estado committed+pushed limpo (hold-vivo cedido por instrução direta do operador).
2026-08-21 20:27:33 -03:00
mymusicmyspace
3caa59107e feat(sse): add STRICT_ZERO_COST opt-in free-access policy (#10965)
5 — freeAccessPolicy "strict" opt-in (default off): verifica candidatos de auto-combo contra estado de quota ao vivo + segurança econômica por conexão antes do dispatch (fail-closed — estado desconhecido/stale/incompleto é excluído). Zero mudança de comportamento com o default "off". 82 testes focados, eslint/prettier/typecheck limpos, docs em docs/routing/STRICT_ZERO_COST.md.
2026-08-21 14:59:11 -03:00
Jonathan Bailey
00dfdadf93 fix(combo): resolve effort variants via base model capabilities (#11034)
5 — Variantes de modelo com sufixo de effort (ex: model-max/model-xhigh) são sintetizadas no catálogo a partir de supportedThinkingEfforts do modelo base, sem linha própria no registry — getResolvedModelCapabilities resolvia NULL para tool/vision/context, o que fazia combos com tools reordenar silenciosamente essas variantes para trás. Fix: quando todas as fontes diretas falham, resolve as capacidades a partir do modelo base após strip do sufixo. TDD, 65 testes focados verdes.
2026-08-21 14:58:53 -03:00
Ravi Tharuma
137e49e393 feat(search): first-class X Search via SuperGrok x_search (#10988)
5 — Provider x-search de primeira classe (SuperGrok/xAI x_search) em POST /v1/search e MCP omniroute_x_search. Fallback de credenciais xai-oauth→xao→xai; distinto de web search e do X Developer MCP.

Reconciliado com o release tip (que já incluía #10981 "skip catalog-default SearXNG" deste mesmo lote): merge trouxe 5 conflitos reais de contagem gerada (llm.txt/README.md/AGENTS.md/PROVIDER_REFERENCE.md/SVGs/46 mirrors i18n, todos verificados como bump puro 347→348, sem perda de conteúdo do HEAD) + 1 conflito real de mergeable=CONFLICTING.

Durante a validação, os 3 testes novos de SearXNG expuseram um bug real de interação com #10981: `isUnconfiguredLoopbackSearchProvider()` checava o baseUrl ESTÁTICO do catálogo em vez do baseUrl efetivo (após override de `provider_options.baseUrl` ou `providerSpecificData.baseUrl` da conexão), então QUALQUER request a searxng-search — mesmo com override customizado — era rejeitado como se fosse o default não-configurado. Corrigido em `open-sse/handlers/search.ts` (resolve o baseUrl efetivo via `resolveSearchBaseUrl()` antes do skip-check, tanto para o provider primário quanto o alternate). Um teste do próprio #10988 que assumia o comportamento pré-#10981 (default localhost:8888 sempre atendido) foi atualizado para refletir o comportamento já mesclado e intencional (503 quando não configurado).

Validação completa: typecheck limpo, 70/70 testes unit (search-route/search-registry/x-search-provider/searxng-loopback-default), 24/24 vitest MCP, 14/14 integration (search-providers-catalog), lint limpo nos arquivos tocados, docs-counts-sync OK (2 drifts soft pré-existentes, não relacionados), gates estáticos (file-size/complexity/cognitive/dead-code/changelog) todos OK.
2026-08-21 14:16:42 -03:00
Ravi Tharuma
9459546621 fix(providers): 401 when active terminal grok-cli credentials expire (#10969) (#10971)
5 — getProviderCredentials() descartava conexões isActive:true com testStatus expired/banned/credits_exhausted e retornava null, virando 404 model_not_found mesmo com o modelo listado em /models. Agora retorna o sentinel allExpired quando toda conexão ativa é terminal, resultando em 401 com hint de reconexão. Testes de auth-terminal-status/sse-auth/chat-helpers verdes. Fecha #10969, follow-up de #7611.
2026-08-21 14:00:46 -03:00
Ravi Tharuma
fefca17762 fix(db): pause call-log rotate on SQLITE_CORRUPT (#10979)
5 — Em SQLITE_CORRUPT/pager malformado durante rotação de call-log, pausa novas rotações em vez de retry de DELETE contra arquivo quebrado; /api/db/health reporta integrity_check_failed. Não faz REINDEX automático (inseguro em single-writer live). 4/4 testes novos + suíte irmã verde. Fecha o gap de #10736.
2026-08-21 14:00:39 -03:00
Ravi Tharuma
30e20c6b60 fix(startup): log when credential health check is disabled (#11016) (#11021)
5 — initCredentialHealthCheck() agora retorna se o sweep está armado; boot loga "disabled" quando OMNIROUTE_DISABLE_CREDENTIAL_HEALTH_CHECK está setado, em vez de sempre "started". 3 testes verdes, comportamento do sweep inalterado. Fecha #11016.
2026-08-21 14:00:27 -03:00
Diego Rodrigues de Sa e Souza
054cfae044 fix(cli): always emit limit.output in OpenCode config (#10940) (#11010)
5 — Fix(#10940): OpenCode config rejeitava modelos sem metadata de catálogo por faltar limit.output (campo obrigatório no schema v1). Agora sempre emite limit com fallback (catálogo → override → 8192). TDD RED→GREEN; teste pré-existente que codificava o bug corrigido. UNSTABLE é o base-red inherited #9985.
2026-08-21 13:57:56 -03:00
Diego Rodrigues de Sa e Souza
60829241fd fix(security): close 4 STILL-REAL advisory findings (ACP RCE hardening, db-backups tier, uppercase authz bypass, spawn-veto drift) (#11028)
5 — 4 achados STILL-REAL de advisories de segurança, cada um com TDD (RED→GREEN) e crédito ao reporter original: ACP RCE hardening (resolveVersionProbe), db-backups Tier-2 allowlist, uppercase authz bypass (matcher case-insensitive), spawn-veto drift (chatgpt-web-codex-doctor). typecheck/lint limpos, suíte authz/acp/cors verde. UNSTABLE é o base-red inherited #9985, já documentado no corpo da PR.
2026-08-21 13:57:42 -03:00
SB Yoon
c130f2aa1c feat(providers): Cursor PKCE login with Bearer quota, auto router, and empty-turn errors (#9909)
5 — Cursor PKCE login com Bearer quota, auto router e empty-turn errors. Feature completa e testada (11 arquivos de teste, 133 testes focados, todos verdes).

**Validação (worktree combinado `.claude/worktrees/fix-9909`, board sobre `origin/release/v3.8.50`):**
- 3 conflitos reais resolvidos: `config/quality/eslint-suppressions.json` (aditivo), `open-sse/config/providers/registry/cursor/index.ts` (dedup de 208 entradas de catálogo, 0 IDs duplicados verificado), `open-sse/executors/cursor.ts` (imports aditivos).
- `npm run typecheck:core`: limpo.
- `check-changelog-integrity`, `check-file-size`, `check-complexity` (2615/2774), `check-cognitive-complexity` (1175/1223), `check-dead-code` (410/416): todos OK.
- `check-public-creds`: 1 entrada obsoleta pré-existente na allowlist (`copilot-m365-web.ts:330`), já presente no tip da release — não é desta PR.
- `npm run lint`: 0 errors (5 warnings pré-existentes).
- Testes focados (`cursor-agent-cli-version`, `cursor-available-models`, `cursor-catalog-combo-compat`, `cursor-errors-classify`, `cursor-login-pkce`, `cursor-model-effort-suffix-7289`, `cursor-streaming`, `cursor-token-extractor`, `cursor-token-refresh-wiring`, `cursor-usage-fetcher`, `empty-stream-no-content-8649`): 133/133 verdes.
- Corrigido durante a validação: 1 teste novo da própria PR (`cursor-model-effort-suffix-7289.test.ts`, "splits effort off legacy grok- ids") colidia com `CURSOR_MODEL_ALIASES` já mesclado na release (mapeia `grok-4.5-high` → `cursor-grok-4.5-high` antes do fallback legado rodar); ajustado para usar um id não-aliasado (`grok-3-high`) que de fato exercita o fallback — commit `68b58ed`.

Obrigado pela contribuição, @yansigit — feature robusta com boa cobertura de testes.
2026-08-21 10:28:01 -03:00
Diego Rodrigues de Sa e Souza
ad3f7bc008 fix(ci): clear base-reds on release/v3.8.50 (ESLint / dead-code / vitest) (#9985) (#10778)
Reconciliado com a release e revalidado: typecheck:core, check:dead-code (410 real vs 416 na baseline resolvida — a PR mede corretamente sua própria melhoria), lint (adicionei 1 entrada de suppression para GrokBuildToolCard.tsx, arquivo mergeado depois que esta branch nasceu, 2 violações novas de react-hooks/set-state-in-effect não capturadas pela contagem original), complexity, cognitive-complexity, file-size, changelog-integrity e 11/11 testes do tieredRotation todos verdes. Drena 3 dos 8 hard failures do #9985. Obrigado!
2026-08-21 09:27:06 -03:00
Dizzle
1f09e2f9b3 feat(rankings): report what a free provider actually served (#10926)
Validado no worktree combinado: mesmos gates + testes focados verdes. Extensão opt-in bem desenhada sobre #10909 (dimensão de uso real via call_logs). CI vermelho é o base-red já rastreado em #9985.
2026-08-21 08:25:23 -03:00
Mr White
28924fe05b fix(models): enforce a synced model's real context window and default effort immediately (#10957)
Validado no worktree combinado: mesmos gates + testes focados verdes. Fix bem medido (context window real vs anunciado divergindo por até 24h para modelos sincronizados fora do ciclo). CI vermelho é o base-red já rastreado em #9985.
2026-08-21 08:25:14 -03:00
Xiangzhe
6ec6940314 fix(catalog): preserve provider effort tiers (#10953)
Validado no worktree combinado: mesmos gates + teste focado verde. Preserva effort_tiers declarados pelo provider (Kimi k3) em vez de substituir pela lista canônica genérica. CI vermelho é o base-red já rastreado em #9985.
2026-08-21 08:25:10 -03:00
Reza Rezaei
6efb01a957 feat(sse): add kimi web token lifecycle manager, rolling auto-refresh and 401 recovery (#10944)
Validado no worktree combinado: typecheck:core, changelog-integrity, complexity, cognitive-complexity, file-size, lint e 52 testes focados (kimi-jwt, kimi-credentials-extract, kimi-token-refresh, kimi-web-401-retry, provider-refresh-token-route, token-health-check-kimi) todos verdes. Implementação sólida e bem testada de ciclo de vida de token para Kimi Web. CI vermelho é o base-red já rastreado em #9985. Obrigado!
2026-08-21 04:25:56 -03:00
Dizzle
65dcb1d1ed feat(resilience): stop retrying sibling connections after an IP-bucketed 429 (#10920)
Validado no worktree combinado: typecheck:core, changelog-integrity, complexity, cognitive-complexity, file-size, lint e testes focados (egress-ip-lock-10880, egress-lock-allowlist-10880, proxy-logs-egress-lookup-10880) todos verdes. Otimização de resiliência bem fundamentada (cooldown de conexões compartilhando IP de egress após 429 do allowlist). CI vermelho é o base-red já rastreado em #9985. Obrigado!
2026-08-21 04:25:22 -03:00
Dizzle
4c0b54abc1 feat(rankings): expose provider reliability alongside free provider rankings (#10909)
Validado no worktree combinado: typecheck:core, changelog-integrity, complexity, cognitive-complexity, file-size, lint e testes focados (freeProviderRankings-filters) todos verdes. Feature aditiva bem documentada (campo reliability nos rankings). CI vermelho é o base-red já rastreado em #9985. Obrigado!
2026-08-21 04:23:17 -03:00
Reza Rezaei
e4a24173af feat(auth): add OIDC password-login disabler when OIDC is active (#10889)
Validado no worktree combinado: typecheck:core, changelog-integrity, complexity, cognitive-complexity, file-size, lint e testes focados (auth-login-route, login-bootstrap-route, feature-flags-settings — corrigi EXPECTED_FEATURE_FLAG_COUNT 51→52 fix-in-place, novo flag adicionado sem atualizar a própria contagem) todos verdes. CI vermelho é o base-red já rastreado em #9985. Obrigado!
2026-08-21 04:18:55 -03:00
Nguyen Thanh Dat
4fa204de68 fix(relay): share one private-host guard across the three relay workers (#10941)
Reconciliado com #10935 (já mergeada) — mesclado o guard inline recém-mergeado com a extração para `privateHostname.ts` deste PR, mantendo a intenção original: os 3 workers de relay agora usam a MESMA função compartilhada. Validado: lint limpo, 49/49 testes focados passando (incluindo verificação de que nenhum worker mantém cópia inline). Hardening de segurança real e bem documentado (4 gaps de bypass: `::`, `localhost.`, `::127.0.0.1`, `feb0::1`). CI vermelho é o base-red já rastreado em #9985. Obrigado!
2026-08-21 04:17:25 -03:00
Nguyen Thanh Dat
6eaa737333 fix(relay): resolve x-relay-path through the shared guard in the CF worker (#10935)
Validado no worktree combinado do lote: typecheck:core, changelog-integrity, complexity, cognitive-complexity, file-size e 163 testes focados (incluindo cloudflare-relay-path-ssrf) todos verdes. Fix de segurança real e bem documentado (SSRF via concatenação pós-validação no Cloudflare relay worker). CI vermelho é o base-red já rastreado em #9985. Obrigado!
2026-08-21 04:12:53 -03:00
Rouzbeh†
354d3a2741 fix(models): persist apiFormat, targetFormat, and supportsVision overrides for catalog models (#10871) (#10898)
Reconciliado com a release (mesmo drift de typecheck-baseline/glm.ts/fetchTimeout.ts/stryker.conf.json que os PRs irmãos) e corrigi o `no-explicit-any` no teste novo (o tipo `ModelCompatOverride` já expõe apiFormat/targetFormat/supportsVision — o cast era desnecessário). Validado: lint limpo, 2/2 testes focados passando. Fix real e bem documentado (persistência de overrides de protocolo por modelo). CI vermelho é o base-red já rastreado em #9985. Obrigado!
2026-08-21 03:56:57 -03:00
Rouzbeh†
467a80428c fix(model): return model_not_found for unrecognized prefix models when provider is inactive (#10856) (#10894)
Reconciliado com a release (drift em typecheck-baseline.json/glm.ts/fetchTimeout.ts/stryker.conf.json — a tip já simplificou essas funções, mantida a versão da tip) e corrigi o `no-explicit-any` no teste novo (cast tipado, mesmo padrão já usado em outros testes do repo). Validado: lint limpo, teste focado passando. Fix real e bem documentado (claude-*/gemini-*/gemma-* sem provider ativo agora retorna 404 model_not_found em vez de 401 enganoso). CI vermelho é o base-red já rastreado em #9985. Obrigado!
2026-08-21 03:49:01 -03:00
Dizzle
fdeac496e8 feat(providers): restore per-connection upstream timeout tier (#10885)
Reconciliado com a release (conflito aditivo em targetTimeoutRunner.ts — combina o warning G3 já mergeado com a resolução de effectiveTimeoutMs deste PR) e revalidado: 41/41 testes focados passando (upstream-timeout-connection-tier, combo-target-timeout-runner, provider-specific-data-schema). CI vermelho é o base-red já rastreado em #9985. Obrigado!
2026-08-21 02:18:25 -03:00