mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-01-02 22:32:27 +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) => {
|
onError: (error) => {
|
||||||
// Handle server-side quota limit (429 response)
|
// 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")) {
|
if (error.message.includes("Daily request limit")) {
|
||||||
quotaManager.showQuotaLimitToast()
|
quotaManager.showQuotaLimitToast()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (error.message.includes("Daily token limit")) {
|
if (error.message.includes("Daily token limit")) {
|
||||||
quotaManager.showTokenLimitToast(dailyTokenLimit)
|
quotaManager.showTokenLimitToast()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -18,36 +18,39 @@ export interface QuotaConfig {
|
|||||||
* This hook only provides UI feedback when limits are exceeded.
|
* This hook only provides UI feedback when limits are exceeded.
|
||||||
*/
|
*/
|
||||||
export function useQuotaManager(config: QuotaConfig): {
|
export function useQuotaManager(config: QuotaConfig): {
|
||||||
showQuotaLimitToast: () => void
|
showQuotaLimitToast: (used?: number, limit?: number) => void
|
||||||
showTokenLimitToast: (used: number) => void
|
showTokenLimitToast: (used?: number, limit?: number) => void
|
||||||
showTPMLimitToast: () => void
|
showTPMLimitToast: (limit?: number) => void
|
||||||
} {
|
} {
|
||||||
const { dailyRequestLimit, dailyTokenLimit, tpmLimit } = config
|
const { dailyRequestLimit, dailyTokenLimit, tpmLimit } = config
|
||||||
const dict = useDictionary()
|
const dict = useDictionary()
|
||||||
|
|
||||||
// Show quota limit toast (request-based)
|
// Show quota limit toast (request-based)
|
||||||
const showQuotaLimitToast = useCallback(() => {
|
const showQuotaLimitToast = useCallback(
|
||||||
|
(used?: number, limit?: number) => {
|
||||||
toast.custom(
|
toast.custom(
|
||||||
(t) => (
|
(t) => (
|
||||||
<QuotaLimitToast
|
<QuotaLimitToast
|
||||||
used={dailyRequestLimit}
|
used={used ?? dailyRequestLimit}
|
||||||
limit={dailyRequestLimit}
|
limit={limit ?? dailyRequestLimit}
|
||||||
onDismiss={() => toast.dismiss(t)}
|
onDismiss={() => toast.dismiss(t)}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
{ duration: 15000 },
|
{ duration: 15000 },
|
||||||
)
|
)
|
||||||
}, [dailyRequestLimit])
|
},
|
||||||
|
[dailyRequestLimit],
|
||||||
|
)
|
||||||
|
|
||||||
// Show token limit toast
|
// Show token limit toast
|
||||||
const showTokenLimitToast = useCallback(
|
const showTokenLimitToast = useCallback(
|
||||||
(used: number) => {
|
(used?: number, limit?: number) => {
|
||||||
toast.custom(
|
toast.custom(
|
||||||
(t) => (
|
(t) => (
|
||||||
<QuotaLimitToast
|
<QuotaLimitToast
|
||||||
type="token"
|
type="token"
|
||||||
used={used}
|
used={used ?? dailyTokenLimit}
|
||||||
limit={dailyTokenLimit}
|
limit={limit ?? dailyTokenLimit}
|
||||||
onDismiss={() => toast.dismiss(t)}
|
onDismiss={() => toast.dismiss(t)}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -58,15 +61,21 @@ export function useQuotaManager(config: QuotaConfig): {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Show TPM limit toast
|
// Show TPM limit toast
|
||||||
const showTPMLimitToast = useCallback(() => {
|
const showTPMLimitToast = useCallback(
|
||||||
|
(limit?: number) => {
|
||||||
|
const effectiveLimit = limit ?? tpmLimit
|
||||||
const limitDisplay =
|
const limitDisplay =
|
||||||
tpmLimit >= 1000 ? `${tpmLimit / 1000}k` : String(tpmLimit)
|
effectiveLimit >= 1000
|
||||||
|
? `${effectiveLimit / 1000}k`
|
||||||
|
: String(effectiveLimit)
|
||||||
const message = formatMessage(dict.quota.tpmMessageDetailed, {
|
const message = formatMessage(dict.quota.tpmMessageDetailed, {
|
||||||
limit: limitDisplay,
|
limit: limitDisplay,
|
||||||
seconds: 60,
|
seconds: 60,
|
||||||
})
|
})
|
||||||
toast.error(message, { duration: 8000 })
|
toast.error(message, { duration: 8000 })
|
||||||
}, [tpmLimit, dict])
|
},
|
||||||
|
[tpmLimit, dict],
|
||||||
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
showQuotaLimitToast,
|
showQuotaLimitToast,
|
||||||
|
|||||||
Reference in New Issue
Block a user