UNPKG

ai-ctrf

Version:

Generate AI summaries of test results using a wide range of AI models like OpenAI, Anthropic, Gemini, Mistral, Grok, DeepSeek, Azure, Perplexity, OpenRouter, and custom OpenAI-compatible APIs

176 lines (170 loc) 9.72 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateJsonSummary = generateJsonSummary; const openai_1 = require("./models/openai"); const claude_1 = require("./models/claude"); const azure_openai_1 = require("./models/azure-openai"); const grok_1 = require("./models/grok"); const deepseek_1 = require("./models/deepseek"); const gemini_1 = require("./models/gemini"); const perplexity_1 = require("./models/perplexity"); const openrouter_1 = require("./models/openrouter"); const bedrock_1 = require("./models/bedrock"); const custom_1 = require("./models/custom"); function generateJsonSummary(report, model, args, customUrl) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; const failedTests = report.results.tests.filter((test) => test.status === 'failed'); const testDetails = []; let testCount = 0; for (const test of failedTests) { if (args.maxMessages != null && testCount >= args.maxMessages) { break; } let detail = `Test Name: ${test.name}\n`; if (test.message != null && test.message.trim() !== '') { detail += `Message: ${test.message}\n`; } if (test.trace != null && test.trace.trim() !== '') { detail += `Trace: ${test.trace}\n`; } if (test.ai != null && test.ai.trim() !== '') { detail += `AI Summary: ${test.ai}\n`; } testDetails.push(detail); testCount++; } let systemPrompt = `You are a test analysis expert. Your task is to analyze test failures and provide structured output in JSON format. Avoid: - Including any code in your response. - Adding generic conclusions or advice such as "By following these steps..." - headings, bullet points, or special formatting. You must respond ONLY with valid JSON in the following structure: { "summary": "High-level overview of what went wrong", "code_issues": "Detailed description of code-related issues that occurred", "timeout_issues": "Detailed description of timeout and performance issues", "application_issues": "Detailed description of application-level issues", "recommendations": "Detailed recommendations for fixing the issues" } Guidelines: - "summary": Provide a concise overview of the test run failures - "code_issues": Describe specific code-related problems (bugs, logic errors, assertion failures, etc.) in a paragraph. If there are no code-related issues, use an empty string. - "timeout_issues": Describe any timeout, performance, or timing-related issues in a paragraph. If there are no timeout-related issues, use an empty string. - "application_issues": Describe application-level problems (configuration, environment, dependencies, etc.) in a paragraph. If there are no application-related issues, use an empty string. - "recommendations": Provide actionable recommendations to fix the issues in a paragraph. If there are no recommendations, use an empty string. Important: - Each field should be a string - If no issues exist for a category, use an empty string "" - Keep descriptions clear and actionable - Do not include code snippets - Respond ONLY with the JSON object, no additional text`; if (args.additionalSystemPromptContext != null && args.additionalSystemPromptContext !== '') { systemPrompt += `\n\nAdditional Context:\n${args.additionalSystemPromptContext}`; } let analysisPrompt = `Analyze the following test failures and provide a structured JSON response. Test Environment: ${report.results.environment != null ? JSON.stringify(report.results.environment) : 'Not specified'} Test Tool: ${report.results.tool.name} Total Tests Run: ${report.results.tests.length} Failed Tests: ${failedTests.length} Passed Tests: ${report.results.summary.passed} ${testCount < failedTests.length ? `\nNote: Showing ${testCount} of ${failedTests.length} failed tests to stay within token limits.\n` : ''} Failed Test Details: ${testDetails.join('\n')} Provide your analysis in the specified JSON format.`; if (args.additionalPromptContext != null && args.additionalPromptContext !== '') { analysisPrompt += `\n\nAdditional Context:\n${args.additionalPromptContext}`; } let jsonResponse = ''; if (model === 'openai') { jsonResponse = (_a = (yield (0, openai_1.openAI)(systemPrompt, analysisPrompt, args))) !== null && _a !== void 0 ? _a : ''; } else if (model === 'claude') { jsonResponse = (_b = (yield (0, claude_1.claudeAI)(systemPrompt, analysisPrompt, args))) !== null && _b !== void 0 ? _b : ''; } else if (model === 'azure') { jsonResponse = (_c = (yield (0, azure_openai_1.azureOpenAI)(systemPrompt, analysisPrompt, args))) !== null && _c !== void 0 ? _c : ''; } else if (model === 'grok') { jsonResponse = (_d = (yield (0, grok_1.grokAI)(systemPrompt, analysisPrompt, args))) !== null && _d !== void 0 ? _d : ''; } else if (model === 'deepseek') { jsonResponse = (_e = (yield (0, deepseek_1.deepseekAI)(systemPrompt, analysisPrompt, args))) !== null && _e !== void 0 ? _e : ''; } else if (model === 'gemini') { jsonResponse = (_f = (yield (0, gemini_1.gemini)(systemPrompt, analysisPrompt, args))) !== null && _f !== void 0 ? _f : ''; } else if (model === 'perplexity') { jsonResponse = (_g = (yield (0, perplexity_1.perplexity)(systemPrompt, analysisPrompt, args))) !== null && _g !== void 0 ? _g : ''; } else if (model === 'openrouter') { jsonResponse = (_h = (yield (0, openrouter_1.openRouter)(systemPrompt, analysisPrompt, args))) !== null && _h !== void 0 ? _h : ''; } else if (model === 'bedrock') { jsonResponse = (_j = (yield (0, bedrock_1.bedrock)(systemPrompt, analysisPrompt, args))) !== null && _j !== void 0 ? _j : ''; } else if (model === 'custom') { jsonResponse = (_k = (yield (0, custom_1.customService)(systemPrompt, analysisPrompt, args, customUrl))) !== null && _k !== void 0 ? _k : ''; } if (jsonResponse === '') { console.error('Failed to generate JSON summary: empty response from model'); return null; } try { let cleanedResponse = jsonResponse.trim(); if (cleanedResponse.startsWith('```json')) { cleanedResponse = cleanedResponse .replace(/^```json\n?/, '') .replace(/\n?```$/, ''); } else if (cleanedResponse.startsWith('```')) { cleanedResponse = cleanedResponse .replace(/^```\n?/, '') .replace(/\n?```$/, ''); } const parsedResponse = JSON.parse(cleanedResponse); if (typeof parsedResponse.summary !== 'string' || typeof parsedResponse.code_issues !== 'string' || typeof parsedResponse.timeout_issues !== 'string' || typeof parsedResponse.application_issues !== 'string' || typeof parsedResponse.recommendations !== 'string') { throw new Error('Invalid JSON structure returned from model'); } if (args.log === true) { console.log(`\n─────────────────────────────────────────────────────────────────────────────────────────────────────────────\n`); console.log(`📊 Structured Analysis Summary:\n`); console.log(`📝 Summary:\n${parsedResponse.summary}\n`); if (parsedResponse.code_issues.trim() !== '') { console.log(`🐛 Code Issues:\n${parsedResponse.code_issues}\n`); } if (parsedResponse.timeout_issues.trim() !== '') { console.log(`⏱️ Timeout Issues:\n${parsedResponse.timeout_issues}\n`); } if (parsedResponse.application_issues.trim() !== '') { console.log(`⚙️ Application Issues:\n${parsedResponse.application_issues}\n`); } if (parsedResponse.recommendations.trim() !== '') { console.log(`💡 Recommendations:\n${parsedResponse.recommendations}\n`); } } return parsedResponse; } catch (error) { console.error('Failed to parse JSON response from model:', error); console.error('Raw response:', jsonResponse); return null; } }); }