/** * Test script to diagnose Groq API issues with TFL status summarization */ const apiKey = process.env.GROQ_API_KEY if (!apiKey || apiKey.trim() === "") { console.error("ERROR: GROQ_API_KEY is not set or empty") console.error("Please check your .env file") console.error("Add: GROQ_API_KEY=your_api_key_here") process.exit(1) } console.log(`API Key found (length: ${apiKey.length}, starts with: ${apiKey.substring(0, 10)}...)`) // Sample TFL disruption data (similar to what the real code sends) const sampleDisruptions = [ { lineName: "Piccadilly", status: "Part Suspended", reason: "Piccadilly Line: No service between Rayners Lane and Uxbridge due to Storm Benjamin. Use Metropolitan line services between Rayners Lane and Uxbridge. Good service on the rest of the line." }, { lineName: "Central", status: "Minor Delays", reason: "Central Line: Minor delays due to train cancellations." } ] // Build the same prompt that the real code uses function buildBatchShorteningPrompt(disruptions: typeof sampleDisruptions): string { const disruptionsList = disruptions.map((d, i) => `${i + 1}. Line: ${d.lineName}\n Status: ${d.status}\n Message: "${d.reason}"` ).join('\n\n') return `Shorten these London transport disruption messages for a dashboard display. Return your response as a JSON array. Disruptions to shorten: ${disruptionsList} Requirements: - Keep each shortened message under 80 characters - Be concise but keep essential information (reason, locations, alternatives, time info) - DO NOT include line names in the shortened text (they're displayed separately) - Use natural, clear language - NO emojis Return ONLY a JSON array in this exact format: [ {"lineName": "Piccadilly", "shortened": "Suspended Rayners Lane-Uxbridge until Fri due to Storm Benjamin. Use Metropolitan line."}, {"lineName": "Central", "shortened": "Minor delays due to train cancellations"}, ... ] Good examples of shortened messages: - "Suspended Rayners Lane-Uxbridge until Fri due to Storm Benjamin. Use Metropolitan line." - "Minor delays due to train cancellations" - "Minor delays due to earlier incidents at Gospel Oak & Highbury" - "Severe delays - signal failure at King's Cross. Use buses/Elizabeth line." - "No service Earls Court-Wimbledon until Sun 27 Oct (engineering)" Generate JSON array:` } const prompt = buildBatchShorteningPrompt(sampleDisruptions) console.log("\n=== Sending request to Groq API ===\n") console.log("URL:", "https://api.groq.com/openai/v1/chat/completions") console.log("Model:", "openai/gpt-oss-120b") console.log("\nPrompt length:", prompt.length, "characters") console.log("\nFirst 500 chars of prompt:") console.log(prompt.substring(0, 500)) console.log("...\n") const requestBody = { model: "openai/gpt-oss-120b", messages: [ { role: "user", content: prompt, }, ], temperature: 0.3, max_tokens: 2000, top_p: 0.9, } try { console.log("Making API request...\n") const response = await fetch( "https://api.groq.com/openai/v1/chat/completions", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${apiKey}`, }, body: JSON.stringify(requestBody), } ) console.log("=== Response Status ===") console.log(`Status: ${response.status} ${response.statusText}`) console.log(`OK: ${response.ok}`) console.log("\n=== Response Headers ===") for (const [key, value] of response.headers.entries()) { console.log(`${key}: ${value}`) } if (!response.ok) { const errorText = await response.text() console.log("\n=== Error Response Body ===") console.log(errorText) try { const errorJson = JSON.parse(errorText) console.log("\n=== Parsed Error JSON ===") console.log(JSON.stringify(errorJson, null, 2)) } catch { // Not JSON, that's fine } process.exit(1) } const data = await response.json() console.log("\n=== Full API Response ===") console.log(JSON.stringify(data, null, 2)) console.log("\n=== Extracting Response Text ===") const responseText = data.choices?.[0]?.message?.content?.trim() || "" if (!responseText) { console.error("ERROR: Response text is empty!") console.log("Response structure:") console.log("- choices exists:", !!data.choices) console.log("- choices[0] exists:", !!data.choices?.[0]) console.log("- message exists:", !!data.choices?.[0]?.message) console.log("- content exists:", !!data.choices?.[0]?.message?.content) process.exit(1) } console.log("\n=== Response Text ===") console.log(responseText) console.log("\n=== Response Text Length ===") console.log(responseText.length, "characters") // Try to parse JSON console.log("\n=== Attempting to Parse JSON ===") let jsonText = responseText const jsonMatch = responseText.match(/```json\s*([\s\S]*?)\s*```/) if (jsonMatch) { console.log("Found JSON in markdown code block") jsonText = jsonMatch[1] } else { console.log("No markdown code block found, using response text directly") } try { const shortened = JSON.parse(jsonText) console.log("\n=== Successfully Parsed JSON ===") console.log(JSON.stringify(shortened, null, 2)) if (Array.isArray(shortened)) { console.log("\n=== Summary ===") console.log(`Parsed ${shortened.length} items:`) for (const item of shortened) { console.log(` - ${item.lineName}: "${item.shortened}"`) } } else { console.log("WARNING: Response is not an array!") } } catch (parseError) { console.error("\n=== JSON Parse Error ===") console.error(parseError) console.log("\n=== Text that failed to parse ===") console.log(jsonText) process.exit(1) } console.log("\n✅ Test completed successfully!") } catch (error) { console.error("\n=== Request Failed ===") console.error(error) if (error instanceof Error) { console.error("Error message:", error.message) console.error("Error stack:", error.stack) } process.exit(1) }