Skip to content

feat(providers): wire CrofAI /usage_api/ into quota preflight, monitor & Limits page - #1606

Merged
diegosouzapw merged 2 commits into
diegosouzapw:release/v3.7.0from
jeanfbrito:feat/crof-usage-fetcher
Apr 26, 2026
Merged

diegosouzapw merged 2 commits into
diegosouzapw:release/v3.7.0from
jeanfbrito:feat/crof-usage-fetcher

Conversation

@jeanfbrito

@jeanfbrito jeanfbrito commented Apr 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #1604 (built-in CrofAI provider). CrofAI exposes a tiny usage endpoint:

```
GET https://crof.ai/usage_api/
Authorization: Bearer
→ { "usable_requests": number | null, "credits": number }
```

  • `usable_requests` — daily request bucket on a subscription plan (`null` on pay-as-you-go).
  • `credits` — USD credit balance.

This PR wires that endpoint into all three places OmniRoute exposes provider quota data, so a CrofAI connection behaves like the existing GLM / Minimax built-ins out of the box:

  1. Quota preflight (`open-sse/services/quotaPreflight.ts`) — opt-in proactive blocking.
  2. Quota monitor (`open-sse/services/quotaMonitor.ts`) — runtime snapshot stream.
  3. Limits & Quotas dashboard (`/dashboard/limits` → `open-sse/services/usage.ts` switch + `USAGE_SUPPORTED_PROVIDERS` + `PROVIDER_LIMITS_APIKEY_PROVIDERS`) — what the user sees in the UI.

Without all three, a CrofAI key silently never appears under Limits & Quotas even though the live data is available.

Mapping

Account type Quota label Block (preflight only) when `resetAt`
Subscription (`usable_requests` is a number) Requests Today — remaining count exposed (no fake percent-used bar; daily allotment isn't returned by the API) `usable_requests <= 0` next UTC midnight ISO ¹
Pay-as-you-go (`usable_requests === null`) — (omitted) `credits <= 0` n/a
Always Credits — `unlimited: true`, displayName `Credits: $X.XXXX` (open balance, not a bucket) n/a `null`

¹ CrofAI's `/usage_api/` returns no reset timestamp and the docs only say "requests left today". We synthesize the next UTC midnight as a best-guess so the dashboard's existing `formatResetTime` countdown renders (matches Minimax / Bailian cards). Code comment cites the investigation; swap for a real field if Crof ever exposes one.

Files

File Change
`open-sse/services/crofUsageFetcher.ts` (new) Quota fetcher with 60s in-memory cache (matches the codex/bailian shape). Exposes `registerCrofUsageFetcher()`, `fetchCrofUsage()`, `parseCrofUsageResponse()`, `invalidateCrofUsageCache()`.
`src/sse/handlers/chat.ts` Call `registerCrofUsageFetcher()` at module load alongside the existing Codex / Bailian registrations.
`open-sse/services/usage.ts` Add `getCrofUsage(apiKey)` and a `case "crof":` in `getUsageForProvider`. Returns `Requests Today` (subscription only) + `Credits` quotas using the existing `UsageQuota` shape. Synthesizes `Requests Today.resetAt` as next UTC midnight.
`src/shared/constants/providers.ts` Append `"crof"` to `USAGE_SUPPORTED_PROVIDERS`.
`src/lib/usage/providerLimits.ts` Add `"crof"` to `PROVIDER_LIMITS_APIKEY_PROVIDERS` so the apikey path of `isSupportedUsageConnection` accepts it.
`tests/unit/crof-usage-fetcher.test.ts` (new) 9 cases — parser branches, apiKey fail-open, response cache hit, 401 cache eviction, idempotent register call.
`tests/unit/crof-usage.test.ts` (new) 5 cases — allowlist membership, missing apiKey, subscription quota mapping (incl. `resetAt` parses to a future Date within 24h), pay-as-you-go fallback, 401 messaging.

Total: +460 lines, no deletions.

Verification

  • `npm run test:unit` — full suite green (3593/3593) including the two new test files. Pushed via the husky pre-push hook.
  • Live `GET https://crof.ai/usage_api/\` with a real key returns `{ credits, usable_requests }` and both `parseCrofUsageResponse` (preflight) and `getCrofUsage` (limits page) produce the expected output for both subscription and pay-as-you-go branches.
  • In a locally rebuilt image with this PR + feat(providers): add CrofAI as a built-in API-key provider #1604 stacked, a real CrofAI connection appears on `/dashboard/limits` next to the existing GLM / Minimax / Claude Code cards. `Requests Today` shows a live countdown (e.g., `⏱ 0h 39m`) computed from `resetAt = next UTC midnight`.

Notes

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

CrofAI exposes a simple usage endpoint that the quota subsystem can
hook into the same way the Codex and Bailian fetchers do:

  GET https://crof.ai/usage_api/
  Authorization: Bearer <key>
  → { "usable_requests": 450 | null, "credits": 12.3456 }

`usable_requests` is the daily request bucket on a subscription plan
(null on pay-as-you-go). `credits` is the USD credit balance.

Mapping to QuotaInfo (open-sse/services/quotaPreflight.ts):
- Subscription account: surfaces `usable_requests` as `total`/raw counter
  and only sets `percentUsed = 1` (block) when the bucket hits zero.
- Pay-as-you-go: same gate, but driven by `credits > 0`.

We don't try to invent a daily allotment from a single response, so the
fetcher only blocks at exhaustion rather than guessing a percent. Account
switching for healthy balances is left to the existing combo retry path.

Files:
- open-sse/services/crofUsageFetcher.ts — new fetcher with a 60s in-memory
  cache (matches the codex/bailian shape), exposed via
  `registerCrofUsageFetcher()` for both `registerQuotaFetcher` and
  `registerMonitorFetcher`. Also re-exports `parseCrofUsageResponse` and
  `invalidateCrofUsageCache` for tests/diagnostics.
- src/sse/handlers/chat.ts — call `registerCrofUsageFetcher()` at module
  load alongside the existing Codex / Bailian registrations.
- tests/unit/crof-usage-fetcher.test.ts — covers parser branches
  (subscription, exhausted, pay-as-you-go, string-encoded, garbage
  payloads), apiKey fail-open, response cache hit, and 401 cache eviction.
  Required by the repo's PR Test Policy.

Verified:
- `tests/unit/crof-usage-fetcher.test.ts` — 9/9 pass.
- `GET https://crof.ai/usage_api/` with a real key returns
  `{ credits, usable_requests }` and `parseCrofUsageResponse` produces a
  valid `QuotaInfo` for both branches.

Note: this assumes the `crof` provider is registered in
`APIKEY_PROVIDERS` / `REGISTRY` (proposed in diegosouzapw#1604). The fetcher
self-registers under provider id `crof`; if that PR has not landed yet
the registration is a harmless no-op.
jeanfbrito pushed a commit to jeanfbrito/OmniRoute that referenced this pull request Apr 25, 2026
Follow-up to diegosouzapw#1604 (built-in CrofAI provider) and complementary to diegosouzapw#1606
(quota preflight/monitor fetcher). The Limits & Quotas dashboard
(`/dashboard/limits`) renders only providers that:

  1. appear in `USAGE_SUPPORTED_PROVIDERS` (src/shared/constants/providers.ts), and
  2. are oauth, OR
     are apikey AND in `PROVIDER_LIMITS_APIKEY_PROVIDERS` (src/lib/usage/providerLimits.ts), and
  3. have a `case` in `getUsageForProvider` (open-sse/services/usage.ts).

Without all three, a CrofAI connection silently never appears on the
Limits & Quotas page even though the live key has data to show.

CrofAI exposes a tiny endpoint matching the established pattern:

  GET https://crof.ai/usage_api/
  Authorization: Bearer <key>
  → { "usable_requests": number | null, "credits": number }

`usable_requests` is the daily request bucket on a subscription plan
(`null` for pay-as-you-go); `credits` is the USD credit balance.

Files:
- src/shared/constants/providers.ts — append "crof" to
  USAGE_SUPPORTED_PROVIDERS.
- src/lib/usage/providerLimits.ts — add "crof" to
  PROVIDER_LIMITS_APIKEY_PROVIDERS.
- open-sse/services/usage.ts — add `getCrofUsage(apiKey)` and a
  `case "crof":` in `getUsageForProvider`. The fetcher returns up to two
  quotas:
    - "Requests Today" — populated only on subscription accounts; the
      remaining count comes straight from the API since the daily
      allotment is not exposed (no fake percent-used bar).
    - "Credits" — always present, marked unlimited so the UI shows the
      USD balance via displayName instead of a misleading 0/0 bar.
  Errors and 401/403 surface friendly messages and never throw.
- tests/unit/crof-usage.test.ts (new) — 5 cases covering allowlist
  membership, missing apiKey message, subscription quota mapping,
  pay-as-you-go fallback (no Requests Today), and 401 messaging. Required
  by the repo's PR Test Policy.

Verified end-to-end against a locally rebuilt image with all four crof
patches stacked: a real CrofAI connection now appears on
/dashboard/limits with "Requests Today" and "Credits" cards next to the
existing GLM/Minimax entries.

Notes:
- This PR depends on diegosouzapw#1604 having landed (provider id `crof` must exist).
  Without it the new switch case is dormant.
- This PR is independent of diegosouzapw#1606 (the quota preflight/monitor fetcher);
  they hit different code paths and cooperate cleanly.
@jeanfbrito
jeanfbrito force-pushed the feat/crof-usage-fetcher branch from 8298a36 to e216cf0 Compare April 25, 2026 22:44
@jeanfbrito jeanfbrito changed the title feat(providers): wire CrofAI /usage_api/ into quota preflight & monitor feat(providers): wire CrofAI /usage_api/ into quota preflight, monitor & Limits page Apr 25, 2026
@jeanfbrito
jeanfbrito changed the base branch from main to release/v3.7.0 April 25, 2026 22:45
jeanfbrito pushed a commit to jeanfbrito/OmniRoute that referenced this pull request Apr 25, 2026
Follow-up to diegosouzapw#1604 (built-in CrofAI provider) and complementary to diegosouzapw#1606
(quota preflight/monitor fetcher). The Limits & Quotas dashboard
(`/dashboard/limits`) renders only providers that:

  1. appear in `USAGE_SUPPORTED_PROVIDERS` (src/shared/constants/providers.ts), and
  2. are oauth, OR
     are apikey AND in `PROVIDER_LIMITS_APIKEY_PROVIDERS` (src/lib/usage/providerLimits.ts), and
  3. have a `case` in `getUsageForProvider` (open-sse/services/usage.ts).

Without all three, a CrofAI connection silently never appears on the
Limits & Quotas page even though the live key has data to show.

CrofAI exposes a tiny endpoint matching the established pattern:

  GET https://crof.ai/usage_api/
  Authorization: Bearer <key>
  → { "usable_requests": number | null, "credits": number }

`usable_requests` is the daily request bucket on a subscription plan
(`null` for pay-as-you-go); `credits` is the USD credit balance.

Files:
- src/shared/constants/providers.ts — append "crof" to
  USAGE_SUPPORTED_PROVIDERS.
- src/lib/usage/providerLimits.ts — add "crof" to
  PROVIDER_LIMITS_APIKEY_PROVIDERS.
- open-sse/services/usage.ts — add `getCrofUsage(apiKey)` and a
  `case "crof":` in `getUsageForProvider`. The fetcher returns up to two
  quotas:
    - "Requests Today" — populated only on subscription accounts; the
      remaining count comes straight from the API since the daily
      allotment is not exposed (no fake percent-used bar).
    - "Credits" — always present, marked unlimited so the UI shows the
      USD balance via displayName instead of a misleading 0/0 bar.
  Errors and 401/403 surface friendly messages and never throw.
- tests/unit/crof-usage.test.ts (new) — 5 cases covering allowlist
  membership, missing apiKey message, subscription quota mapping,
  pay-as-you-go fallback (no Requests Today), and 401 messaging. Required
  by the repo's PR Test Policy.

Verified end-to-end against a locally rebuilt image with all four crof
patches stacked: a real CrofAI connection now appears on
/dashboard/limits with "Requests Today" and "Credits" cards next to the
existing GLM/Minimax entries.

Notes:
- This PR depends on diegosouzapw#1604 having landed (provider id `crof` must exist).
  Without it the new switch case is dormant.
- This PR is independent of diegosouzapw#1606 (the quota preflight/monitor fetcher);
  they hit different code paths and cooperate cleanly.
@jeanfbrito
jeanfbrito force-pushed the feat/crof-usage-fetcher branch 2 times, most recently from 02c7671 to 7e287da Compare April 25, 2026 23:34
jeanfbrito pushed a commit to jeanfbrito/OmniRoute that referenced this pull request Apr 25, 2026
Follow-up to diegosouzapw#1604 (built-in CrofAI provider) and complementary to diegosouzapw#1606
(quota preflight/monitor fetcher). The Limits & Quotas dashboard
(`/dashboard/limits`) renders only providers that:

  1. appear in `USAGE_SUPPORTED_PROVIDERS` (src/shared/constants/providers.ts), and
  2. are oauth, OR
     are apikey AND in `PROVIDER_LIMITS_APIKEY_PROVIDERS` (src/lib/usage/providerLimits.ts), and
  3. have a `case` in `getUsageForProvider` (open-sse/services/usage.ts).

Without all three, a CrofAI connection silently never appears on the
Limits & Quotas page even though the live key has data to show.

CrofAI exposes a tiny endpoint matching the established pattern:

  GET https://crof.ai/usage_api/
  Authorization: Bearer <key>
  → { "usable_requests": number | null, "credits": number }

`usable_requests` is the daily request bucket on a subscription plan
(`null` for pay-as-you-go); `credits` is the USD credit balance.

Files:
- src/shared/constants/providers.ts — append "crof" to
  USAGE_SUPPORTED_PROVIDERS.
- src/lib/usage/providerLimits.ts — add "crof" to
  PROVIDER_LIMITS_APIKEY_PROVIDERS.
- open-sse/services/usage.ts — add `getCrofUsage(apiKey)` and a
  `case "crof":` in `getUsageForProvider`. The fetcher returns up to two
  quotas:
    - "Requests Today" — populated only on subscription accounts; the
      remaining count comes straight from the API since the daily
      allotment is not exposed (no fake percent-used bar).
    - "Credits" — always present, marked unlimited so the UI shows the
      USD balance via displayName instead of a misleading 0/0 bar.
  Errors and 401/403 surface friendly messages and never throw.
- tests/unit/crof-usage.test.ts (new) — 5 cases covering allowlist
  membership, missing apiKey message, subscription quota mapping,
  pay-as-you-go fallback (no Requests Today), and 401 messaging. Required
  by the repo's PR Test Policy.

Verified end-to-end against a locally rebuilt image with all four crof
patches stacked: a real CrofAI connection now appears on
/dashboard/limits with "Requests Today" and "Credits" cards next to the
existing GLM/Minimax entries.

Notes:
- This PR depends on diegosouzapw#1604 having landed (provider id `crof` must exist).
  Without it the new switch case is dormant.
- This PR is independent of diegosouzapw#1606 (the quota preflight/monitor fetcher);
  they hit different code paths and cooperate cleanly.
Follow-up to diegosouzapw#1604 (built-in CrofAI provider) and complementary to diegosouzapw#1606
(quota preflight/monitor fetcher). The Limits & Quotas dashboard
(`/dashboard/limits`) renders only providers that:

  1. appear in `USAGE_SUPPORTED_PROVIDERS` (src/shared/constants/providers.ts), and
  2. are oauth, OR
     are apikey AND in `PROVIDER_LIMITS_APIKEY_PROVIDERS` (src/lib/usage/providerLimits.ts), and
  3. have a `case` in `getUsageForProvider` (open-sse/services/usage.ts).

Without all three, a CrofAI connection silently never appears on the
Limits & Quotas page even though the live key has data to show.

CrofAI exposes a tiny endpoint matching the established pattern:

  GET https://crof.ai/usage_api/
  Authorization: Bearer <key>
  → { "usable_requests": number | null, "credits": number }

`usable_requests` is the daily request bucket on a subscription plan
(`null` for pay-as-you-go); `credits` is the USD credit balance.

Files:
- src/shared/constants/providers.ts — append "crof" to
  USAGE_SUPPORTED_PROVIDERS.
- src/lib/usage/providerLimits.ts — add "crof" to
  PROVIDER_LIMITS_APIKEY_PROVIDERS.
- open-sse/services/usage.ts — add `getCrofUsage(apiKey)` and a
  `case "crof":` in `getUsageForProvider`. The fetcher returns up to two
  quotas:
    - "Requests Today" — populated only on subscription accounts; the
      remaining count comes straight from the API since the daily
      allotment is not exposed (no fake percent-used bar).
    - "Credits" — always present, marked unlimited so the UI shows the
      USD balance via displayName instead of a misleading 0/0 bar.
  Errors and 401/403 surface friendly messages and never throw.
- tests/unit/crof-usage.test.ts (new) — 5 cases covering allowlist
  membership, missing apiKey message, subscription quota mapping,
  pay-as-you-go fallback (no Requests Today), and 401 messaging. Required
  by the repo's PR Test Policy.

Verified end-to-end against a locally rebuilt image with all four crof
patches stacked: a real CrofAI connection now appears on
/dashboard/limits with "Requests Today" and "Credits" cards next to the
existing GLM/Minimax entries.

Notes:
- This PR depends on diegosouzapw#1604 having landed (provider id `crof` must exist).
  Without it the new switch case is dormant.
- This PR is independent of diegosouzapw#1606 (the quota preflight/monitor fetcher);
  they hit different code paths and cooperate cleanly.
@jeanfbrito
jeanfbrito force-pushed the feat/crof-usage-fetcher branch from 7e287da to cb0b65f Compare April 25, 2026 23:57
@diegosouzapw
diegosouzapw merged commit 13495d4 into diegosouzapw:release/v3.7.0 Apr 26, 2026
1 of 2 checks passed
@diegosouzapw

Copy link
Copy Markdown
Owner

Thanks @diegosouzapw for this great contribution! 🎉 It's now officially merged into the release/v3.7.0 branch and will be part of the next release. We appreciate your effort on adding Image Generation & Editing for ChatGPT Web!

@diegosouzapw diegosouzapw mentioned this pull request Apr 26, 2026
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
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