mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-01-02 14:22:28 +08:00
fix: display correct quota values in limit toast (#383)
- Parse JSON error response from server to get actual used/limit values - Previously showed 0/0 due to race condition (config fetch vs error) - AI SDK puts full response body in error.message for non-OK responses - Updated all quota toasts (request, token, TPM) to use server values
This commit is contained in:
@@ -557,12 +557,32 @@ Continue from EXACTLY where you stopped.`,
|
||||
},
|
||||
onError: (error) => {
|
||||
// Handle server-side quota limit (429 response)
|
||||
// AI SDK puts the full response body in error.message for non-OK responses
|
||||
try {
|
||||
const data = JSON.parse(error.message)
|
||||
if (data.type === "request") {
|
||||
quotaManager.showQuotaLimitToast(data.used, data.limit)
|
||||
return
|
||||
}
|
||||
if (data.type === "token") {
|
||||
quotaManager.showTokenLimitToast(data.used, data.limit)
|
||||
return
|
||||
}
|
||||
if (data.type === "tpm") {
|
||||
quotaManager.showTPMLimitToast(data.limit)
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
// Not JSON, fall through to string matching for backwards compatibility
|
||||
}
|
||||
|
||||
// Fallback to string matching
|
||||
if (error.message.includes("Daily request limit")) {
|
||||
quotaManager.showQuotaLimitToast()
|
||||
return
|
||||
}
|
||||
if (error.message.includes("Daily token limit")) {
|
||||
quotaManager.showTokenLimitToast(dailyTokenLimit)
|
||||
quotaManager.showTokenLimitToast()
|
||||
return
|
||||
}
|
||||
if (
|
||||
|
||||
@@ -18,36 +18,39 @@ export interface QuotaConfig {
|
||||
* This hook only provides UI feedback when limits are exceeded.
|
||||
*/
|
||||
export function useQuotaManager(config: QuotaConfig): {
|
||||
showQuotaLimitToast: () => void
|
||||
showTokenLimitToast: (used: number) => void
|
||||
showTPMLimitToast: () => void
|
||||
showQuotaLimitToast: (used?: number, limit?: number) => void
|
||||
showTokenLimitToast: (used?: number, limit?: number) => void
|
||||
showTPMLimitToast: (limit?: number) => void
|
||||
} {
|
||||
const { dailyRequestLimit, dailyTokenLimit, tpmLimit } = config
|
||||
const dict = useDictionary()
|
||||
|
||||
// Show quota limit toast (request-based)
|
||||
const showQuotaLimitToast = useCallback(() => {
|
||||
const showQuotaLimitToast = useCallback(
|
||||
(used?: number, limit?: number) => {
|
||||
toast.custom(
|
||||
(t) => (
|
||||
<QuotaLimitToast
|
||||
used={dailyRequestLimit}
|
||||
limit={dailyRequestLimit}
|
||||
used={used ?? dailyRequestLimit}
|
||||
limit={limit ?? dailyRequestLimit}
|
||||
onDismiss={() => toast.dismiss(t)}
|
||||
/>
|
||||
),
|
||||
{ duration: 15000 },
|
||||
)
|
||||
}, [dailyRequestLimit])
|
||||
},
|
||||
[dailyRequestLimit],
|
||||
)
|
||||
|
||||
// Show token limit toast
|
||||
const showTokenLimitToast = useCallback(
|
||||
(used: number) => {
|
||||
(used?: number, limit?: number) => {
|
||||
toast.custom(
|
||||
(t) => (
|
||||
<QuotaLimitToast
|
||||
type="token"
|
||||
used={used}
|
||||
limit={dailyTokenLimit}
|
||||
used={used ?? dailyTokenLimit}
|
||||
limit={limit ?? dailyTokenLimit}
|
||||
onDismiss={() => toast.dismiss(t)}
|
||||
/>
|
||||
),
|
||||
@@ -58,15 +61,21 @@ export function useQuotaManager(config: QuotaConfig): {
|
||||
)
|
||||
|
||||
// Show TPM limit toast
|
||||
const showTPMLimitToast = useCallback(() => {
|
||||
const showTPMLimitToast = useCallback(
|
||||
(limit?: number) => {
|
||||
const effectiveLimit = limit ?? tpmLimit
|
||||
const limitDisplay =
|
||||
tpmLimit >= 1000 ? `${tpmLimit / 1000}k` : String(tpmLimit)
|
||||
effectiveLimit >= 1000
|
||||
? `${effectiveLimit / 1000}k`
|
||||
: String(effectiveLimit)
|
||||
const message = formatMessage(dict.quota.tpmMessageDetailed, {
|
||||
limit: limitDisplay,
|
||||
seconds: 60,
|
||||
})
|
||||
toast.error(message, { duration: 8000 })
|
||||
}, [tpmLimit, dict])
|
||||
},
|
||||
[tpmLimit, dict],
|
||||
)
|
||||
|
||||
return {
|
||||
showQuotaLimitToast,
|
||||
|
||||
Reference in New Issue
Block a user