Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 26x 26x 1x 1x 25x 1x 1x 1x 1x 24x 20x 20x 4x 1x 3x 1x 2x 1x 1x 42x 42x 65x 65x 25x 40x 40x 1x 39x | export type QuotaError = {
kind: 'requests' | 'tokens'
used: number
limit: number
window: string
resetAt: Date | null
}
function computeResetAt(window: string): Date | null {
const now = new Date()
if (window === 'monthly') {
// 1st of next calendar month, 00:00 UTC
const d = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1, 0, 0, 0, 0))
return d
}
if (window === 'weekly') {
// Next Monday 00:00 UTC (dayOfWeek: 0=Sun, 1=Mon ... 6=Sat)
const day = now.getUTCDay() // 0=Sun
const daysUntilMonday = day === 0 ? 1 : 8 - day
const d = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + daysUntilMonday))
return d
}
if (window === 'daily') {
// Next midnight UTC
const d = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1))
return d
}
if (window === '1m') {
return new Date(now.getTime() + 60_000)
}
if (window === '5m') {
return new Date(now.getTime() + 5 * 60_000)
}
if (window === '1h') {
return new Date(now.getTime() + 60 * 60_000)
}
return null
}
export function isTooManyRequestsError(error: string): boolean {
const lowerErr = error.toLowerCase()
return lowerErr.includes('429') || lowerErr.includes('unavailable')
}
export function parseQuotaError(error: string): QuotaError | null {
const tokenMatch = error.match(/user token quota exceeded: (\d+)\/(\d+) tokens used \(window: (\w+)\)/)
if (tokenMatch) {
return {
kind: 'tokens',
used: Number(tokenMatch[1]),
limit: Number(tokenMatch[2]),
window: tokenMatch[3],
resetAt: computeResetAt(tokenMatch[3]),
}
}
const requestMatch = error.match(/user request limit exceeded: (\d+)\/(\d+) requests \(window: (\w+)\)/)
if (requestMatch) {
return {
kind: 'requests',
used: Number(requestMatch[1]),
limit: Number(requestMatch[2]),
window: requestMatch[3],
resetAt: computeResetAt(requestMatch[3]),
}
}
return null
}
|