From 70e0e8a535011f17500f7044090a6c4f5d9adc47 Mon Sep 17 00:00:00 2001 From: Victor Noguera Date: Thu, 21 May 2026 20:26:37 -0400 Subject: [PATCH] feat: Enhance LLM robustness with improved error handling and model resolution --- src/llm.ts | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/llm.ts b/src/llm.ts index aeee1e8..e96c5ff 100644 --- a/src/llm.ts +++ b/src/llm.ts @@ -111,7 +111,17 @@ export async function analyzeProducts( } return fallback; } - throw err; + + const errorReason = formatErrorReason(err); + console.warn( + `LLM request failed for ${products.length} product(s): ${errorReason}`, + ); + return products.map((product) => ({ + asin: product.record.asin, + verdict: "SKIP" as const, + confidence: 0, + reasoning: `LLM analysis failed: ${errorReason}`, + })); } } @@ -195,6 +205,10 @@ async function requestClaudeContent( ); } + const model = resolveAnthropicModel( + config.anthropicModel ?? "claude-sonnet-4-6", + ); + const res = await fetch("https://api.anthropic.com/v1/messages", { method: "POST", headers: { @@ -203,7 +217,7 @@ async function requestClaudeContent( "anthropic-version": "2023-06-01", }, body: JSON.stringify({ - model: config.anthropicModel, + model, system: systemPrompt, messages: [ { role: "user", content: JSON.stringify(productSummaries, null, 2) }, @@ -230,6 +244,31 @@ async function requestClaudeContent( .join("\n"); } +function resolveAnthropicModel(rawModel: string): string { + const normalized = rawModel.trim().toLowerCase(); + const aliases: Record = { + "claude-4-6-sonnet": "claude-sonnet-4-6", + "claude-4-6-haiku": "claude-haiku-4-5", + "claude-4-7-opus": "claude-opus-4-7", + }; + + const mapped = aliases[normalized]; + if (mapped && mapped !== rawModel) { + console.warn( + `ANTHROPIC_MODEL '${rawModel}' is not an official API ID. Using '${mapped}' instead.`, + ); + return mapped; + } + + return rawModel; +} + +function formatErrorReason(err: unknown): string { + const message = String(err).replace(/\s+/g, " ").trim(); + if (!message) return "Unknown LLM error"; + return message.length > 140 ? `${message.slice(0, 137)}...` : message; +} + async function readErrorBody(response: Response): Promise { const text = await response.text(); if (!text.trim()) return "No response body";