Job-Scorer / lib /digest-admin-errors.ts
zimejin's picture
Upgrade discovery yield, digest reliability, and runtime UI.
b7bf6e2
Raw
History Blame Contribute Delete
1.89 kB
/**
* Maps raw digest / upstream errors to clear admin-lab messages (not shown to subscribers).
*/
export function classifyDigestAdminError(raw: string): string {
const s = raw.toLowerCase();
if (/429|rate limit|too many requests/.test(s)) {
return "Groq rate limit hit — try later or check quota and DIGEST_SCORE_DELAY_MS.";
}
if (
/resend/i.test(raw) ||
/RESEND_API_KEY/i.test(raw) ||
(s.includes("resend") && /missing|401|403|invalid/i.test(s))
) {
return "Resend API key missing or invalid — check RESEND_API_KEY and sender domain.";
}
if (/SERPER|serper/i.test(raw) || s.includes("missing serper")) {
return "Serper search API not configured — set SERPER_API_KEY.";
}
if (/groq|GROQ_API_KEY|openrouter|OPENROUTER/i.test(raw) && /key|401|403|missing/i.test(s)) {
return "Scoring API key missing or rejected — check GROQ_API_KEY / OPENROUTER_API_KEY on the deployment.";
}
if (/insufficient credits/i.test(s)) {
return "Insufficient credits for this user to run a paid digest.";
}
if (/no listings|no matches|passed threshold|passed today/i.test(s)) {
return raw;
}
return raw;
}
export type DiscoveryFailureKind = "config" | "quota" | "timeout" | "scoring" | "unknown";
/** Classify discovery tool errors for digest handling and user messaging. */
export function classifyDiscoveryFailure(error: string): DiscoveryFailureKind {
const s = error.toLowerCase();
if (
/temporarily unavailable|serper|not configured|missing serper/i.test(s) ||
/job discovery is temporarily unavailable/i.test(s)
) {
return "config";
}
if (/monthly_limit_reached|monthly limit|insufficient credits/i.test(s)) {
return "quota";
}
if (/timed out|timeout/i.test(s)) {
return "timeout";
}
if (/scoring|score failed|couldn't score/i.test(s)) {
return "scoring";
}
return "unknown";
}