import { readFileSync } from 'node:fs'; import { askTrackedWithImages, askTracked, deterministicSeed } from '@detiq/agents'; import type { LLMConfig } from '@detiq/agents'; import { AppBrain } from '@detiq/app-brain'; export interface FailureContext { tenantId?: string; error: string; stepDescription?: string; consoleLogs?: Array<{ type: string; text: string }>; networkErrors?: Array<{ url: string; status: number; method: string }>; screenshotPath?: string; } export async function analyzeFailure(ctx: FailureContext): Promise { try { let llmCfg: LLMConfig | undefined; if (ctx.tenantId) { llmCfg = await AppBrain.getTaskLLMConfig(ctx.tenantId, 'testRunner').catch(() => undefined) as LLMConfig | undefined ?? undefined; } if (!llmCfg) return null; const consoleSection = ctx.consoleLogs?.length ? `\n\nBrowser console (last ${ctx.consoleLogs.length} entries):\n${ctx.consoleLogs.map(l => `[${l.type}] ${l.text}`).join('\n')}` : ''; const networkSection = ctx.networkErrors?.length ? `\n\nFailed network requests:\n${ctx.networkErrors.map(n => `${n.method} ${n.url} → ${n.status}`).join('\n')}` : ''; const userText = `A Playwright automated test failed. Identify the root cause in 2-3 sentences. Be specific — name the failing element, API endpoint, or error type. Do not suggest fixes. Test step: ${ctx.stepDescription ?? 'unknown'} Error: ${ctx.error}${consoleSection}${networkSection}`; if (ctx.screenshotPath) { try { const img = readFileSync(ctx.screenshotPath); const result = await askTrackedWithImages('', userText, [{ base64: img.toString('base64'), mediaType: 'image/png' }], llmCfg); return result.text || null; } catch { /* fall through to text-only */ } } const failureSeed = deterministicSeed(`${ctx.tenantId ?? ''}:failure:${(ctx.stepDescription ?? '').slice(0, 100)}:${ctx.error.slice(0, 200)}`); const result = await askTracked('', userText, llmCfg, 256, undefined, { temperature: 0, seed: failureSeed }); return result.text || null; } catch { return null; } }