Commit Graph

1606 Commits

Author SHA1 Message Date
Diego Rodrigues de Sa e Souza
07b385d4c1 feat(combo): task-aware routing strategy (#4945)
Integrated into release/v3.8.36
2026-06-24 12:43:38 -03:00
Diego Rodrigues de Sa e Souza
6137d4ef57 fix(translator): provider thinking compatibility (DeepSeek/Gemini) (#4946)
Integrated into release/v3.8.36
2026-06-24 12:41:30 -03:00
Diego Rodrigues de Sa e Souza
d65050a1db feat(providers): update volcengine-ark model list with DeepSeek V4 (#4905)
Integrated into release/v3.8.36
2026-06-24 12:40:47 -03:00
Diego Rodrigues de Sa e Souza
7c75b48792 fix(combo): fetch models dynamically from custom provider endpoints (#4860)
Integrated into release/v3.8.36
2026-06-24 12:40:08 -03:00
Diego Rodrigues de Sa e Souza
950fc6e60e fix(compression): eliminate ReDoS in math_inline preservation pattern (#4795) (#4838)
Integrated into release/v3.8.36 (fixes #4795)
2026-06-24 12:39:32 -03:00
Diego Rodrigues de Sa e Souza
4a1ae868ce refactor(open-sse): extract safeParseJSON util, dedup tryParseJSON (#4735)
Integrated into release/v3.8.36
2026-06-24 12:39:03 -03:00
Diego Rodrigues de Sa e Souza
6e28889aad refactor(sse): dedup fallback tool_call id helper (#4736)
Integrated into release/v3.8.36
2026-06-24 12:38:25 -03:00
Diego Rodrigues de Sa e Souza
cc8557cedf fix(qoder): exchange PAT for jt-* job token before Cosy chat (#4683) (#4884)
Integrated into release/v3.8.36 (fixes #4683)
2026-06-24 11:56:33 -03:00
Diego Rodrigues de Sa e Souza
b1b3069cd1 fix(translator): regroup parallel tool results adjacent to their assistant (#4714) (#4882)
Integrated into release/v3.8.36 (fixes #4714)
2026-06-24 11:55:40 -03:00
Diego Rodrigues de Sa e Souza
de19b3b087 refactor(sse): extrai quota-core (UsageQuota + builders) de services/usage.ts (#4950)
Integrated into release/v3.8.36
2026-06-24 11:54:09 -03:00
Diego Rodrigues de Sa e Souza
565b77143c refactor(sse): extrai scalar/format helpers de services/usage.ts (#4949)
Integrated into release/v3.8.36
2026-06-24 11:53:22 -03:00
Diego Rodrigues de Sa e Souza
ca72de7ba4 refactor(db): extrai schema-column reconciliation de db/core.ts (#4948)
Integrated into release/v3.8.36
2026-06-24 11:52:40 -03:00
Diego Rodrigues de Sa e Souza
5073aff2ae refactor(db): extrai column-mapping (snake↔camel) de db/core.ts (#4947)
Integrated into release/v3.8.36
2026-06-24 11:52:04 -03:00
Diego Rodrigues de Sa e Souza
ca0fdddebf refactor(db): extrai row-parsers + tipos compartilhados de db/apiKeys.ts (#4943)
Integrated into release/v3.8.36
2026-06-24 11:51:33 -03:00
Diego Rodrigues de Sa e Souza
f1589801ee refactor(db): extrai model-permission matching de db/apiKeys.ts (#4936)
Integrated into release/v3.8.36
2026-06-24 11:50:52 -03:00
Diego Rodrigues de Sa e Souza
419a90f240 refactor(api): extrai format-validators (OpenAI/Anthropic) de validation.ts (#4933)
Integrated into release/v3.8.36
2026-06-24 11:50:20 -03:00
Diego Rodrigues de Sa e Souza
537e5b5f6e refactor(api): extrai validators search + embedding/rerank de validation.ts (#4932)
Integrated into release/v3.8.36
2026-06-24 11:48:10 -03:00
Diego Rodrigues de Sa e Souza
9708288b57 feat(quota): estratégia dedicada de quota-share (DRR + P2C in-flight + gating per-model) [Fase 3 #9] (#4939)
* feat(quota): estratégia dedicada de quota-share (DRR + P2C in-flight + gating per-model) [Fase 3 #9]

Estratégia interna "quota-share" isolada num módulo dedicado — NÃO toca a seleção/
fair-share genérica (decisão do dono: não mexer no que já funciona). Os combos qtSd/
(quotaCombos.ts) passam de fill-first para essa strategy; combo.ts ganha só 1 branch
de dispatch que delega 100% ao módulo (nenhum case existente alterado).

- quotaShareStrategy.ts: gating per-model (isBucketSaturated do #3) + DRR (quantum
  proporcional ao weight) + P2C sobre carga in-flight.
- quotaShareInflight.ts: contador in-flight com TTL/lease de 120s — fallback do
  decrement-on-abort sem precisar instrumentar o combo genérico.
- "quota-share" registrada como strategy INTERNA (não exposta na UI).
- testes de síntese (quota-combo-balancing, quota-multiprovider) alinhados: a strategy
  esperada dos combos qtSd/ passa de "fill-first" para "quota-share" (alinhamento ao novo
  comportamento intencional, não mascaramento — os 73 testes de qtSd/ seguem verdes).

* test(quota-share): alinha 2 scope-guards ao godfile sweep (base-reds que bloqueavam o CI)

Dois testes de "arquivo contém X" quebraram por decomposições de godfile que outras
sessões mergearam no release DURANTE a validação de #9 — NÃO são regressão de #9
(que não toca validation/oauth). Alinhados ao novo layout, asserts preservados:
- proxy-bypass-scope-guard #3226: bypassProxyPatch foi extraído de validation.ts para
  validation/headers.ts (split #4921–#4930) → o teste lê a camada de validação.
- sse-error-passthrough #3324: a windsurf authHint foi extraída de providers.ts para
  providers/oauth.ts → o teste lê o novo local.

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
2026-06-24 11:40:17 -03:00
Diego Rodrigues de Sa e Souza
833adce8fb refactor(api): extrai validators áudio/speech + misc apikey de validation.ts (#4930)
Integrado em release/v3.8.36 (validation.ts split fatia 4 — áudio/speech + misc apikey)
2026-06-24 09:53:36 -03:00
Diego Rodrigues de Sa e Souza
6035fd8ba1 refactor(api): extrai validators enterprise-cloud + probe compartilhado de validation.ts (#4923)
Integrado em release/v3.8.36 (validation.ts split fatia 3 — enterprise-cloud + probe)
2026-06-24 09:52:23 -03:00
Diego Rodrigues de Sa e Souza
1cb246215a refactor(api): extrai validators web-cookie + Meta AI de validation.ts (#4922)
Integrado em release/v3.8.36 (validation.ts split fatia 2 — web-cookie + Meta AI)
2026-06-24 09:51:11 -03:00
Diego Rodrigues de Sa e Souza
21ce4872d2 refactor(api): extrai camada-folha pura de validation.ts (URL/headers/transport) (#4921)
Integrado em release/v3.8.36 (validation.ts split fatia 1 — leaf layer)
2026-06-24 09:49:59 -03:00
Diego Rodrigues de Sa e Souza
c872b6710d refactor(pricing): decompõe pricing.ts em shared-tiers + DEFAULT_PRICING particionado (godfile sweep, #3501) (#4918)
Integrado em release/v3.8.36 (godfile sweep pricing.ts, #3501)
2026-06-24 09:48:46 -03:00
Diego Rodrigues de Sa e Souza
b8e3dc950c refactor(providers): decompõe catálogo providers.ts em módulos de dados (godfile sweep, #3501) (#4917)
Integrado em release/v3.8.36 (godfile sweep providers.ts, #3501)
2026-06-24 09:47:45 -03:00
Diego Rodrigues de Sa e Souza
15ee83b44a feat(quota): buckets multi-janela por conexão (5h/7d/per-model) [Fase 3 #3] (#4928)
Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
2026-06-24 09:35:28 -03:00
Diego Rodrigues de Sa e Souza
0811a15a09 feat(quota): session stickiness p/ integridade de prompt-cache [Fase 3 #5] (#4929)
* feat(quota): session stickiness p/ integridade de prompt-cache [Fase 3 #5]

Adiciona stickiness de sessão ao roteamento de combo: uma conversa multi-turno
é roteada para a MESMA conexão enquanto ela permanecer saudável, evitando a
perda do prompt-cache do provider (custo 5-10× sem stickiness, efeito conhecido
no dario/clewdr).

Implementação:
- `open-sse/services/combo/sessionStickiness.ts` (novo, <800 linhas):
  mapa em memória (messageHash → connectionId) com TTL 15 min + cap 500 entradas;
  `applySessionStickiness` promove a conexão sticky ao índice 0 dos targets
  ordenados pelo strategy, guardado por `computeHeadroom > 0.15` (threshold);
  quando saturada (headroom ≤ 0.15), o binding é limpo e a seleção normal reage.
  Hash da sessão = SHA-256 dos primeiros chars da 1ª mensagem user → 16 hex chars.
  Seam de teste: `__setStickinessHeadroomFetcherForTests`.
- `open-sse/services/combo.ts`: import + 2 pontos de integração (pré-eval-scores
  e pós-success), dentro do orçamento congelado de 3180 linhas.
- `tests/unit/combo-session-stickiness.test.ts`: 19 testes node:test + assert/strict,
  todos via injeção de fetcher (zero rede/DB).

Threshold 0.15: conexão a >85% de utilização está a um burst de rate-limit;
o benefício de cache não compensa manter-se numa conexão degradada. Valor
alinhado com a zona de soft-penalty do restante do engine de quota-share.

* test(combo): isola combo-strategies da session stickiness (#5)

selectedConnectionFor reusa o mesmo body, então o sticky map (#5) fixava a
connection após a 1ª chamada e quebrava o round-robin tie-break do teste
reset-aware. Limpa o sticky map no início da helper — a stickiness tem suíte
própria (combo-session-stickiness). Sem enfraquecer asserts.

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
2026-06-24 09:23:34 -03:00
Diego Rodrigues de Sa e Souza
98296169ed feat(quota): cap per-(key,model) — quota_allocation_model_caps [Fase 3 #7] (#4927)
* feat(quota): cap per-(key,model) com tabela quota_allocation_model_caps [Fase 3 #7]

Fecha o buraco onde uma API key pode drenar o pool inteiro consumindo um único modelo.

Tabela nova: quota_allocation_model_caps(pool_id, api_key_id, model, cap_value, cap_unit)
PK composta (pool_id, api_key_id, model). cap_unit alinhado ao QuotaUnit existente.

Comportamento: keyA acima do cap para modelo M → bloqueada somente em M; ainda
permitida em qualquer outro modelo no mesmo pool. Cap <= EPSILON → ignorado (seed).

Consumo por-(key,model) usa bucket segregado no quota_consumption existente
(poolId mangled ':model:<model>') com window fixa 'hourly'; nenhuma nova tabela
ou método de store necessário.

Módulo novo: src/lib/db/quotaModelCaps.ts (getModelCap/setModelCap/deleteModelCap/listModelCaps)
enforce.ts ganha o pre-check em enforceQuotaShare + recording em recordConsumption.
EnforceInput e RecordConsumptionInput ganham model?: string (backward-compatible).
localDb.ts re-exporta os 4 helpers (Hard Rule #2).

TDD: tests/unit/quota-per-key-model.test.ts — 4 cenários (bloqueia em M, permite em M2,
sem cap → sem bloqueio, EPSILON → ignorado). Todos os gates de qualidade passam.

* feat(quota): plumba model resolvido no hot path para ativar o per-(key,model) cap [Fase 3 #7]

A tabela/enforce do commit anterior estavam INERTES: o hot path não passava `model`
ao enforce nem ao record, então nenhum model-cap disparava em produção.

Plumbagem (model resolvido = mesma var usada no log/roteamento, pós background-redirect/alias):
- chatCore.ts: enforceQuotaShare ganha `model`; scheduleQuotaShareConsumption recebe `model`.
- chatCore/quotaShareConsumption.ts: threade `model` no RecordConsumptionInput (non-streaming).
- spendRecorder.ts: recordStreamingConsumption já recebia `model` — agora o coloca no
  RecordConsumptionInput (streaming accrue por-modelo).
- embeddings.ts: enforce + record ganham `model`.

Namespace do cap = id do modelo RESOLVIDO (o mesmo de modelForScope/pendingScope/getUnsupportedParams),
não o requestedModel cru nem o finalModelToUpstream (sem prefixo de provider). Operador configura
o cap contra esse id. `model || undefined` em todos os pontos: vazio/null → check pulado (fail-safe,
zero latência — só um campo no objeto).

Teste de integração novo (tests/unit/quota-per-key-model-hotpath.test.ts): prova end-to-end que
N consumos via scheduleQuotaShareConsumption({model}) → enforceQuotaShare({model}) bloqueia, e que
outro modelo no mesmo pool ainda passa; + guard de que enforce SEM model nunca dispara model-cap.

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
2026-06-24 08:07:42 -03:00
Diego Rodrigues de Sa e Souza
118875e3ed feat(quota): estratégia de combo "headroom" — seleção por folga de cota [Fase 3 #4] (#4908)
Nova estratégia de roteamento que escolhe a conexão com MAIS folga de plano:
headroom = 1 − max(util_5h, util_7d) (técnica do dario), via getSaturation
(melhorado p/ Claude no #1). Proativo em vez de só fill-first reativo.

- Helper PURO headroomRanking.ts (computeHeadroom + rankByHeadroom; saturação
  injetada, não-mutante, tie-break estável, fail-open).
- Orderer async em combo/quotaStrategies.ts (reusa a maquinaria reset-aware de
  expansão de conexões + concorrência limitada; seam injetável).
- Registrada como "headroom" em routingStrategies (combo-only); fill-first segue
  default — nenhuma estratégia existente tocada.
- baseline file-size combo.ts 3168->3180 (só +12L de dispatch; lógica fora do god-file).

16 testes novos + combo-strategies 15/15 = 31/31; typecheck:core + eslint +
file-size limpos.

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
2026-06-24 07:25:40 -03:00
Diego Rodrigues de Sa e Souza
9d5954122d feat(quota): saturação proativa por headers de tokens (universal) [Fase 3 #2] (#4907)
storeRateLimitHeaders só capturava os headers de REQUESTS (RPM/min), que não
refletem a pressão de TOKENS. Agora também parseia os headers de tokens (em toda
resposta, sucesso também) para throttle proativo antes do 429:
- Anthropic: anthropic-ratelimit-tokens-{limit,remaining,reset} (+ input/output), RFC3339.
- OpenAI: x-ratelimit-{limit,remaining,reset}-tokens, reset em duração (6m0s).

saturation = 1 − remaining/limit; resetAt normalizado a epoch (parse de duração
ReDoS-safe). getTokenHeaderSaturation por (provider, connectionId). fetchGeneric-
Saturation passa a usar esse sinal (complementa o oauth/usage do #1, que segue
primário p/ Claude). Fail-open, cache mantido, request-path inalterado.

16 testes novos + regressão (oauth/usage #1 8/8, signals 6/6) = 30/30;
typecheck:core + eslint limpos.

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
2026-06-24 07:14:00 -03:00
Diego Rodrigues de Sa e Souza
5d9ecf6f8b chore(quality): conserta base-red de release/v3.8.36 (gates + 7 testes + build MDX) (#4915)
A base tinha base-red sistêmica herdada de PRs de outras sessões, bloqueando
TODOS os PRs do ciclo (o TIA roda a suíte full em fail-safe p/ diffs hub).

4 Fast Quality Gates:
- test-discovery (#4877): live-server-allowlist.test.ts em tests/unit/server/
  (não-coletado) + vitest → nunca rodava. Convertido p/ node:test em tests/unit/security/.
- any-budget:t11 (#4664): 3 explicit-any em tokenRefresh.ts tipados (sem crescer file-size).
- docs-symbols (#4868): rotas inexistentes → /api/system/version e
  PUT /api/providers/{id} {isActive:false}.
- docs-all fabricated-claim (#4868 + #4718): 5 bin/*.sh reais criados (rollback,
  snapshot-data, restore-data, restore-policies, cold-start-bench) + _ops-common.sh
  (snapshot VACUUM INTO, guards de confirmação/TTY, testes de contrato); NODE_EXTRA_CA_CERTS
  (env de runtime Node) na allowlist do checker.

7 testes unit base-red (de features alheias à quota):
- oauth-providers-config (#4664): teste alinhado ao provider codebuddy-cn do registry.
- antigravity-model-aliases (#4636): maxOutputTokens esperado 32769→16384 (cap intencional).
- provider-request-capture #4091 (#4861): exemplo do teste trocado de mcp__ (que #4861
  isenta de cloak por causa dos 400s de assimetria de histórico) para um tool de terceiro
  cloakável — preserva o invariante de #4091 SEM reverter #4861.
- combo-error-response: convertido de vitest p/ node:test (era coletado pelo glob node:test
  e crashava); api/** e server/** removidos do vitest.config (config morta).

Build MDX (dast-smoke, #4679):
- docs/ops/RELEASE_GREEN.md não tinha frontmatter `title` → fumadocs-mdx rejeitava no
  webpack compile ("invalid frontmatter: title expected string"), quebrando o next build
  (e o deploy). Frontmatter title adicionado (único doc do collection sem ele).

17/17 Fast Quality Gates + suíte unit completa (17737 testes, 0 fail) + vitest verdes localmente.

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
2026-06-24 07:00:16 -03:00
Diego Rodrigues de Sa e Souza
8080800d8f feat(proxy-pool): Cloudflare Workers proxy deployer + pool integration (#4640)
Integrated into release/v3.8.36 (relay type added to RELAY_TYPES set; dropdown UX preserved + Cloudflare item added; proxies.ts file-size rebaselined 1057→1060)
2026-06-24 00:57:43 -03:00
Diego Rodrigues de Sa e Souza
078785cbf3 fix(cli): SIGKILL systray child PID before IPC close to avoid macOS NSStatusItem orphan (#4732)
Integrated into release/v3.8.36
2026-06-24 00:47:40 -03:00
Diego Rodrigues de Sa e Souza
1a1a51c744 feat(db): track API endpoint dimension on usage_history (#4676)
Integrated into release/v3.8.36 (migration renumbered 103→105; endpoint plumbed through extracted usage-stats helpers)
2026-06-24 00:46:54 -03:00
Diego Rodrigues de Sa e Souza
8251e7b8fb feat(opencode-go): advertise glm-5.2 and kimi-k2.7-code (align with official Go endpoints) (#4711)
Integrated into release/v3.8.36
2026-06-24 00:41:53 -03:00
Diego Rodrigues de Sa e Souza
7a6f43209c fix(translator): replay reasoning_content on plain Xiaomi MiMo turns (port from 9router#1321) (#4639)
Integrated into release/v3.8.36
2026-06-24 00:41:16 -03:00
Diego Rodrigues de Sa e Souza
95e26a07ff fix(cli): bump better-sqlite3 runtime pin to 12.10.1 for Node 26 (#4685)
Integrated into release/v3.8.36
2026-06-24 00:38:50 -03:00
Diego Rodrigues de Sa e Souza
f9ccf342c0 chore(dashboard): rename Qoder display label from "Qoder AI" to "Qoder" (#4733)
Integrated into release/v3.8.36
2026-06-24 00:37:15 -03:00
Diego Rodrigues de Sa e Souza
70afa2b5c6 feat(quota): saturação real do Claude no fair-share via /api/oauth/usage (#4885)
Integrated into release/v3.8.36
2026-06-24 00:04:37 -03:00
Diego Rodrigues de Sa e Souza
4305ef8690 fix(quota): policy inválida não vaza allow + guard connectionIds vazio [Fase 3 #10] (#4901)
Integrated into release/v3.8.36
2026-06-24 00:04:22 -03:00
Diego Rodrigues de Sa e Souza
27c994ffd3 feat(quota): recuperação proativa de conexões em cooldown (cron heal) [Fase 3 #8] (#4900)
Integrated into release/v3.8.36
2026-06-24 00:04:20 -03:00
Diego Rodrigues de Sa e Souza
5c0cda929c fix(security): SSRF allowlist bypass via x-relay-path nos relays Deno/Vercel (#4899)
Integrated into release/v3.8.36
2026-06-24 00:04:17 -03:00
Diego Rodrigues de Sa e Souza
2039095f69 chore(claude,codex): bump pinned CLI identity — Claude 2.1.158→2.1.187, Codex 0.132.0→0.142.0 (#4883)
Integrated into release/v3.8.36
2026-06-24 00:04:13 -03:00
KooshaPari
c522454c79 feat(live-ws): allow non-loopback clients via LIVE_WS_ALLOWED_HOSTS (closes #4873) (#4877)
Integrated into release/v3.8.36 (live-ws + combo-api commits; Tailscale CGNAT commit held pending opt-in/opt-out decision)
2026-06-23 23:21:51 -03:00
Éder Costa
2a7f2c892a feat(routing): honor X-Route-Model header to override body.model (#4863)
Integrated into release/v3.8.36
2026-06-23 23:15:02 -03:00
Jefferson Felizardo
eb175db8ed fix(codex): drop non-standard codex.* events that break responses.stream (env-gated, #4602) (#4715)
Integrated into release/v3.8.36
2026-06-23 23:07:51 -03:00
Éder Costa
86b14add6e fix(claude): skip mcp__ tool-name cloak + guard missing connectionId (#4861)
Integrated into release/v3.8.36
2026-06-23 22:59:51 -03:00
Éder Costa
108e93e14b fix(sse): drop ccp pin when pinned provider is durably unhealthy (failover + anti-flap) (#4864)
Integrated into release/v3.8.36
2026-06-23 22:58:21 -03:00
Randi
459ffcf2c0 fix db storage tuning settings (#4834)
Integrated into release/v3.8.36
2026-06-23 22:57:26 -03:00
Chewji
e99e2887bf fix(combo): propagate selected connection ID to fallback error responses for correct model lockout (#4809)
Integrated into release/v3.8.36
2026-06-23 22:56:14 -03:00
Demiurge The Single
604654cc3a fix(install): make transformers optional for CUDA-host installs (#4807)
Integrated into release/v3.8.36
2026-06-23 22:54:15 -03:00