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
JavaScript
;
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;
}
});
}