Show hosted demo credits popup#576
Open
vishxrad wants to merge 2 commits into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a consistent “hosted demo credits exhausted” detection + UI flow across docs demo surfaces, so users see a friendly dialog with local-run instructions instead of confusing provider/streaming failures.
Changes:
- Introduces a shared
demo-creditsutility for normalizing credit-exhaustion detection into a structured payload + 402 response. - Adds a reusable
DemoCreditsDialogcomponent and wires it into/playground,/demo/github, and the docs overview chat modal. - Updates docs API routes to translate OpenRouter 402s (and streaming/SDK-flattened credit errors) into the structured payload.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/lib/demo-credits.ts | Adds shared constants, payload helpers, and detection heuristics for credit exhaustion. |
| docs/components/overview-components/chat-modal.tsx | Forks the OpenAI SSE adapter to intercept structured credit errors and display the dialog in the docs chat modal. |
| docs/components/DemoCreditsDialog.tsx | New dialog component presenting the hosted-demo credits message + local run commands. |
| docs/components/DemoCreditsDialog.css | Styling for the credits dialog overlay and content. |
| docs/app/playground/page.tsx | Displays the credits dialog when the playground API returns the structured error payload. |
| docs/app/demo/github/page.tsx | Displays the credits dialog when the GitHub demo streaming route returns the structured error payload. |
| docs/app/api/playground/stream/route.ts | Converts OpenRouter credit-exhaustion failures into the shared structured 402 response. |
| docs/app/api/demo/github/stream/route.ts | Converts OpenRouter credit-exhaustion failures into the shared structured 402 response. |
| docs/app/api/chat/route.ts | Converts SDK/streaming credit errors into a structured SSE frame and adds a missing-key short-circuit. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| }; | ||
|
|
||
| if (isDemoCreditsErrorPayload(json.error)) { | ||
| onCreditsExhausted(); |
Comment on lines
+15
to
+29
| export function DemoCreditsDialog({ open, onClose }: DemoCreditsDialogProps) { | ||
| if (!open) return null; | ||
|
|
||
| return ( | ||
| <div className="demo-credits-dialog-overlay" onClick={onClose}> | ||
| <section | ||
| className="demo-credits-dialog" | ||
| role="dialog" | ||
| aria-modal="true" | ||
| aria-labelledby="demo-credits-dialog-title" | ||
| onClick={(event) => event.stopPropagation()} | ||
| > | ||
| <button className="demo-credits-dialog-close" onClick={onClose} aria-label="Close dialog"> | ||
| <X size={16} /> | ||
| </button> |
|
|
||
| const apiKey = process.env.OPENROUTER_API_KEY; | ||
| if (!apiKey) { | ||
| return createDemoCreditsExhaustedResponse(); |
e24ffe2 to
d5255ca
Compare
Comment on lines
+81
to
+91
| return [ | ||
| DEMO_CREDITS_EXHAUSTED_CODE, | ||
| "insufficient_quota", | ||
| "insufficient credits", | ||
| "insufficient quota", | ||
| "insufficient balance", | ||
| "requires more credits", | ||
| "can only afford", | ||
| "payment required", | ||
| "out of credits", | ||
| ].some((signal) => hasSignal(text, signal)); |
There was a problem hiding this comment.
check openai error chunks for streaming. Also check how OpenRouter gives these error chunks
| signal?: AbortSignal, | ||
| onFirstChunk?: () => void, | ||
| ) { | ||
| ): Promise<"done" | "credits-exhausted"> { |
There was a problem hiding this comment.
make these string consts rather than defining them inline
Comment on lines
+15
to
+29
| export function DemoCreditsDialog({ open, onClose }: DemoCreditsDialogProps) { | ||
| if (!open) return null; | ||
|
|
||
| return ( | ||
| <div className="demo-credits-dialog-overlay" onClick={onClose}> | ||
| <section | ||
| className="demo-credits-dialog" | ||
| role="dialog" | ||
| aria-modal="true" | ||
| aria-labelledby="demo-credits-dialog-title" | ||
| onClick={(event) => event.stopPropagation()} | ||
| > | ||
| <button className="demo-credits-dialog-close" onClick={onClose} aria-label="Close dialog"> | ||
| <X size={16} /> | ||
| </button> |
| }; | ||
|
|
||
| if (isDemoCreditsErrorPayload(json.error)) { | ||
| onCreditsExhausted(); |
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Closes #575
Verification