1export type OrrErrClass = 'permanent' | 'rateLimit' | 'transient' | 'auth' | 'unknown' 3const permanentMsgRe = /model|invalid|not found|deprecat|unsupported/i 4const rateLimitMsgRe = /rate.?limit|429|too many requests|quota|throttl/i 5const transientMsgRe = /network|fetch failed|timeout|econn|etimedout|abort|socket hang up|5\d{2}\b/i 7const classifyByStatus = (code: number): OrrErrClass | undefined => { 8 if (code === 401 || code === 403) return 'auth' 9 if (code === 429) return 'rateLimit' 10 if (code >= 500) return 'transient' 11 if (code === 400 || code === 404) return 'permanent' 15export const classifyOrrErr = (err: any): OrrErrClass => { 16 const msg = String(err?.message || '') 17 const statusMatch = msg.match(/OpenRouter\s+(\d{3})/) || msg.match(/\b(\d{3})\b/) 19 const classified = classifyByStatus(Number(statusMatch[1])) 20 if (classified) return classified 22 if (err?.name === 'AbortError' || transientMsgRe.test(msg)) return 'transient' 23 if (rateLimitMsgRe.test(msg)) return 'rateLimit' 24 if (permanentMsgRe.test(msg)) return 'permanent'