Repository navigation
feat(gateway): exact reset time in premium cap error - #3076
Merged
Merged
Conversation
The weekly premium-cap 402 message rounded the wait up to whole days (6 days and a few hours displayed as "Resets in 7 days", and even a 20-minute wait as "1 day"). Format the remaining time as days and hours instead (e.g. "Resets in 6 days and 3 hours."), rounding up to the next hour and reporting sub-hour waits as "less than an hour". Claude-Session: https://claude.ai/code/session_01NeqtWHWHmyug3BXUv3JmV9
Contributor
WalkthroughChangesPremium reset formatting
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Contributor
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/gateway/src/chat/tools/resolve-provider-context.ts (1)
218-233: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueExtract the millisecond multiplier to a constant.
You can apply DRY principles by extracting
60 * 60 * 1000into a local constant, such asHOUR_IN_MS, to avoid duplicating the magic number.♻️ Proposed refactor
export function formatTimeUntilReset(ms: number): string { - if (ms < 60 * 60 * 1000) { + const HOUR_IN_MS = 60 * 60 * 1000; + if (ms < HOUR_IN_MS) { return "less than an hour"; } - const totalHours = Math.ceil(ms / (60 * 60 * 1000)); + const totalHours = Math.ceil(ms / HOUR_IN_MS); const days = Math.floor(totalHours / 24); const hours = totalHours % 24;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/gateway/src/chat/tools/resolve-provider-context.ts` around lines 218 - 233, In formatTimeUntilReset, extract the repeated 60 * 60 * 1000 expression into a local constant such as HOUR_IN_MS, then reuse it for both the threshold check and totalHours calculation without changing the existing behavior.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@apps/gateway/src/chat/tools/resolve-provider-context.ts`:
- Around line 218-233: In formatTimeUntilReset, extract the repeated 60 * 60 *
1000 expression into a local constant such as HOUR_IN_MS, then reuse it for both
the threshold check and totalHours calculation without changing the existing
behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 78b2b81d-3980-4fd2-8249-4cc694195b0e
📒 Files selected for processing (2)
apps/gateway/src/chat/tools/resolve-provider-context.spec.tsapps/gateway/src/chat/tools/resolve-provider-context.ts
steebchen
approved these changes
Jul 15, 2026
smakosh
added this pull request to the merge queue
Jul 15, 2026
huangyingting
pushed a commit
to repomesh/llmgateway
that referenced
this pull request
Jul 15, 2026
## Summary DevPass users had no way to see which models actually count against the weekly premium allowance — the docs described a $5/$15 threshold while marketing surfaces used informal "flagship"/"cheap" tags, and the allowance itself was only visible when you hit the 402. This PR surfaces the exact classification the gateway enforces (`isPremiumModel`: $5+/M input or $15+/M output on any provider mapping) across all user-facing surfaces. ## Changes ### llmgateway.io /models (apps/ui) - **Pricing Tier filter** (All/Premium/Standard) with `?tier=` URL param, stacked under Use Case so the filter panel stays on one row. Since the tier only matters for DevPass fair-use limits, it is **hidden by default** on llmgateway.io — it appears when the visitor arrives from DevPass (`?from=devpass`), or when a `?tier=` deep link is active, and is labeled "Pricing Tier (DevPass)" - **Gem icon** on premium model rows with a tooltip explaining the threshold and DevPass weekly cap - Models are annotated with `premium` **server-side** in `fetchModels()` using the same `isPremiumModel` function the gateway uses for enforcement — the catalogue never enters the client bundle - **New `/models/premium` SEO category page** listing exactly the premium models, with FAQs; linked from the directory, sitemap, and the docs model-categories page ### devpass.llmgateway.io /models (apps/code, new page) - Full models directory with the **same search, filters (incl. pricing tier, always visible here), sorting, and pagination** as llmgateway.io — the `AllModels` component tree (all-models, model-card, status badge, code-example dialog, category filters, API types/fetchers) moved to `@llmgateway/shared/components` and is now rendered by both apps - App-specific bits are injected per app: footer, CTA (`renderCta` render prop — ui passes ModelCtaButton, DevPass passes a Get DevPass button), and `modelHrefBase` so model detail links point at llmgateway.io - DevPass links to the main directory carry `from=devpass` so the tier filter shows there - apps/ui keeps thin shims at the old paths so its ~15 existing consumers are unchanged - Premium vs standard explainer with the weekly allowance percentages derived from `DEV_PLAN_PREMIUM_WEEKLY_PERCENT` ### DevPass dashboard (apps/code) - **Weekly premium allowance progress bar** in the usage card, reusing the existing `UsageBar`, with premium-specific warning copy and a "Resets in N days and M hours" countdown (mirrors the gateway 402 formatting from theopenco#3076) - Backed by new fields on `GET /dev-plans/status`: `devPlanPremiumWeeklyLimit`, `devPlanPremiumCreditsUsed`, `devPlanPremiumWeekResetsAt`, computed with the same shared helpers the gateway/worker use (expired window ⇒ zero usage, no reset date) ### packages/shared - New `components/models-directory/` module + card/table/toggle shadcn primitives; adds `next` and `prism-react-renderer` deps; `@source` entries added to ui/code globals.css for Tailwind scanning; `showPricingTierFilter` prop controls tier-filter visibility per surface ## Verification - Full monorepo build green; `dev-plans.spec.ts` 14/14 passing - Verified live against the seeded DB: /models/premium server-filtered JSON-LD (40 premium models, no standard leakage), DevPass /models premium/standard split (Gemini 3.1 Pro correctly standard, Opus 4.8 premium), `/dev-plans/status` fields for fresh + active windows (Pro: 35.55 limit, resets exactly weekStart+7d), and the dashboard bar rendered in-browser; user verified the running stack manually https://claude.ai/code/session_01NeqtWHWHmyug3BXUv3JmV9 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Premium models browsing (directory + Premium models page) with table/card views, filtering, sorting, provider/pricing details, and updated CTA. * Updated the dashboard Usage view to display weekly Premium fair-use usage/allowance and the next reset time. * **Documentation** * Refreshed Premium vs Standard guidance to describe automatic classification and fair-use behavior. * **SEO / Navigation** * Added Premium models and `/models` routes to the sitemap, and improved internal links to surface Premium context across the app. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This was referenced Aug 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #3074. The DevPass weekly premium-cap 402 error rounded the remaining wait up to whole days: 6 days and a few hours displayed as "Resets in 7 days", and even a 20-minute wait showed "Resets in 1 day".
The message now shows the remaining time as days and hours, e.g. "Resets in 6 days and 3 hours.":
Changes
apps/gateway/src/chat/tools/resolve-provider-context.ts: replaced the whole-day ceil with aformatTimeUntilReset()helper used in the 402 message.apps/gateway/src/chat/tools/resolve-provider-context.spec.ts: unit tests for the formatter (rounding, zero components, singular/plural, sub-hour).Testing
vitest run apps/gateway/src/chat/tools/resolve-provider-context.spec.ts— 10/10 passingturbo run build --filter=gateway— builds cleanhttps://claude.ai/code/session_01NeqtWHWHmyug3BXUv3JmV9
Summary by CodeRabbit