Skip to content

fix(quota): route quota fetcher reads through the connection proxy - #15885

Merged
diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.52from
maxmad64bis:fix/quota-fetchers-through-connection-proxy
Oct 18, 2026
Merged

diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.52from
maxmad64bis:fix/quota-fetchers-through-connection-proxy

Conversation

@maxmad64bis

@maxmad64bis maxmad64bis commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ base-red inherited: #15306

Summary

Quota fetcher reads go out as direct fetches instead of using the proxy assigned to the connection. A shared helper now resolves the assigned proxy and runs each read inside that proxy context, reporting an unknown reading instead of fetching directly when the proxied read fails. Without an assigned proxy the fetch runs unchanged.

Related Issues

Target Branch

  • Base is the active release/v3.8.x branch (the highest open release/v*), not main
  • New feature? From 3.8.55 on it is held with the v4-feature label for the v4 channel

Validation

  • Change type: other
  • Focused tests and category gates from the golden path
  • npm run lint
  • Reconciled with the current active release base; focused checks rerun afterward
  • Production-code changes include a new or updated automated test in this PR

Tests Added Or Updated

  • tests/unit/quota-fetchers-connection-proxy.test.ts — 17 cases: helper routing, passthrough, missing identifier, failures, and one case per fetcher inside the proxy context.
  • tests/unit/bailian-usage.test.ts — 4 cases: known entries pass an identifier; a no-identifier entry fetches nothing.

Coverage Notes

  • open-sse/services/qwenTokenPlanQuotaFetcher.ts — covered by "qwen token plan quota reads the dashboard and gateway inside the proxy context".
  • open-sse/services/agentrouterQuotaFetcher.ts — covered by "agentrouter quota reads inside the proxy context".
  • open-sse/services/alibabaFreeTierQuotaFetcher.ts — covered by "alibaba free tier quota reads inside the proxy context".
  • open-sse/services/bailianQuotaFetcher.ts — covered by "bailian quota retries the fallback host inside the proxy context".
  • open-sse/services/codexQuotaFetcher.ts — covered by "codex quota reads inside the proxy context".
  • open-sse/services/context7QuotaFetcher.ts — covered by "context7 quota reads inside the proxy context".
  • open-sse/services/deepseekQuotaFetcher.ts — covered by "deepseek quota reads inside the proxy context".
  • open-sse/services/firecrawlQuotaFetcher.ts — covered by "firecrawl quota reads inside the proxy context".
  • open-sse/services/grokCliQuotaFetcher.ts — covered by "grok cli quota reads inside the proxy context".
  • open-sse/services/grokQuotaFetcher.ts — covered by "grok web billing reads inside the proxy context".
  • open-sse/services/xaiOauthQuotaFetcher.ts — covered by "getUsageForProvider without a connection id reports no reading instead of fetching directly" in tests/unit/bailian-usage.test.ts (empty-identifier guard shared with the threaded call).

Reviewer Notes

  • Behavior: quota readings now use the assigned egress path; without an assigned proxy the fetch runs unchanged, and a failed proxied read reports an unknown reading instead of fetching directly.
  • Merge: lands before fix(quota): route remaining console quota reads through the connection proxy #16344, which extends the same helper to the nine remaining readers.
  • Follow-up: routing the remaining direct console quota reads (jina, llmgateway, lyceum, moonshot, new-api aggregator, opencode, openrouter, tavily and v0) through the assigned proxy is left for a later change.

@maxmad64bis
maxmad64bis force-pushed the fix/quota-fetchers-through-connection-proxy branch 2 times, most recently from a7b66e6 to 340a6cb Compare October 8, 2026 12:14
@maxmad64bis
maxmad64bis marked this pull request as ready for review October 8, 2026 12:22
@maxmad64bis
maxmad64bis marked this pull request as draft October 8, 2026 16:16
@maxmad64bis
maxmad64bis force-pushed the fix/quota-fetchers-through-connection-proxy branch from 340a6cb to 61d5119 Compare October 8, 2026 16:17
@maxmad64bis
maxmad64bis marked this pull request as ready for review October 8, 2026 17:06
@maxmad64bis
maxmad64bis marked this pull request as draft October 8, 2026 22:03
@maxmad64bis
maxmad64bis marked this pull request as ready for review October 9, 2026 08:55
@maxmad64bis
maxmad64bis marked this pull request as draft October 9, 2026 09:29
@maxmad64bis
maxmad64bis force-pushed the fix/quota-fetchers-through-connection-proxy branch from 61d5119 to 0be7ae7 Compare October 9, 2026 12:58
@maxmad64bis
maxmad64bis marked this pull request as ready for review October 9, 2026 13:26
@maxmad64bis
maxmad64bis marked this pull request as draft October 9, 2026 16:00
@maxmad64bis
maxmad64bis force-pushed the fix/quota-fetchers-through-connection-proxy branch from 0be7ae7 to 1c4c34b Compare October 9, 2026 17:06
@maxmad64bis
maxmad64bis marked this pull request as ready for review October 9, 2026 17:25
@diegosouzapw

Copy link
Copy Markdown
Collaborator

Hi @maxmad64bis — closing this pull request to clear the open queue. The branch fix/quota-fetchers-through-connection-proxy is kept, so the commits stay. Comment here if it should be reopened.

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Hi @maxmad64bis — reopening this pull request. The close was a mistake, and it is back in the merge queue. The branch fix/quota-fetchers-through-connection-proxy was kept.

@diegosouzapw diegosouzapw reopened this Oct 10, 2026
@maxmad64bis
maxmad64bis marked this pull request as draft October 11, 2026 12:24
@maxmad64bis
maxmad64bis force-pushed the fix/quota-fetchers-through-connection-proxy branch from 1c4c34b to 98637ba Compare October 11, 2026 12:24
@maxmad64bis
maxmad64bis marked this pull request as ready for review October 11, 2026 12:41
@maxmad64bis
maxmad64bis marked this pull request as draft October 11, 2026 21:41
@maxmad64bis
maxmad64bis force-pushed the fix/quota-fetchers-through-connection-proxy branch 2 times, most recently from 482e331 to 533aa50 Compare October 11, 2026 21:52
@maxmad64bis
maxmad64bis marked this pull request as ready for review October 11, 2026 22:27
Console quota reads used a direct fetch; they now run inside the assigned connection proxy context with no direct fallback.
@maxmad64bis
maxmad64bis marked this pull request as draft October 16, 2026 19:47
@maxmad64bis
maxmad64bis force-pushed the fix/quota-fetchers-through-connection-proxy branch from 533aa50 to d31ab96 Compare October 16, 2026 19:47
@maxmad64bis
maxmad64bis marked this pull request as ready for review October 16, 2026 20:31
@diegosouzapw
diegosouzapw merged commit 9d67706 into cheaper-inference:release/v3.8.52 Oct 18, 2026
43 of 95 checks passed
diegosouzapw pushed a commit that referenced this pull request Oct 18, 2026
…n proxy (#16344)

Routes the remaining console quota readings (jina, llmgateway, lyceum, moonshot, new-api aggregator, opencode, openrouter, tavily, v0) through the connection's assigned egress path via fetchWithConnectionProxy, completing #15885 (merged first; this branch was stacked on it and now carries only its own delta).

Maintainer fixes on top:
- open-sse/services/opencodeQuotaFetcher.ts: dropped the stale effectiveConnectionId = connectionId || "noauth" sentinel. Keyless OpenCode Free is gone (#16310), so 'noauth' resolved a proxy for a connection that cannot exist and shared one cache entry/session seed across every empty-id reading. Cache, session seed, proxy lookup and invalidation now use the real connection id; an empty id reports no reading like every other quota fetcher (the policy #16773/#15885 test for the helper).
- open-sse/services/grokQuotaFetcher.ts: the OIDC/refresh/billing helpers took an optional id and passed connectionId ?? "" to the helper, which turns an empty id into an unknown reading. Every caller already has the id (fetchGrokWebQuota, xaiOauthQuotaFetcher), so the parameter is now required and the ?? "" fallback is gone. The helper's empty-id policy itself is unchanged (merged + tested in #16773/#15885).
- tests/unit/quota-fetchers-connection-proxy.test.ts: the 'shared no-auth reading' case replaced by (a) an empty id makes no fetch outside the proxy — red on the PR head before the fix — and (b) the cache is keyed and invalidated by the connection id, not a shared no-auth key.

Evidence: focused node:test 324/324 over 29 quota-fetcher / usage-proxy files, 66/66 re-run after the final tip merge. Gates: typecheck:core, open-sse and API typechecks, file-size, complexity, cognitive-complexity, dead-code, boundary, agent-skills (Generated: 0), changelog-integrity, env-doc-sync, docs-sync, eslint all exit 0; prettier clean on the PR's hunks (the one flagged file, newApiAggregatorQuotaFetcher.ts, is unformatted on the release tip in an untouched function). Remaining CI reds are the inherited base-red #15306.

Thanks @maxmad64bis!
diegosouzapw pushed a commit that referenced this pull request Oct 18, 2026
Adds a per-provider registry of quota-cache invalidators (registerQuotaCacheInvalidator / getQuotaCacheInvalidator in quotaPreflight.ts). Every bespoke quota fetcher registers how to drop its cached snapshot under the same provider ids (aliases included) it registers its fetcher with, and the upstream-429 site in executeProviderRequest now calls invalidateQuotaCacheOnStatus, which uses the provider's invalidator and falls back to the generic cache drop. Before, a 429 only dropped the Codex and generic caches, so bespoke providers kept serving a stale 'quota available' snapshot for up to a minute. Behaviour note: a 429 now drops every bespoke fetcher's cache for that connection, so the next preflight re-reads usage — more quota reads after 429s, each still throttled by throttleQuotaFetch.

Maintainer fixes on top:
- Merged #15885 and #16344 (landed first, same fetcher files) into the branch: the only conflict was the grokQuotaFetcher import block (kept both the invalidator registration and the connection-proxy import). The combined fetchers both register their invalidator and read through the connection proxy.
- tests/unit/quota-cache-invalidation-on-429.test.ts (~L364): removed "opencode" from the expected invalidator keys — after #16310 the OpenCode fetcher registers only opencode-go and opencode-zen; the assertion was red on the merged tree ('missing quota cache invalidator for opencode') and is green now.

Evidence: focused node:test 332/332 over 29 files (quota-cache-invalidation-on-429, chatcore/execute-provider-request, generic-quota-fetcher, quota-fetchers-connection-proxy, every *-quota-fetcher suite, usage-connection-proxy, bailian-usage, newapi preflight dispatch), 74/74 re-run after the final tip merge. Gates: typecheck:core, open-sse and API typechecks, file-size, complexity, cognitive-complexity, dead-code, boundary, agent-skills (Generated: 0), changelog-integrity, env-doc-sync, docs-sync, eslint all exit 0; prettier clean on the PR's hunks (the flagged lines in tests/unit/chatcore/execute-provider-request.test.ts are pre-existing on the release tip). Remaining CI reds are the inherited base-red #15306.

Thanks @maxmad64bis!
@maxmad64bis
maxmad64bis deleted the fix/quota-fetchers-through-connection-proxy branch October 18, 2026 22:37
diegosouzapw added a commit that referenced this pull request Oct 18, 2026
…and two WorkBuddy contracts left by #17046 (#17102)

* test(quota): time the shared throttle, not the first fetch's start-up (#6911)

Since #15885 every quota fetcher calls fetchWithConnectionProxy() between the
throttle's acquire() and the upstream fetch. The first call of the process pays
one-time costs inside that window: it lazily imports the proxy transport and
the error helpers, then imports the DB settings module and opens SQLite with
every migration to look up the connection's proxy (first lookup measured at
~4.9 s, the next ones 6-12 ms). The second call, released 200 ms later, waits
on the same imports, so both fetches left together (spread 20-50 ms) and the
first test of the file, DeepSeek, failed whatever the throttle did.

The suite now answers the proxy lookup through the documented
connectionProxyTestOverride (as the proxy suites do) and pays the lazy imports
once in test.before, so the spread it measures is the throttle's again. The
assertions are unchanged; removing `await throttleQuotaFetch()` from the
DeepSeek fetcher still fails the suite (spread 3 ms).

Refs #15306

* test(providers): record WorkBuddy's compliance headers in the translate-path golden

#17046 (gateway compliance for WorkBuddy, #16978) deliberately changed the
headers the WorkBuddy executor sends: User-Agent WorkBuddy/5.5.6, the X-Agent-*
and X-IDE-* set, X-Domain and X-Requested-With. It shipped its own test but did
not regenerate tests/snapshots/provider/translate-path.json, so
provider-translate-path-golden has been red on the release branch since it
merged (19:03Z).

Regenerated with UPDATE_GOLDEN=1: the only provider entry that changed is
"workbuddy" (apiKey, nonStream and oauth header blocks). The golden and
workbuddy-gateway-compliance suites pass together (12/12).

Refs #15306

* test(providers): pin WorkBuddy's compliance body rewrites in the registry test

#17046 (#16978) placed four gateway-compliance rewrites ahead of the generic
Codex/OpenAI pairs in the WorkBuddy registry entry: the Anthropic billing
header is dropped, and the Claude Code and Codex CLI identity sentences are
reworded. It did not touch workbuddy-provider.test.ts, whose
bodyStringReplacements assertion still listed only the four old pairs, so the
suite has been red on the release branch since 19:03Z.

The assertion now pins all eight pairs in order: the long Codex sentence must
be rewritten whole before the generic "Codex CLI" / "OpenAI" pairs touch it.
workbuddy-provider + workbuddy-gateway-compliance + provider-translate-path
golden: 40/40.

Refs #15306
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants