mcp-lab-agent 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -261,7 +261,7 @@ function collectTestFiles(structure, options = {}) {
261
261
  } else if (e.isFile() && isTestFile(e.name)) {
262
262
  const filePath = `${dir}/${rel}`;
263
263
  if (pattern && !filePath.toLowerCase().includes(pattern.toLowerCase())) continue;
264
- const inferredFw = inferFrameworkFromFile(e.name, structure);
264
+ const inferredFw = inferFrameworkFromFile(e.name, structure, filePath);
265
265
  if (framework && framework !== "all" && inferredFw !== framework && !matchesFramework(inferredFw, framework)) continue;
266
266
  const entry = { path: filePath, inferredFramework: inferredFw };
267
267
  if (maxContentFiles > 0 && results.length < maxContentFiles) {
@@ -278,7 +278,19 @@ function collectTestFiles(structure, options = {}) {
278
278
  }
279
279
  return results;
280
280
  }
281
- function inferFrameworkFromFile(name, structure = {}) {
281
+ function inferFrameworkFromFile(name, structure = {}, filePath = "") {
282
+ const pathLower = (filePath || "").toLowerCase().replace(/\\/g, "/");
283
+ if (/[\/]cypress[\/\-]/.test(pathLower)) return "cypress";
284
+ if (/[\/]playwright[\/\-]/.test(pathLower)) return "playwright";
285
+ if (/[\/]wdio[\/\-]|[\/]webdriver[\/\-]/.test(pathLower)) return "webdriverio";
286
+ if (/[\/]appium[\/\-]/.test(pathLower)) return "appium";
287
+ if (/[\/]selenium-python[\/]|[\/]pytest[\/\-]/.test(pathLower)) return "pytest";
288
+ if (/[\/]robot[\/\-]/.test(pathLower)) return "robot";
289
+ if (/[\/]codecept[\/\-]/.test(pathLower)) return "codeceptjs";
290
+ if (/[\/]nightwatch[\/\-]/.test(pathLower)) return "nightwatch";
291
+ if (/[\/]testcafe[\/\-]/.test(pathLower)) return "testcafe";
292
+ if (/[\/]puppeteer[\/\-]/.test(pathLower)) return "puppeteer";
293
+ if (/[\/]behave[\/\-]|[\/]features[\/]/.test(pathLower)) return "behave";
282
294
  if (/\.cy\.(js|ts|jsx|tsx)/i.test(name)) return "cypress";
283
295
  if (/_test\.(js|ts)$/i.test(name)) return "codeceptjs";
284
296
  if (/\.spec\.(js|ts|jsx|tsx)/i.test(name)) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.js"],"sourcesContent":["#!/usr/bin/env node\n/**\n * MCP Lab Agent - Standalone\n * MCP server genérico para QA automation em qualquer projeto.\n * Detecta automaticamente Cypress, Playwright, Jest, estrutura do projeto, etc.\n */\nimport { config } from \"dotenv\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { spawn } from \"node:child_process\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\n\nconst PROJECT_ROOT = process.cwd();\nconfig({ path: path.join(PROJECT_ROOT, \".env\") });\n\nconst server = new McpServer({\n name: \"mcp-lab-agent\",\n version: \"1.0.0\",\n});\n\n// ============================================================================\n// DETECÇÃO AUTOMÁTICA DE ESTRUTURA\n// ============================================================================\n\nfunction detectProjectStructure() {\n const structure = {\n hasTests: false,\n testFrameworks: [],\n testDirs: [],\n hasBackend: false,\n backendDir: null,\n hasFrontend: false,\n frontendDir: null,\n hasMobile: false,\n packageJson: null,\n pythonRequirements: null,\n };\n\n // Detectar Node.js/JavaScript/TypeScript\n const pkgPath = path.join(PROJECT_ROOT, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n structure.packageJson = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n const deps = {\n ...structure.packageJson.dependencies,\n ...structure.packageJson.devDependencies,\n };\n\n // Frameworks E2E/UI\n if (deps.cypress) {\n structure.testFrameworks.push(\"cypress\");\n structure.hasTests = true;\n }\n if (deps[\"@playwright/test\"] || deps.playwright) {\n structure.testFrameworks.push(\"playwright\");\n structure.hasTests = true;\n }\n if (deps.webdriverio || deps[\"@wdio/cli\"]) {\n structure.testFrameworks.push(\"webdriverio\");\n structure.hasTests = true;\n }\n\n // Frameworks Unit/Integration\n if (deps.jest) {\n structure.testFrameworks.push(\"jest\");\n structure.hasTests = true;\n }\n if (deps.vitest) {\n structure.testFrameworks.push(\"vitest\");\n structure.hasTests = true;\n }\n if (deps.mocha) {\n structure.testFrameworks.push(\"mocha\");\n structure.hasTests = true;\n }\n if (deps.jasmine) {\n structure.testFrameworks.push(\"jasmine\");\n structure.hasTests = true;\n }\n\n // Frameworks Mobile\n if (deps.appium || deps[\"appium-webdriverio\"]) {\n structure.testFrameworks.push(\"appium\");\n structure.hasTests = true;\n structure.hasMobile = true;\n }\n if (deps.detox) {\n structure.testFrameworks.push(\"detox\");\n structure.hasTests = true;\n structure.hasMobile = true;\n }\n\n // API Testing\n if (deps.supertest) {\n structure.testFrameworks.push(\"supertest\");\n structure.hasTests = true;\n }\n if (deps[\"@pactum/pactum\"] || deps.pactum) {\n structure.testFrameworks.push(\"pactum\");\n structure.hasTests = true;\n }\n\n // Outros frameworks E2E\n if (deps.testcafe || deps[\"testcafe\"]) {\n structure.testFrameworks.push(\"testcafe\");\n structure.hasTests = true;\n }\n if (deps.nightwatch || deps[\"nightwatch\"]) {\n structure.testFrameworks.push(\"nightwatch\");\n structure.hasTests = true;\n }\n if (deps.puppeteer) {\n structure.testFrameworks.push(\"puppeteer\");\n structure.hasTests = true;\n }\n if (deps.codeceptjs || deps[\"codeceptjs\"]) {\n structure.testFrameworks.push(\"codeceptjs\");\n structure.hasTests = true;\n }\n\n // Backend detection\n if (deps.express || deps.fastify || deps[\"@nestjs/core\"] || deps.koa) {\n structure.hasBackend = true;\n }\n \n // Frontend detection\n if (deps.next || deps.react || deps.vue || deps.svelte || deps.angular) {\n structure.hasFrontend = true;\n }\n }\n\n // Detectar Python (Robot Framework, pytest, etc.)\n const requirementsPath = path.join(PROJECT_ROOT, \"requirements.txt\");\n if (fs.existsSync(requirementsPath)) {\n const requirements = fs.readFileSync(requirementsPath, \"utf8\");\n structure.pythonRequirements = requirements;\n\n if (/robotframework/i.test(requirements)) {\n structure.testFrameworks.push(\"robot\");\n structure.hasTests = true;\n }\n if (/pytest/i.test(requirements)) {\n structure.testFrameworks.push(\"pytest\");\n structure.hasTests = true;\n }\n if (/behave/i.test(requirements)) {\n structure.testFrameworks.push(\"behave\");\n structure.hasTests = true;\n }\n if (/requests/i.test(requirements)) {\n structure.hasBackend = true;\n }\n }\n\n // Detectar pastas de teste (genérico)\n const commonTestDirs = [\n \"tests\", \"test\", \"e2e\", \"cypress\", \"playwright\", \"__tests__\",\n \"specs\", \"spec\", \"integration\", \"unit\", \"functional\", \"robot\",\n \"features\", \"scenarios\", \"mobile\", \"api\",\n // Monorepo: subprojetos por framework\n \"playwright-js\", \"puppeteer-js\", \"testcafe-js\", \"wdio-webdriver-io\",\n \"nightwatch-js\", \"codeceptjs\", \"robot-framework\", \"selenium-python\"\n ];\n for (const dir of commonTestDirs) {\n const fullPath = path.join(PROJECT_ROOT, dir);\n if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {\n structure.testDirs.push(dir);\n }\n }\n\n // Monorepo: escanear subdirs de primeiro nível que parecem ter testes\n const skipDirs = [\"node_modules\", \".git\", \"dist\", \"build\", \".next\", \".venv\"];\n try {\n const rootEntries = fs.readdirSync(PROJECT_ROOT, { withFileTypes: true });\n for (const e of rootEntries) {\n if (!e.isDirectory() || skipDirs.includes(e.name)) continue;\n const subPath = path.join(PROJECT_ROOT, e.name);\n if (structure.testDirs.includes(e.name)) continue;\n // Verificar se há package.json ou tests/ dentro\n const hasPkg = fs.existsSync(path.join(subPath, \"package.json\"));\n const hasTests = fs.existsSync(path.join(subPath, \"tests\")) ||\n fs.existsSync(path.join(subPath, \"test\")) ||\n fs.existsSync(path.join(subPath, \"e2e\")) ||\n fs.existsSync(path.join(subPath, \"__tests__\")) ||\n fs.existsSync(path.join(subPath, \"specs\"));\n if (hasPkg || hasTests) {\n structure.testDirs.push(e.name);\n }\n }\n } catch {}\n\n // Monorepo: detectar frameworks em package.json de subdirs\n for (const dir of structure.testDirs) {\n const subPkg = path.join(PROJECT_ROOT, dir, \"package.json\");\n if (!fs.existsSync(subPkg)) continue;\n try {\n const sub = JSON.parse(fs.readFileSync(subPkg, \"utf8\"));\n const subDeps = { ...(sub.dependencies || {}), ...(sub.devDependencies || {}) };\n const toAdd = [];\n if (subDeps.cypress && !structure.testFrameworks.includes(\"cypress\")) toAdd.push(\"cypress\");\n if ((subDeps[\"@playwright/test\"] || subDeps.playwright) && !structure.testFrameworks.includes(\"playwright\")) toAdd.push(\"playwright\");\n if ((subDeps.webdriverio || subDeps[\"@wdio/cli\"]) && !structure.testFrameworks.includes(\"webdriverio\")) toAdd.push(\"webdriverio\");\n if (subDeps.testcafe && !structure.testFrameworks.includes(\"testcafe\")) toAdd.push(\"testcafe\");\n if (subDeps.nightwatch && !structure.testFrameworks.includes(\"nightwatch\")) toAdd.push(\"nightwatch\");\n if (subDeps.puppeteer && !structure.testFrameworks.includes(\"puppeteer\")) toAdd.push(\"puppeteer\");\n if (subDeps.codeceptjs && !structure.testFrameworks.includes(\"codeceptjs\")) toAdd.push(\"codeceptjs\");\n if (subDeps.jest && !structure.testFrameworks.includes(\"jest\")) toAdd.push(\"jest\");\n toAdd.forEach((fw) => { structure.testFrameworks.push(fw); structure.hasTests = true; });\n } catch {}\n }\n\n // Monorepo: detectar Robot/pytest em requirements.txt de subdirs\n for (const dir of structure.testDirs) {\n const reqPath = path.join(PROJECT_ROOT, dir, \"requirements.txt\");\n if (!fs.existsSync(reqPath)) continue;\n try {\n const req = fs.readFileSync(reqPath, \"utf8\");\n if (/robotframework/i.test(req) && !structure.testFrameworks.includes(\"robot\")) {\n structure.testFrameworks.push(\"robot\");\n structure.hasTests = true;\n }\n if (/pytest|selenium/i.test(req) && !structure.testFrameworks.includes(\"pytest\")) {\n structure.testFrameworks.push(\"pytest\");\n structure.hasTests = true;\n }\n } catch {}\n }\n\n // Detectar backend\n const commonBackendDirs = [\"backend\", \"server\", \"api\", \"src\"];\n for (const dir of commonBackendDirs) {\n const fullPath = path.join(PROJECT_ROOT, dir);\n if (fs.existsSync(fullPath) && !structure.backendDir) {\n const hasServerFile = fs.existsSync(path.join(fullPath, \"server.js\")) ||\n fs.existsSync(path.join(fullPath, \"index.js\")) ||\n fs.existsSync(path.join(fullPath, \"app.js\"));\n if (hasServerFile) {\n structure.backendDir = dir;\n }\n }\n }\n\n // Detectar frontend\n const commonFrontendDirs = [\"frontend\", \"client\", \"web\", \"app\", \"src\"];\n for (const dir of commonFrontendDirs) {\n const fullPath = path.join(PROJECT_ROOT, dir);\n if (fs.existsSync(fullPath) && !structure.frontendDir) {\n const hasAppFile = fs.existsSync(path.join(fullPath, \"App.js\")) ||\n fs.existsSync(path.join(fullPath, \"App.tsx\")) ||\n fs.existsSync(path.join(fullPath, \"index.html\"));\n if (hasAppFile) {\n structure.frontendDir = dir;\n }\n }\n }\n\n return structure;\n}\n\n// ============================================================================\n// PADRÕES UNIVERSAIS DE ARQUIVOS DE TESTE (qualquer framework)\n// ============================================================================\n\nconst UNIVERSAL_TEST_PATTERNS = [\n /\\.(cy|spec|test)\\.(js|ts|jsx|tsx)$/i,\n /_test\\.(js|ts)$/i, // CodeceptJS\n /\\.robot$/i,\n /\\.feature$/i,\n /^(test_.*|.*_test)\\.py$/i,\n /\\.steps?\\.(js|ts|py)$/i,\n /\\.e2e\\.(js|ts)$/i,\n /\\.it\\.(js|ts)$/i,\n];\n\nfunction isTestFile(name) {\n return UNIVERSAL_TEST_PATTERNS.some((re) => re.test(name));\n}\n\nfunction collectTestFiles(structure, options = {}) {\n const { pattern, framework, maxContentFiles = 0 } = options;\n const results = [];\n\n for (const dir of structure.testDirs) {\n const fullPath = path.join(PROJECT_ROOT, dir);\n const walk = (p, base = \"\") => {\n if (!fs.existsSync(p)) return;\n const entries = fs.readdirSync(p, { withFileTypes: true });\n for (const e of entries) {\n const rel = base ? `${base}/${e.name}` : e.name;\n if (e.isDirectory()) {\n if (e.name === \"node_modules\" || e.name === \".git\" || e.name === \".venv\") continue;\n walk(path.join(p, e.name), rel);\n } else if (e.isFile() && isTestFile(e.name)) {\n const filePath = `${dir}/${rel}`;\n if (pattern && !filePath.toLowerCase().includes(pattern.toLowerCase())) continue;\n const inferredFw = inferFrameworkFromFile(e.name, structure);\n if (framework && framework !== \"all\" && inferredFw !== framework && !matchesFramework(inferredFw, framework)) continue;\n const entry = { path: filePath, inferredFramework: inferredFw };\n if (maxContentFiles > 0 && results.length < maxContentFiles) {\n try {\n entry.content = fs.readFileSync(path.join(PROJECT_ROOT, filePath), \"utf8\");\n } catch {}\n }\n results.push(entry);\n }\n }\n };\n walk(fullPath);\n }\n return results;\n}\n\nfunction inferFrameworkFromFile(name, structure = {}) {\n if (/\\.cy\\.(js|ts|jsx|tsx)/i.test(name)) return \"cypress\";\n if (/_test\\.(js|ts)$/i.test(name)) return \"codeceptjs\";\n if (/\\.spec\\.(js|ts|jsx|tsx)/i.test(name)) {\n if (structure?.testFrameworks?.includes(\"webdriverio\")) return \"webdriverio\";\n if (structure?.testFrameworks?.includes(\"appium\")) return \"appium\";\n return \"playwright\";\n }\n if (/\\.test\\.(js|ts|jsx|tsx)/i.test(name)) return structure?.testFrameworks?.includes(\"vitest\") ? \"vitest\" : \"jest\";\n if (/\\.robot$/i.test(name)) return \"robot\";\n if (/\\.feature$/i.test(name)) return \"behave\";\n if (/\\.(py|steps?\\.py)$/i.test(name) || /^(test_.*|.*_test)\\.py$/i.test(name)) return \"pytest\";\n if (/\\.e2e\\.(js|ts)/i.test(name)) return \"playwright\";\n return \"unknown\";\n}\n\nfunction matchesFramework(inferred, requested) {\n const aliases = { spec: [\"playwright\", \"webdriverio\", \"appium\"] };\n if (inferred === requested) return true;\n return aliases[inferred]?.includes(requested);\n}\n\n// ============================================================================\n// MÉTRICAS DE NEGÓCIO - Helpers\n// ============================================================================\n\nconst METRICS_FILE = path.join(PROJECT_ROOT, \".qa-lab-metrics.json\");\nconst FLOWS_CONFIG_FILE = path.join(PROJECT_ROOT, \"qa-lab-flows.json\");\n\nfunction parseTestRunResult(runOutput, exitCode) {\n let passed = 0;\n let failed = 0;\n const jestMatch = runOutput.match(/Tests:\\s+(\\d+)\\s+passed(?:,\\s*(\\d+)\\s+failed)?/);\n if (jestMatch) {\n passed = parseInt(jestMatch[1], 10);\n failed = jestMatch[2] ? parseInt(jestMatch[2], 10) : 0;\n }\n const cypressPass = runOutput.match(/(\\d+)\\s+passing/);\n const cypressFail = runOutput.match(/(\\d+)\\s+failing/);\n if (cypressPass) passed = parseInt(cypressPass[1], 10);\n if (cypressFail) failed = parseInt(cypressFail[1], 10);\n const pwPass = runOutput.match(/(\\d+)\\s+passed/);\n const pwFail = runOutput.match(/(\\d+)\\s+failed/);\n if (pwPass) passed = parseInt(pwPass[1], 10);\n if (pwFail) failed = parseInt(pwFail[1], 10);\n if (passed === 0 && failed === 0) {\n if (exitCode === 0) passed = 1;\n else failed = 1;\n }\n return { passed, failed };\n}\n\nfunction appendMetricsEvent(event) {\n try {\n let data = { events: [], lastUpdated: new Date().toISOString() };\n if (fs.existsSync(METRICS_FILE)) {\n const raw = fs.readFileSync(METRICS_FILE, \"utf8\");\n try {\n data = JSON.parse(raw);\n } catch {}\n }\n data.events = data.events || [];\n data.events.push({ ...event, timestamp: event.timestamp || new Date().toISOString() });\n data.lastUpdated = new Date().toISOString();\n if (data.events.length > 500) data.events = data.events.slice(-400);\n fs.writeFileSync(METRICS_FILE, JSON.stringify(data, null, 2), \"utf8\");\n } catch {}\n}\n\nfunction extractFailuresFromOutput(runOutput) {\n const failures = [];\n const lines = runOutput.split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (/fail|error|assertion|timeout|element not found|selector/i.test(line)) {\n failures.push({\n test: lines[Math.max(0, i - 1)]?.trim() || \"unknown\",\n message: line.trim().slice(0, 500),\n });\n }\n }\n return failures.slice(0, 20);\n}\n\n// ============================================================================\n// FERRAMENTAS GENÉRICAS\n// ============================================================================\n\nserver.registerTool(\n \"read_file\",\n {\n title: \"Ler qualquer arquivo\",\n description: \"Lê o conteúdo de QUALQUER arquivo do projeto por caminho. Use para specs, page objects, componentes, código fonte - qualquer formato.\",\n inputSchema: z.object({\n path: z.string().describe(\"Caminho relativo ao projeto (ex: cypress/e2e/login.cy.js, src/pages/Login.tsx, tests/login.robot).\"),\n encoding: z.enum([\"utf8\", \"utf-8\"]).optional().describe(\"Encoding. Default: utf8\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n content: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ path: filePath, encoding = \"utf8\" }) => {\n const normalized = filePath.replace(/^\\//, \"\").replace(/\\\\/g, \"/\");\n const fullPath = path.join(PROJECT_ROOT, normalized);\n\n if (!fullPath.startsWith(PROJECT_ROOT)) {\n return {\n content: [{ type: \"text\", text: \"Caminho fora do projeto.\" }],\n structuredContent: { ok: false, error: \"Path outside project\" },\n };\n }\n if (!fs.existsSync(fullPath)) {\n return {\n content: [{ type: \"text\", text: `Arquivo não encontrado: ${normalized}` }],\n structuredContent: { ok: false, error: \"File not found\" },\n };\n }\n const stat = fs.statSync(fullPath);\n if (stat.isDirectory()) {\n return {\n content: [{ type: \"text\", text: \"É um diretório. Use um caminho de arquivo.\" }],\n structuredContent: { ok: false, error: \"Is directory\" },\n };\n }\n\n try {\n const content = fs.readFileSync(fullPath, encoding);\n return {\n content: [{ type: \"text\", text: content }],\n structuredContent: { ok: true, content },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao ler: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\nserver.registerTool(\n \"detect_project\",\n {\n title: \"Detectar estrutura do projeto\",\n description: \"Analisa o projeto e identifica frameworks de teste, pastas, backend, frontend.\",\n inputSchema: z.object({}),\n outputSchema: z.object({\n ok: z.boolean(),\n structure: z.object({\n hasTests: z.boolean(),\n testFrameworks: z.array(z.string()),\n testDirs: z.array(z.string()),\n hasBackend: z.boolean(),\n backendDir: z.string().nullable(),\n hasFrontend: z.boolean(),\n frontendDir: z.string().nullable(),\n }),\n }),\n },\n async () => {\n const structure = detectProjectStructure();\n const summary = [\n `Frameworks de teste: ${structure.testFrameworks.join(\", \") || \"nenhum\"}`,\n `Pastas de teste: ${structure.testDirs.join(\", \") || \"nenhuma\"}`,\n `Backend: ${structure.backendDir || \"não detectado\"}`,\n `Frontend: ${structure.frontendDir || \"não detectado\"}`,\n ].join(\"\\n\");\n\n return {\n content: [{ type: \"text\", text: summary }],\n structuredContent: { ok: true, structure },\n };\n }\n);\n\nserver.registerTool(\n \"run_tests\",\n {\n title: \"Executar testes\",\n description: \"Roda testes do projeto. Suporta: Cypress, Playwright, WebdriverIO, Jest, Vitest, Mocha, Appium, Detox, Robot Framework, pytest, e mais. Detecta automaticamente.\",\n inputSchema: z.object({\n framework: z.enum([\n \"cypress\", \"playwright\", \"webdriverio\", \"jest\", \"vitest\", \"mocha\",\n \"appium\", \"detox\", \"robot\", \"pytest\", \"supertest\", \"pactum\",\n \"testcafe\", \"nightwatch\", \"puppeteer\", \"codeceptjs\", \"npm\"\n ]).optional().describe(\"Framework específico ou 'npm' para npm test.\"),\n spec: z.string().optional().describe(\"Caminho do spec (ex: cypress/e2e/test.cy.js).\"),\n suite: z.string().optional().describe(\"Suite ou pattern (ex: e2e, api).\"),\n explainOnFailure: z.boolean().optional().describe(\"Se true, quando falhar gera automaticamente: O que aconteceu, Por que falhou, O que fazer, Sugestão de correção. Requer API key.\"),\n }),\n outputSchema: z.object({\n status: z.enum([\"passed\", \"failed\", \"not_found\"]),\n message: z.string(),\n exitCode: z.number(),\n runOutput: z.string().optional(),\n }),\n },\n async ({ framework, spec, suite, explainOnFailure }) => {\n const structure = detectProjectStructure();\n \n if (!structure.hasTests) {\n return {\n content: [{ type: \"text\", text: \"Nenhum framework de teste detectado no projeto.\" }],\n structuredContent: {\n status: \"not_found\",\n message: \"No test framework found\",\n exitCode: 1,\n },\n };\n }\n\n let selectedFramework = framework;\n if (!selectedFramework && structure.testFrameworks.length > 0) {\n selectedFramework = structure.testFrameworks[0];\n }\n\n let cmd, args, cwd;\n\n // E2E/UI Frameworks\n if (selectedFramework === \"cypress\") {\n cmd = \"npx\";\n args = spec ? [\"cypress\", \"run\", \"--spec\", spec] : [\"cypress\", \"run\"];\n cwd = structure.testDirs.includes(\"cypress\") \n ? path.join(PROJECT_ROOT, \"cypress\")\n : structure.testDirs[0] \n ? path.join(PROJECT_ROOT, structure.testDirs[0])\n : PROJECT_ROOT;\n } else if (selectedFramework === \"playwright\") {\n cmd = \"npx\";\n args = spec ? [\"playwright\", \"test\", spec] : [\"playwright\", \"test\"];\n cwd = structure.testDirs.includes(\"playwright\")\n ? path.join(PROJECT_ROOT, \"playwright\")\n : structure.testDirs[0]\n ? path.join(PROJECT_ROOT, structure.testDirs[0])\n : PROJECT_ROOT;\n } else if (selectedFramework === \"webdriverio\") {\n cmd = \"npx\";\n args = spec ? [\"wdio\", \"run\", spec] : [\"wdio\", \"run\"];\n cwd = getFrameworkCwd(structure, [\"wdio-webdriver-io\", \"specs\", \"tests\"]);\n } else if (selectedFramework === \"testcafe\") {\n cmd = \"npx\";\n args = spec ? [\"testcafe\", spec] : [\"testcafe\"];\n cwd = getFrameworkCwd(structure, [\"testcafe-js\", \"testcafe\", \"tests\"]);\n } else if (selectedFramework === \"nightwatch\") {\n cmd = \"npx\";\n args = spec ? [\"nightwatch\", \"--test\", spec] : [\"nightwatch\"];\n cwd = getFrameworkCwd(structure, [\"nightwatch-js\", \"nightwatch\", \"tests\"]);\n } else if (selectedFramework === \"puppeteer\") {\n cmd = \"npx\";\n args = spec ? [\"jest\", spec, \"--config\", \"jest.config.js\"] : [\"jest\"];\n cwd = getFrameworkCwd(structure, [\"puppeteer-js\", \"puppeteer\", \"__tests__\"]);\n } else if (selectedFramework === \"codeceptjs\") {\n cmd = \"npx\";\n args = spec ? [\"codeceptjs\", \"run\", \"--grep\", spec] : [\"codeceptjs\", \"run\"];\n cwd = getFrameworkCwd(structure, [\"codeceptjs\", \"tests\"]);\n\n // Unit/Integration Frameworks\n } else if (selectedFramework === \"jest\") {\n cmd = \"npx\";\n args = [\"jest\"];\n if (spec) args.push(spec);\n cwd = PROJECT_ROOT;\n } else if (selectedFramework === \"vitest\") {\n cmd = \"npx\";\n args = [\"vitest\", \"run\"];\n if (spec) args.push(spec);\n cwd = PROJECT_ROOT;\n } else if (selectedFramework === \"mocha\") {\n cmd = \"npx\";\n args = spec ? [\"mocha\", spec] : [\"mocha\"];\n cwd = PROJECT_ROOT;\n \n // Mobile Frameworks\n } else if (selectedFramework === \"appium\") {\n cmd = \"npx\";\n args = spec ? [\"wdio\", \"run\", spec] : [\"wdio\", \"run\"];\n cwd = PROJECT_ROOT;\n } else if (selectedFramework === \"detox\") {\n cmd = \"npx\";\n args = [\"detox\", \"test\"];\n if (spec) args.push(spec);\n cwd = PROJECT_ROOT;\n \n // Python Frameworks\n } else if (selectedFramework === \"robot\") {\n cmd = \"robot\";\n args = spec ? [spec] : [structure.testDirs[0] || \"tests\"];\n cwd = PROJECT_ROOT;\n } else if (selectedFramework === \"pytest\") {\n cmd = \"pytest\";\n args = spec ? [spec] : [];\n cwd = PROJECT_ROOT;\n \n // API Testing\n } else if (selectedFramework === \"supertest\" || selectedFramework === \"pactum\") {\n cmd = \"npm\";\n args = [\"test\"];\n cwd = PROJECT_ROOT;\n \n // Fallback\n } else {\n cmd = \"npm\";\n args = [\"test\"];\n cwd = PROJECT_ROOT;\n }\n\n const startTime = Date.now();\n return new Promise((resolve) => {\n const child = spawn(cmd, args, {\n cwd,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n shell: process.platform === \"win32\",\n env: { ...process.env },\n });\n\n let stdout = \"\";\n let stderr = \"\";\n if (child.stdout) {\n child.stdout.on(\"data\", (d) => {\n const s = d.toString();\n stdout += s;\n process.stdout.write(s);\n });\n }\n if (child.stderr) {\n child.stderr.on(\"data\", (d) => {\n const s = d.toString();\n stderr += s;\n process.stderr.write(s);\n });\n }\n\n child.on(\"close\", (code) => {\n const runOutput = [stdout, stderr].filter(Boolean).join(\"\\n\").trim();\n const passed = code === 0;\n const durationSeconds = Math.round((Date.now() - startTime) / 1000);\n if (!passed && runOutput) {\n try {\n fs.writeFileSync(path.join(PROJECT_ROOT, \".qa-lab-last-failure.log\"), runOutput, \"utf8\");\n } catch {}\n }\n const { passed: p, failed: f } = parseTestRunResult(runOutput, code);\n appendMetricsEvent({\n type: \"test_run\",\n framework: selectedFramework,\n spec: spec || undefined,\n passed: p,\n failed: f,\n durationSeconds,\n exitCode: code ?? 1,\n failures: !passed ? extractFailuresFromOutput(runOutput) : undefined,\n });\n resolve({\n content: [{ type: \"text\", text: passed ? \"Testes executados com sucesso.\" : \"Falha na execução dos testes.\" }],\n structuredContent: {\n status: passed ? \"passed\" : \"failed\",\n message: passed ? \"Tests passed\" : \"Tests failed\",\n exitCode: code ?? 1,\n runOutput: !passed ? runOutput : undefined,\n },\n });\n });\n });\n }\n);\n\nserver.registerTool(\n \"read_project\",\n {\n title: \"Ler estrutura do projeto\",\n description: \"Lê package.json, specs existentes (qualquer framework: Cypress, Playwright, WDIO, Robot, pytest, etc) e retorna contexto. Use includeContent para trazer código de exemplos.\",\n inputSchema: z.object({\n includeContent: z.boolean().optional().describe(\"Se true, inclui conteúdo dos primeiros 3 arquivos de teste como referência. Default: false.\"),\n maxFiles: z.number().optional().describe(\"Máximo de arquivos cujo conteúdo será lido. Default: 3.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n summary: z.string(),\n packageJson: z.object({}).passthrough().optional(),\n testFiles: z.array(z.string()).optional(),\n testFilesWithContent: z.array(z.object({ path: z.string(), content: z.string() })).optional(),\n }),\n },\n async ({ includeContent = false, maxFiles = 3 } = {}) => {\n const structure = detectProjectStructure();\n const collected = collectTestFiles(structure, {\n maxContentFiles: includeContent ? maxFiles : 0,\n });\n\n const testFiles = collected.map((e) => e.path);\n const testFilesWithContent = includeContent\n ? collected.filter((e) => e.content).map((e) => ({ path: e.path, content: e.content }))\n : undefined;\n\n const summary = [\n `Frameworks: ${structure.testFrameworks.join(\", \") || \"nenhum\"}`,\n `Arquivos de teste: ${testFiles.length} (qualquer framework)`,\n `Backend: ${structure.backendDir || \"não detectado\"}`,\n `Frontend: ${structure.frontendDir || \"não detectado\"}`,\n includeContent && testFilesWithContent?.length\n ? `Conteúdo incluído: ${testFilesWithContent.length} arquivo(s) como referência`\n : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n\n return {\n content: [{ type: \"text\", text: summary }],\n structuredContent: {\n ok: true,\n summary,\n packageJson: structure.packageJson,\n testFiles: testFiles.slice(0, 100),\n testFilesWithContent,\n structure,\n },\n };\n }\n);\n\nserver.registerTool(\n \"generate_tests\",\n {\n title: \"Gerar ou traduzir testes com LLM\",\n description: \"Gera spec em QUALQUER framework. Aceita referência de outro framework: leia com read_file e passe em referenceCode. Traduz automaticamente (ex: Robot→Playwright, Cypress→WDIO).\",\n inputSchema: z.object({\n context: z.string().describe(\"Contexto do projeto (read_project) ou descrição.\"),\n request: z.string().describe(\"O que testar (ex: 'logout flow', 'teste de login') ou 'traduzir o teste abaixo'.\"),\n framework: z.enum([\n \"cypress\", \"playwright\", \"webdriverio\", \"jest\", \"vitest\", \"mocha\",\n \"appium\", \"robot\", \"pytest\", \"supertest\", \"behave\", \"detox\"\n ]).optional().describe(\"Framework alvo (detectado do projeto se omitido).\"),\n referenceCode: z.string().optional().describe(\"Código de referência em QUALQUER framework (Cypress, Robot, WDIO, etc). O LLM traduz/adapta para o framework alvo.\"),\n referencePaths: z.array(z.string()).optional().describe(\"Caminhos de arquivos para ler como referência. O agente lê e usa como padrão.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n specContent: z.string().optional(),\n suggestedFileName: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ context, request, framework, referenceCode, referencePaths }) => {\n const structure = detectProjectStructure();\n const fw = framework || structure.testFrameworks[0] || \"cypress\";\n\n let referenceBlock = \"\";\n if (referenceCode) referenceBlock += `\\n\\n--- CÓDIGO DE REFERÊNCIA (use como padrão, traduza/adapte para ${fw}) ---\\n${referenceCode.slice(0, 8000)}`;\n if (referencePaths?.length) {\n for (const p of referencePaths.slice(0, 5)) {\n const full = path.join(PROJECT_ROOT, p.replace(/^\\//, \"\").replace(/\\\\/g, \"/\"));\n if (fs.existsSync(full)) {\n try {\n const content = fs.readFileSync(full, \"utf8\");\n referenceBlock += `\\n\\n--- Arquivo: ${p} ---\\n${content.slice(0, 6000)}`;\n } catch {}\n }\n }\n }\n\n const GROQ_KEY = process.env.GROQ_API_KEY;\n const GEMINI_KEY = process.env.GEMINI_API_KEY;\n const OPENAI_KEY = process.env.OPENAI_API_KEY || process.env.QA_LAB_LLM_API_KEY;\n\n if (!GROQ_KEY && !GEMINI_KEY && !OPENAI_KEY) {\n return {\n content: [{ type: \"text\", text: \"Configure GROQ_API_KEY, GEMINI_API_KEY ou OPENAI_API_KEY no .env\" }],\n structuredContent: { ok: false, error: \"No API key configured\" },\n };\n }\n\n const provider = GROQ_KEY ? \"groq\" : GEMINI_KEY ? \"gemini\" : \"openai\";\n const apiKey = GROQ_KEY || GEMINI_KEY || OPENAI_KEY;\n const baseUrl = provider === \"groq\" \n ? \"https://api.groq.com/openai/v1\"\n : provider === \"gemini\"\n ? \"https://generativelanguage.googleapis.com/v1beta\"\n : \"https://api.openai.com/v1\";\n const model = provider === \"groq\"\n ? \"llama-3.3-70b-versatile\"\n : provider === \"gemini\"\n ? \"gemini-1.5-flash\"\n : \"gpt-4o-mini\";\n\n const hasReference = Boolean(referenceBlock?.trim());\n const systemPrompt = hasReference\n ? `Você é um engenheiro de QA. TRADUZA/ADAPTE o código de referência para o framework ${fw}.\nO código de referência pode estar em QUALQUER framework (Cypress, Robot, Playwright, WDIO, Appium, pytest, etc).\n- Mantenha a MESMA lógica e fluxo de teste\n- Traduza seletores, comandos e asserções para ${fw}\n- Use Page Objects se o projeto já usa\n- Retorne SOMENTE o código, sem markdown`\n : `Você é um engenheiro de QA especializado em ${fw}. Gere APENAS o código do spec, sem explicações.\nFramework: ${fw}\nRegras:\n- Cypress: cy.request(), cy.visit(), cy.get()\n- Playwright: test(), test.describe(), page.goto(), page.locator()\n- WebdriverIO/Appium: describe(), it(), $(), browser.$\n- Jest/Vitest: describe(), test(), expect()\n- Robot: Keywords, [Tags], Steps\n- pytest: def test_*, assert, fixtures\n- Código limpo. Retorne SOMENTE o código, sem markdown`;\n\n const userPrompt = `Contexto do projeto:\n${context.slice(0, 5000)}\n\nGere um teste para: ${request}\nFramework alvo: ${fw}${referenceBlock}`;\n\n try {\n let specContent;\n if (provider === \"gemini\") {\n const url = `${baseUrl}/models/${model}:generateContent?key=${apiKey}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n systemInstruction: { parts: [{ text: systemPrompt }] },\n contents: [{ parts: [{ text: userPrompt }] }],\n generationConfig: { temperature: 0.3, maxOutputTokens: 4096 },\n }),\n });\n const data = await res.json();\n specContent = data.candidates?.[0]?.content?.parts?.[0]?.text || \"\";\n } else {\n const res = await fetch(`${baseUrl}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userPrompt },\n ],\n temperature: 0.3,\n max_tokens: 4096,\n }),\n });\n const data = await res.json();\n specContent = data.choices?.[0]?.message?.content || \"\";\n }\n\n specContent = specContent.replace(/^```(?:js|javascript)?\\n?/i, \"\").replace(/\\n?```\\s*$/i, \"\").trim();\n const fileName = request.toLowerCase().replace(/\\s+/g, \"-\").replace(/[^a-z0-9-]/g, \"\").slice(0, 40);\n\n return {\n content: [{ type: \"text\", text: `Spec gerado (${specContent.length} chars). Use write_test para gravar.` }],\n structuredContent: {\n ok: true,\n specContent,\n suggestedFileName: fileName,\n },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao gerar: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\nfunction getExtensionAndBaseDir(fw, structure) {\n const extMap = {\n cypress: \".cy.js\",\n playwright: \".spec.js\",\n jest: \".test.js\",\n vitest: \".test.js\",\n mocha: \".test.js\",\n webdriverio: \".spec.js\",\n appium: \".spec.js\",\n detox: \".e2e.js\",\n robot: \".robot\",\n pytest: \"_test.py\",\n behave: \".feature\",\n supertest: \".test.js\",\n pactum: \".test.js\",\n };\n const ext = extMap[fw] || \".spec.js\";\n\n const baseMap = {\n cypress: structure.testDirs.includes(\"cypress\") ? \"cypress\" : structure.testDirs[0] || \"tests\",\n playwright: structure.testDirs.includes(\"playwright\") ? \"playwright\" : structure.testDirs[0] || \"tests\",\n webdriverio: structure.testDirs.includes(\"specs\") ? \"specs\" : structure.testDirs[0] || \"tests\",\n appium: structure.testDirs.includes(\"specs\") ? \"specs\" : structure.testDirs[0] || \"tests\",\n robot: structure.testDirs.includes(\"robot\") ? \"robot\" : structure.testDirs[0] || \"tests\",\n behave: structure.testDirs.includes(\"features\") ? \"features\" : structure.testDirs[0] || \"tests\",\n };\n const baseDir = path.join(PROJECT_ROOT, baseMap[fw] || structure.testDirs[0] || \"tests\");\n return { ext, baseDir };\n}\n\nserver.registerTool(\n \"write_test\",\n {\n title: \"Escrever arquivo de teste\",\n description: \"Grava spec no disco. Suporta QUALQUER framework (Cypress, Playwright, WDIO, Appium, Robot, pytest, etc.). Detecta automaticamente pasta e extensão.\",\n inputSchema: z.object({\n name: z.string().describe(\"Nome do arquivo (ex: login-test, logout_spec).\"),\n content: z.string().describe(\"Conteúdo do spec.\"),\n framework: z.enum([\n \"cypress\", \"playwright\", \"jest\", \"vitest\", \"mocha\", \"webdriverio\",\n \"appium\", \"detox\", \"robot\", \"pytest\", \"behave\", \"supertest\"\n ]).optional().describe(\"Framework (detectado automaticamente se omitido).\"),\n subdir: z.string().optional().describe(\"Subpasta (ex: e2e, api). Default: raiz da pasta de testes.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n path: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ name, content, framework, subdir }) => {\n const structure = detectProjectStructure();\n const fw = framework || structure.testFrameworks[0];\n\n if (!fw) {\n return {\n content: [{ type: \"text\", text: \"Nenhum framework de teste detectado.\" }],\n structuredContent: { ok: false, error: \"No test framework\" },\n };\n }\n\n const { ext, baseDir } = getExtensionAndBaseDir(fw, structure);\n const safeName = name\n .replace(/[^a-z0-9-_]/gi, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/_+/g, \"_\")\n .replace(/\\.(cy|spec|test|robot|feature|py)\\.?(js|ts|py)?$/i, \"\")\n .replace(/^[-_]+|[-_]+$/g, \"\");\n const fileName = ext.startsWith(\"_\") ? `${safeName}${ext}` : `${safeName}${ext}`;\n\n const targetDir = subdir ? path.join(baseDir, subdir) : baseDir;\n const filePath = path.join(targetDir, fileName);\n\n try {\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n fs.writeFileSync(filePath, content, \"utf8\");\n return {\n content: [{ type: \"text\", text: `Arquivo gravado: ${filePath}` }],\n structuredContent: { ok: true, path: filePath },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao gravar: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\nserver.registerTool(\n \"analyze_failures\",\n {\n title: \"Analisar falhas de testes\",\n description: \"Recebe output de testes e extrai falhas estruturadas.\",\n inputSchema: z.object({\n runOutput: z.string().describe(\"Output do teste (stdout/stderr).\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n summary: z.string(),\n failures: z.array(z.object({\n test: z.string().optional(),\n message: z.string().optional(),\n stack: z.string().optional(),\n })).optional(),\n }),\n },\n async ({ runOutput }) => {\n const failures = [];\n const lines = runOutput.split(\"\\n\");\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (/fail|error|assertion/i.test(line)) {\n failures.push({\n test: lines[i - 1] || \"unknown\",\n message: line.trim(),\n stack: lines.slice(i, i + 5).join(\"\\n\"),\n });\n }\n }\n\n const summary = failures.length\n ? `${failures.length} falha(s) detectada(s).`\n : \"Nenhuma falha detectada.\";\n\n return {\n content: [{ type: \"text\", text: summary }],\n structuredContent: { ok: true, summary, failures: failures.length ? failures : undefined },\n };\n }\n);\n\n// ============================================================================\n// POR QUE FALHOU? - Explicação de falhas para juniores (escalável)\n// ============================================================================\n\nfunction formatFailureExplanation(data) {\n const lines = [\n \"## O que aconteceu\",\n \"\",\n data.oQueAconteceu || \"\",\n \"\",\n \"## Por que provavelmente falhou\",\n \"\",\n ...(Array.isArray(data.porQueProvavelmenteFalhou)\n ? data.porQueProvavelmenteFalhou.map((s) => `• ${s}`)\n : [data.porQueProvavelmenteFalhou || \"\"]),\n \"\",\n \"## O que fazer agora\",\n \"\",\n ...(Array.isArray(data.oQueFazerAgora)\n ? data.oQueFazerAgora.map((s, i) => `${i + 1}. ${s}`)\n : [data.oQueFazerAgora || \"\"]),\n ];\n if (data.sugestaoCorrecao) {\n lines.push(\"\", \"## Sugestão de correção\", \"\", \"```\" + (data.framework || \"js\"), data.sugestaoCorrecao, \"```\");\n }\n if (data.conceito) {\n lines.push(\"\", \"## Conceito\", \"\", data.conceito);\n }\n return lines.filter(Boolean).join(\"\\n\");\n}\n\nasync function callLlmForExplanation(provider, apiKey, baseUrl, model, systemPrompt, userPrompt) {\n if (provider === \"gemini\") {\n const url = `${baseUrl}/models/${model}:generateContent?key=${apiKey}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n contents: [{ parts: [{ text: systemPrompt + \"\\n\\n\" + userPrompt }] }],\n generationConfig: { temperature: 0.2, maxOutputTokens: 4096 },\n }),\n });\n const data = await res.json();\n return data.candidates?.[0]?.content?.parts?.[0]?.text || \"\";\n }\n const res = await fetch(`${baseUrl}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userPrompt },\n ],\n temperature: 0.2,\n max_tokens: 4096,\n }),\n });\n const data = await res.json();\n return data.choices?.[0]?.message?.content || \"\";\n}\n\n/** Gera explicação de falha (o que aconteceu, por que, o que fazer, sugestão). Usado por por_que_falhou e run_tests_and_explain. */\nasync function generateFailureExplanation(resolvedOutput, testFilePath = null) {\n const structure = detectProjectStructure();\n const fw = structure.testFrameworks[0] || \"unknown\";\n\n let testCode = \"\";\n if (testFilePath) {\n const normalized = testFilePath.replace(/^\\//, \"\").replace(/\\\\/g, \"/\");\n const fullPath = path.join(PROJECT_ROOT, normalized);\n if (fs.existsSync(fullPath) && !fs.statSync(fullPath).isDirectory()) {\n try {\n testCode = fs.readFileSync(fullPath, \"utf8\");\n } catch {}\n }\n }\n\n const GROQ_KEY = process.env.GROQ_API_KEY;\n const GEMINI_KEY = process.env.GEMINI_API_KEY;\n const OPENAI_KEY = process.env.OPENAI_API_KEY || process.env.QA_LAB_LLM_API_KEY;\n if (!GROQ_KEY && !GEMINI_KEY && !OPENAI_KEY) {\n return { ok: false, error: \"No API key\", formattedText: null };\n }\n\n const provider = GROQ_KEY ? \"groq\" : GEMINI_KEY ? \"gemini\" : \"openai\";\n const apiKey = GROQ_KEY || GEMINI_KEY || OPENAI_KEY;\n const baseUrl = provider === \"groq\"\n ? \"https://api.groq.com/openai/v1\"\n : provider === \"gemini\"\n ? \"https://generativelanguage.googleapis.com/v1beta\"\n : \"https://api.openai.com/v1\";\n const model = provider === \"groq\"\n ? \"llama-3.3-70b-versatile\"\n : provider === \"gemini\"\n ? \"gemini-1.5-flash\"\n : \"gpt-4o-mini\";\n\n const fwHints = {\n webdriverio: \"WebdriverIO (describe/it, $, browser.$)\",\n appium: \"Appium/WebdriverIO (mobile, $, browser.$)\",\n playwright: \"Playwright (test, page, locator)\",\n cypress: \"Cypress (cy.get, cy.click)\",\n jest: \"Jest (describe, test, expect)\",\n vitest: \"Vitest (describe, test, expect)\",\n robot: \"Robot Framework\",\n pytest: \"pytest\",\n };\n\n const systemPrompt = `Você é um mentor de QA. Analise o output de falha e responda em JSON (apenas o JSON, sem markdown) com as chaves:\n- oQueAconteceu: string (explicação em português do que aconteceu, simples)\n- porQueProvavelmenteFalhou: array de strings (lista de possíveis causas, uma por item)\n- oQueFazerAgora: array de strings (passos numerados do que fazer)\n- sugestaoCorrecao: string ou null (código de correção se aplicável, no formato do framework)\n- conceito: string ou null (ex: \"Flaky test = teste intermitente. Geralmente por timing ou seletores frágeis.\")\n- framework: string (framework do projeto)\n\nFramework do projeto: ${fw}. ${fwHints[fw] || \"\"}\nResponda APENAS com o JSON válido, sem texto antes ou depois.`;\n\n const userPrompt = `Output do terminal/log (teste falhou):\n---\n${resolvedOutput.slice(0, 12000)}\n---\n${testCode ? `\\nCódigo do teste que falhou:\\n---\\n${testCode.slice(0, 6000)}\\n---` : \"\"}`;\n\n try {\n let raw = await callLlmForExplanation(provider, apiKey, baseUrl, model, systemPrompt, userPrompt);\n raw = raw.replace(/^```(?:json)?\\s*/i, \"\").replace(/\\s*```\\s*$/i, \"\").trim();\n let data = {};\n try {\n data = JSON.parse(raw);\n } catch {\n data = {\n oQueAconteceu: raw.slice(0, 500) || \"Não foi possível parsear a resposta.\",\n porQueProvavelmenteFalhou: [],\n oQueFazerAgora: [],\n sugestaoCorrecao: null,\n conceito: null,\n framework: fw,\n };\n }\n data.framework = data.framework || fw;\n const formattedText = formatFailureExplanation(data);\n return { ok: true, formattedText, structuredContent: data };\n } catch (err) {\n return { ok: false, error: err.message, formattedText: null };\n }\n}\n\nserver.registerTool(\n \"por_que_falhou\",\n {\n title: \"Por que falhou? Explicação para juniores\",\n description: \"Traduz stack trace em explicação humana. Recebe output do terminal/log, lê o projeto e o teste (se path dado), e retorna: O que aconteceu, Por que falhou, O que fazer, Sugestão de correção, Conceito. Escalável e procedural.\",\n inputSchema: z.object({\n errorOutput: z.string().optional().describe(\"Output do terminal quando o teste falhou. Se vazio, lê automaticamente de .qa-lab-last-failure.log (capturado pelo run_tests). Cole aqui ou deixe vazio para usar última falha.\"),\n testFilePath: z.string().optional().describe(\"Caminho do arquivo de teste que falhou (ex: specs/login.spec.js). Se informado, o agente lê o código e dá sugestão mais precisa.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n oQueAconteceu: z.string().optional(),\n porQueProvavelmenteFalhou: z.array(z.string()).optional(),\n oQueFazerAgora: z.array(z.string()).optional(),\n sugestaoCorrecao: z.string().optional(),\n conceito: z.string().optional(),\n framework: z.string().optional(),\n formattedText: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ errorOutput, testFilePath }) => {\n const structure = detectProjectStructure();\n const fw = structure.testFrameworks[0] || \"unknown\";\n\n let resolvedOutput = errorOutput?.trim() || \"\";\n if (!resolvedOutput) {\n const lastFailurePath = path.join(PROJECT_ROOT, \".qa-lab-last-failure.log\");\n if (fs.existsSync(lastFailurePath)) {\n try {\n resolvedOutput = fs.readFileSync(lastFailurePath, \"utf8\");\n } catch {}\n }\n }\n if (!resolvedOutput) {\n return {\n content: [{\n type: \"text\",\n text: \"Nenhum output de erro fornecido e nenhuma falha recente capturada.\\n\\nComo usar:\\n1. Rode os testes (run_tests) – se falhar, a saída é salva automaticamente.\\n2. Ou cole aqui o output do terminal quando o teste falhou.\\n3. Depois peça: 'Por que falhou?' ou chame por_que_falhou.\",\n }],\n structuredContent: { ok: false, error: \"No error output\" },\n };\n }\n\n let testCode = \"\";\n if (testFilePath) {\n const normalized = testFilePath.replace(/^\\//, \"\").replace(/\\\\/g, \"/\");\n const fullPath = path.join(PROJECT_ROOT, normalized);\n if (fs.existsSync(fullPath) && !fs.statSync(fullPath).isDirectory()) {\n try {\n testCode = fs.readFileSync(fullPath, \"utf8\");\n } catch {}\n }\n }\n\n const GROQ_KEY = process.env.GROQ_API_KEY;\n const GEMINI_KEY = process.env.GEMINI_API_KEY;\n const OPENAI_KEY = process.env.OPENAI_API_KEY || process.env.QA_LAB_LLM_API_KEY;\n\n if (!GROQ_KEY && !GEMINI_KEY && !OPENAI_KEY) {\n return {\n content: [{\n type: \"text\",\n text: \"Configure GROQ_API_KEY, GEMINI_API_KEY ou OPENAI_API_KEY no .env do projeto para usar a explicação com LLM.\",\n }],\n structuredContent: { ok: false, error: \"No API key configured\" },\n };\n }\n\n const provider = GROQ_KEY ? \"groq\" : GEMINI_KEY ? \"gemini\" : \"openai\";\n const apiKey = GROQ_KEY || GEMINI_KEY || OPENAI_KEY;\n const baseUrl = provider === \"groq\"\n ? \"https://api.groq.com/openai/v1\"\n : provider === \"gemini\"\n ? \"https://generativelanguage.googleapis.com/v1beta\"\n : \"https://api.openai.com/v1\";\n const model = provider === \"groq\"\n ? \"llama-3.3-70b-versatile\"\n : provider === \"gemini\"\n ? \"gemini-1.5-flash\"\n : \"gpt-4o-mini\";\n\n const fwHints = {\n webdriverio: \"WebdriverIO (describe/it, $, browser.$)\",\n appium: \"Appium/WebdriverIO (mobile, $, browser.$)\",\n playwright: \"Playwright (test, page, locator)\",\n cypress: \"Cypress (cy.get, cy.click)\",\n jest: \"Jest (describe, test, expect)\",\n vitest: \"Vitest (describe, test, expect)\",\n robot: \"Robot Framework\",\n pytest: \"pytest\",\n };\n\n const systemPrompt = `Você é um mentor de QA. Analise o output de falha e responda em JSON (apenas o JSON, sem markdown) com as chaves:\n- oQueAconteceu: string (explicação em português do que aconteceu, simples)\n- porQueProvavelmenteFalhou: array de strings (lista de possíveis causas, uma por item)\n- oQueFazerAgora: array de strings (passos numerados do que fazer)\n- sugestaoCorrecao: string ou null (código de correção se aplicável, no formato do framework)\n- conceito: string ou null (ex: \"Flaky test = teste intermitente. Geralmente por timing ou seletores frágeis.\")\n- framework: string (framework do projeto)\n\nFramework do projeto: ${fw}. ${fwHints[fw] || \"\"}\nResponda APENAS com o JSON válido, sem texto antes ou depois.`;\n\n const userPrompt = `Output do terminal/log (teste falhou):\n---\n${resolvedOutput.slice(0, 12000)}\n---\n${testCode ? `\\nCódigo do teste que falhou:\\n---\\n${testCode.slice(0, 6000)}\\n---` : \"\"}`;\n\n try {\n let raw = await callLlmForExplanation(provider, apiKey, baseUrl, model, systemPrompt, userPrompt);\n raw = raw.replace(/^```(?:json)?\\s*/i, \"\").replace(/\\s*```\\s*$/i, \"\").trim();\n\n let data = {};\n try {\n data = JSON.parse(raw);\n } catch {\n data = {\n oQueAconteceu: raw.slice(0, 500) || \"Não foi possível parsear a resposta.\",\n porQueProvavelmenteFalhou: [],\n oQueFazerAgora: [],\n sugestaoCorrecao: null,\n conceito: null,\n framework: fw,\n };\n }\n\n data.framework = data.framework || fw;\n const formattedText = formatFailureExplanation(data);\n\n return {\n content: [{ type: \"text\", text: formattedText }],\n structuredContent: {\n ok: true,\n oQueAconteceu: data.oQueAconteceu,\n porQueProvavelmenteFalhou: data.porQueProvavelmenteFalhou,\n oQueFazerAgora: data.oQueFazerAgora,\n sugestaoCorrecao: data.sugestaoCorrecao ?? null,\n conceito: data.conceito ?? null,\n framework: data.framework,\n formattedText,\n },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao analisar: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\n// ============================================================================\n// NOVAS FERRAMENTAS\n// ============================================================================\n\nserver.registerTool(\n \"suggest_fix\",\n {\n title: \"Sugerir correção para falhas\",\n description: \"Recebe análise de falhas e sugere correções (patch, refactor, etc.).\",\n inputSchema: z.object({\n failures: z.array(z.object({\n test: z.string().optional(),\n message: z.string().optional(),\n stack: z.string().optional(),\n })).describe(\"Resultado de analyze_failures.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n suggestions: z.array(z.object({\n test: z.string().optional(),\n description: z.string(),\n fix: z.string().optional(),\n })),\n }),\n },\n async ({ failures }) => {\n const suggestions = [];\n\n for (const f of failures) {\n const msg = f.message || \"\";\n \n if (/element not found|selector|timeout/i.test(msg)) {\n suggestions.push({\n test: f.test,\n description: \"Elemento não encontrado ou timeout\",\n fix: \"Verifique seletores, adicione waits ou aumente timeout. Use data-testid para seletores mais estáveis.\",\n });\n } else if (/expected.*to.*but/i.test(msg)) {\n suggestions.push({\n test: f.test,\n description: \"Asserção falhou\",\n fix: \"Revise o valor esperado. Verifique se o estado da aplicação está correto antes da asserção.\",\n });\n } else if (/network|fetch|ECONNREFUSED/i.test(msg)) {\n suggestions.push({\n test: f.test,\n description: \"Erro de rede ou API não disponível\",\n fix: \"Verifique se o backend está rodando. Confirme a URL e porta da API.\",\n });\n } else {\n suggestions.push({\n test: f.test,\n description: \"Falha detectada\",\n fix: \"Revise o stack trace e o código do teste.\",\n });\n }\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(suggestions, null, 2) }],\n structuredContent: { ok: true, suggestions },\n };\n }\n);\n\n// ============================================================================\n// SELF-HEALING - Sugestão de correção de seletores quando UI muda\n// ============================================================================\n\nserver.registerTool(\n \"suggest_selector_fix\",\n {\n title: \"Sugerir correção de seletor (Self-healing)\",\n description: \"Quando um teste falha por elemento não encontrado (seletor quebrado após mudança de UI), usa LLM para sugerir seletor alternativo mais resiliente. Prioriza data-testid, role, texto acessível.\",\n inputSchema: z.object({\n testFilePath: z.string().describe(\"Caminho do arquivo de teste que falhou (ex: specs/login.spec.js).\"),\n errorOutput: z.string().optional().describe(\"Output do terminal da falha. Se vazio, lê de .qa-lab-last-failure.log.\"),\n framework: z.enum([\"cypress\", \"playwright\", \"webdriverio\", \"appium\"]).optional().describe(\"Framework do teste. Detectado automaticamente se omitido.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n selectorSugerido: z.string().optional(),\n codigoCorrigido: z.string().optional(),\n explicacao: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ testFilePath, errorOutput, framework }) => {\n const structure = detectProjectStructure();\n const fw = framework || inferFrameworkFromFile(testFilePath.split(\"/\").pop(), structure);\n\n let resolvedOutput = errorOutput;\n if (!resolvedOutput) {\n const logPath = path.join(PROJECT_ROOT, \".qa-lab-last-failure.log\");\n if (fs.existsSync(logPath)) {\n resolvedOutput = fs.readFileSync(logPath, \"utf8\");\n }\n }\n if (!resolvedOutput) {\n return {\n content: [{ type: \"text\", text: \"Nenhum output de erro. Rode os testes primeiro ou forneça errorOutput.\" }],\n structuredContent: { ok: false, error: \"No error output\" },\n };\n }\n\n if (!/element not found|selector|timeout|locator|cy\\.get|page\\.locator/i.test(resolvedOutput)) {\n return {\n content: [{ type: \"text\", text: \"A falha não parece ser de seletor/elemento. Use por_que_falhou ou suggest_fix para outros tipos de falha.\" }],\n structuredContent: { ok: false, error: \"Not a selector-related failure\" },\n };\n }\n\n let testCode = \"\";\n const fullPath = path.join(PROJECT_ROOT, testFilePath.replace(/^\\//, \"\").replace(/\\\\/g, \"/\"));\n if (fs.existsSync(fullPath)) {\n try {\n testCode = fs.readFileSync(fullPath, \"utf8\");\n } catch {}\n }\n\n const GROQ_KEY = process.env.GROQ_API_KEY;\n const GEMINI_KEY = process.env.GEMINI_API_KEY;\n const OPENAI_KEY = process.env.OPENAI_API_KEY || process.env.QA_LAB_LLM_API_KEY;\n if (!GROQ_KEY && !GEMINI_KEY && !OPENAI_KEY) {\n return {\n content: [{ type: \"text\", text: \"Configure GROQ_API_KEY, GEMINI_API_KEY ou OPENAI_API_KEY no .env\" }],\n structuredContent: { ok: false, error: \"No API key configured\" },\n };\n }\n\n const provider = GROQ_KEY ? \"groq\" : GEMINI_KEY ? \"gemini\" : \"openai\";\n const apiKey = GROQ_KEY || GEMINI_KEY || OPENAI_KEY;\n const baseUrl = provider === \"groq\" ? \"https://api.groq.com/openai/v1\" : provider === \"gemini\" ? \"https://generativelanguage.googleapis.com/v1beta\" : \"https://api.openai.com/v1\";\n const model = provider === \"groq\" ? \"llama-3.3-70b-versatile\" : provider === \"gemini\" ? \"gemini-1.5-flash\" : \"gpt-4o-mini\";\n\n const fwHints = {\n cypress: \"Cypress: cy.get('[data-testid=...]'), cy.contains(), cy.get('button').filter(':visible')\",\n playwright: \"Playwright: page.getByRole(), page.getByTestId(), page.locator('button:has-text(\\\"...\\\")')\",\n webdriverio: \"WebdriverIO: $('[data-testid=...]'), $('button=Texto')\",\n appium: \"Appium: $('~accessibility-id'), $('//android.view.View')\",\n };\n\n const systemPrompt = `Você é um especialista em testes E2E. O teste falhou porque um seletor não encontrou o elemento (UI mudou).\nAnalise o erro e o código e responda APENAS em JSON (sem markdown) com as chaves:\n- selectorSugerido: string (o novo seletor recomendado, mais resiliente)\n- codigoCorrigido: string (bloco de código completo corrigido, apenas a parte relevante do teste)\n- explicacao: string (breve explicação em português: por que o antigo falhou e por que o novo é melhor)\n\nPriorize nesta ordem: data-testid > role + accessible name > texto visível > estrutura. Evite classes CSS e IDs que mudam.\n\nFramework: ${fw}. ${fwHints[fw] || \"\"}`;\n\n const userPrompt = `Output do erro:\n---\n${resolvedOutput.slice(0, 8000)}\n---\nCódigo do teste:\n---\n${testCode ? testCode.slice(0, 6000) : \"Não disponível\"}\n---`;\n\n try {\n let raw = await callLlmForExplanation(provider, apiKey, baseUrl, model, systemPrompt, userPrompt);\n raw = raw.replace(/^```(?:json)?\\s*/i, \"\").replace(/\\s*```\\s*$/i, \"\").trim();\n let data = {};\n try {\n data = JSON.parse(raw);\n } catch {\n data = {\n selectorSugerido: null,\n codigoCorrigido: raw.slice(0, 2000),\n explicacao: \"Não foi possível parsear. Resposta do LLM acima.\",\n };\n }\n\n const text = [\n data.explicacao && `## Explicação\\n${data.explicacao}`,\n data.selectorSugerido && `## Seletor sugerido\\n\\`${data.selectorSugerido}\\``,\n data.codigoCorrigido && `## Código corrigido\\n\\`\\`\\`${fw}\\n${data.codigoCorrigido}\\n\\`\\`\\``,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n return {\n content: [{ type: \"text\", text: text || JSON.stringify(data, null, 2) }],\n structuredContent: {\n ok: true,\n selectorSugerido: data.selectorSugerido,\n codigoCorrigido: data.codigoCorrigido,\n explicacao: data.explicacao,\n },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao chamar LLM: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\nserver.registerTool(\n \"create_bug_report\",\n {\n title: \"Criar relatório de bug\",\n description: \"Gera um bug report estruturado a partir de falhas de teste.\",\n inputSchema: z.object({\n failures: z.array(z.object({\n test: z.string().optional(),\n message: z.string().optional(),\n stack: z.string().optional(),\n })).describe(\"Falhas (de analyze_failures).\"),\n title: z.string().optional().describe(\"Título do bug.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n report: z.string(),\n title: z.string(),\n }),\n },\n async ({ failures, title }) => {\n const bugTitle = title || `Falha em ${failures.length} teste(s)`;\n const lines = [\n `# ${bugTitle}`,\n \"\",\n \"## Resumo\",\n \"\",\n `${failures.length} teste(s) falharam durante a execução.`,\n \"\",\n \"## Falhas detectadas\",\n \"\",\n ];\n\n failures.forEach((f, i) => {\n lines.push(`### ${i + 1}. ${f.test || \"Teste desconhecido\"}`);\n lines.push(\"\");\n lines.push(`**Mensagem:** ${f.message || \"N/A\"}`);\n lines.push(\"\");\n if (f.stack) {\n lines.push(\"**Stack trace:**\");\n lines.push(\"```\");\n lines.push(f.stack);\n lines.push(\"```\");\n lines.push(\"\");\n }\n });\n\n lines.push(\"## Próximos passos\");\n lines.push(\"\");\n lines.push(\"- [ ] Reproduzir localmente\");\n lines.push(\"- [ ] Identificar causa raiz\");\n lines.push(\"- [ ] Aplicar correção\");\n lines.push(\"- [ ] Validar com testes\");\n\n const report = lines.join(\"\\n\");\n\n appendMetricsEvent({ type: \"bug_reported\", failuresCount: failures.length, title: bugTitle });\n\n return {\n content: [{ type: \"text\", text: report }],\n structuredContent: { ok: true, report, title: bugTitle },\n };\n }\n);\n\n// ============================================================================\n// MÉTRICAS DE NEGÓCIO - Relatório agregado\n// ============================================================================\n\nserver.registerTool(\n \"get_business_metrics\",\n {\n title: \"Obter métricas de negócio\",\n description: \"Retorna métricas: tempo até bug, custo por defeito (tempo estimado), cobertura por fluxo. Requer run_tests executados e opcionalmente qa-lab-flows.json.\",\n inputSchema: z.object({\n period: z.enum([\"7d\", \"30d\", \"all\"]).optional().describe(\"Período para analisar. Default: 30d.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n timeToBug: z.object({\n avgHours: z.number(),\n lastFailureAt: z.string().optional(),\n runsWithFailures: z.number(),\n }).optional(),\n costPerDefect: z.object({\n avgMinutesPerDefect: z.number(),\n totalFailures: z.number(),\n estimatedHoursSpent: z.number(),\n }).optional(),\n flowCoverage: z.object({\n totalFlows: z.number(),\n coveredFlows: z.number(),\n percent: z.number(),\n details: z.array(z.object({ flow: z.string(), covered: z.boolean() })),\n }).optional(),\n summary: z.string(),\n }),\n },\n async ({ period = \"30d\" } = {}) => {\n const now = Date.now();\n const msByPeriod = { \"7d\": 7 * 24 * 60 * 60 * 1000, \"30d\": 30 * 24 * 60 * 60 * 1000, all: Infinity };\n const cutoff = now - msByPeriod[period];\n\n let data = { events: [] };\n if (fs.existsSync(METRICS_FILE)) {\n try {\n data = JSON.parse(fs.readFileSync(METRICS_FILE, \"utf8\"));\n } catch {}\n }\n\n const events = (data.events || []).filter((e) => new Date(e.timestamp).getTime() >= cutoff);\n\n const testRuns = events.filter((e) => e.type === \"test_run\");\n const failedRuns = testRuns.filter((e) => (e.failed || 0) > 0);\n const totalFailed = testRuns.reduce((sum, e) => sum + (e.failed || 0), 0);\n const totalDuration = testRuns.reduce((sum, e) => sum + (e.durationSeconds || 0), 0);\n\n let timeToBug = null;\n if (failedRuns.length > 0) {\n const lastFailure = failedRuns[failedRuns.length - 1];\n timeToBug = {\n avgHours: 0,\n lastFailureAt: lastFailure.timestamp,\n runsWithFailures: failedRuns.length,\n };\n if (failedRuns.length >= 2) {\n const deltas = [];\n for (let i = 1; i < failedRuns.length; i++) {\n const prev = new Date(failedRuns[i - 1].timestamp).getTime();\n const curr = new Date(failedRuns[i].timestamp).getTime();\n deltas.push((curr - prev) / (1000 * 60 * 60));\n }\n timeToBug.avgHours = deltas.reduce((a, b) => a + b, 0) / deltas.length;\n }\n }\n\n let costPerDefect = null;\n if (totalFailed > 0) {\n const estimatedMinutesSpent = totalDuration + totalFailed * 5;\n costPerDefect = {\n avgMinutesPerDefect: Math.round(estimatedMinutesSpent / totalFailed),\n totalFailures: totalFailed,\n estimatedHoursSpent: Math.round((estimatedMinutesSpent / 60) * 10) / 10,\n };\n }\n\n let flowCoverage = null;\n if (fs.existsSync(FLOWS_CONFIG_FILE)) {\n try {\n const flowsConfig = JSON.parse(fs.readFileSync(FLOWS_CONFIG_FILE, \"utf8\"));\n const flows = flowsConfig.flows || [];\n const structure = detectProjectStructure();\n const allTestFiles = new Set(collectTestFiles(structure).map((e) => e.path));\n\n const details = flows.map((f) => {\n const testFiles = f.testFiles || [];\n const covered = testFiles.some((tf) => allTestFiles.has(tf) || allTestFiles.has(tf.replace(/\\\\/g, \"/\")));\n return { flow: f.name || f.id || \"?\", covered };\n });\n\n flowCoverage = {\n totalFlows: flows.length,\n coveredFlows: details.filter((d) => d.covered).length,\n percent: flows.length ? Math.round((details.filter((d) => d.covered).length / flows.length) * 100) : 0,\n details,\n };\n } catch {}\n }\n\n const lines = [\n \"## Métricas de negócio\",\n \"\",\n `Período: ${period}`,\n \"\",\n timeToBug\n ? [\n \"### Tempo até bug\",\n `- Última falha: ${timeToBug.lastFailureAt || \"N/A\"}`,\n `- Execuções com falha: ${timeToBug.runsWithFailures}`,\n timeToBug.avgHours > 0 ? `- Média entre falhas: ${timeToBug.avgHours.toFixed(1)}h` : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\")\n : \"\",\n costPerDefect\n ? [\n \"### Custo por defeito (estimativa)\",\n `- Total de falhas: ${costPerDefect.totalFailures}`,\n `- Tempo médio por defeito: ~${costPerDefect.avgMinutesPerDefect} min`,\n `- Horas estimadas gastas: ${costPerDefect.estimatedHoursSpent}h`,\n ].join(\"\\n\")\n : \"\",\n flowCoverage\n ? [\n \"### Cobertura por fluxo\",\n `- Fluxos cobertos: ${flowCoverage.coveredFlows}/${flowCoverage.totalFlows} (${flowCoverage.percent}%)`,\n flowCoverage.details.map((d) => ` - ${d.flow}: ${d.covered ? \"✅\" : \"❌\"}`).join(\"\\n\"),\n ].join(\"\\n\")\n : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n if (!timeToBug && !costPerDefect && !flowCoverage) {\n const msg =\n \"Nenhuma métrica disponível. Rode run_tests para gerar dados. Para cobertura por fluxo, crie qa-lab-flows.json.\";\n return {\n content: [{ type: \"text\", text: msg }],\n structuredContent: { ok: false, summary: msg },\n };\n }\n\n const summary = [\n timeToBug && `${timeToBug.runsWithFailures} execuções com falha`,\n costPerDefect && `${costPerDefect.totalFailures} falhas (~${costPerDefect.avgMinutesPerDefect} min/defeito)`,\n flowCoverage && `${flowCoverage.coveredFlows}/${flowCoverage.totalFlows} fluxos cobertos`,\n ]\n .filter(Boolean)\n .join(\" | \");\n\n return {\n content: [{ type: \"text\", text: lines || summary }],\n structuredContent: {\n ok: true,\n timeToBug,\n costPerDefect,\n flowCoverage,\n summary,\n },\n };\n }\n);\n\nserver.registerTool(\n \"list_test_files\",\n {\n title: \"Listar arquivos de teste\",\n description: \"Lista TODOS os arquivos de teste (qualquer framework: Cypress, Playwright, WDIO, Robot, pytest, Behave, etc.) com filtro opcional.\",\n inputSchema: z.object({\n framework: z.enum([\n \"cypress\", \"playwright\", \"jest\", \"webdriverio\", \"appium\", \"robot\", \"pytest\", \"behave\", \"detox\", \"all\"\n ]).optional().describe(\"Filtrar por framework. Default: all.\"),\n pattern: z.string().optional().describe(\"Pattern para filtrar (ex: 'login', 'api').\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n files: z.array(z.string()),\n total: z.number(),\n }),\n },\n async ({ framework = \"all\", pattern } = {}) => {\n const structure = detectProjectStructure();\n const collected = collectTestFiles(structure, { framework, pattern });\n const allFiles = collected.map((e) => e.path);\n\n const summary = `Encontrados ${allFiles.length} arquivo(s) de teste (qualquer framework).`;\n\n return {\n content: [{ type: \"text\", text: `${summary}\\n\\n${allFiles.slice(0, 50).join(\"\\n\")}` }],\n structuredContent: { ok: true, files: allFiles, total: allFiles.length },\n };\n }\n);\n\nserver.registerTool(\n \"run_linter\",\n {\n title: \"Executar linter\",\n description: \"Roda ESLint, Prettier ou linter configurado no projeto.\",\n inputSchema: z.object({\n fix: z.boolean().optional().describe(\"Auto-fix (--fix). Default: false.\"),\n path: z.string().optional().describe(\"Caminho específico (ex: src/). Default: todo o projeto.\"),\n }),\n outputSchema: z.object({\n status: z.enum([\"passed\", \"failed\", \"not_found\"]),\n message: z.string(),\n exitCode: z.number(),\n output: z.string().optional(),\n }),\n },\n async ({ fix, path: targetPath }) => {\n const structure = detectProjectStructure();\n const scripts = structure.packageJson?.scripts || {};\n\n let cmd, args;\n if (scripts.lint) {\n cmd = \"npm\";\n args = [\"run\", \"lint\"];\n } else if (structure.packageJson?.devDependencies?.eslint || structure.packageJson?.dependencies?.eslint) {\n cmd = \"npx\";\n args = [\"eslint\", targetPath || \".\"];\n if (fix) args.push(\"--fix\");\n } else {\n return {\n content: [{ type: \"text\", text: \"Linter não detectado no projeto.\" }],\n structuredContent: { status: \"not_found\", message: \"No linter found\", exitCode: 1 },\n };\n }\n\n return new Promise((resolve) => {\n const child = spawn(cmd, args, {\n cwd: PROJECT_ROOT,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n shell: process.platform === \"win32\",\n env: { ...process.env },\n });\n\n let stdout = \"\";\n let stderr = \"\";\n if (child.stdout) child.stdout.on(\"data\", (d) => { stdout += d.toString(); });\n if (child.stderr) child.stderr.on(\"data\", (d) => { stderr += d.toString(); });\n\n child.on(\"close\", (code) => {\n const output = [stdout, stderr].filter(Boolean).join(\"\\n\").trim();\n const passed = code === 0;\n resolve({\n content: [{ type: \"text\", text: passed ? \"Linter passou.\" : \"Linter encontrou problemas.\" }],\n structuredContent: {\n status: passed ? \"passed\" : \"failed\",\n message: passed ? \"Lint passed\" : \"Lint failed\",\n exitCode: code ?? 1,\n output: !passed ? output : undefined,\n },\n });\n });\n });\n }\n);\n\nserver.registerTool(\n \"install_dependencies\",\n {\n title: \"Instalar dependências\",\n description: \"Roda npm install, yarn install ou pnpm install (detecta automaticamente).\",\n inputSchema: z.object({\n packageManager: z.enum([\"npm\", \"yarn\", \"pnpm\", \"auto\"]).optional().describe(\"Package manager. Default: auto.\"),\n }),\n outputSchema: z.object({\n status: z.enum([\"success\", \"failed\"]),\n message: z.string(),\n exitCode: z.number(),\n }),\n },\n async ({ packageManager = \"auto\" }) => {\n let pm = packageManager;\n \n if (pm === \"auto\") {\n if (fs.existsSync(path.join(PROJECT_ROOT, \"yarn.lock\"))) pm = \"yarn\";\n else if (fs.existsSync(path.join(PROJECT_ROOT, \"pnpm-lock.yaml\"))) pm = \"pnpm\";\n else pm = \"npm\";\n }\n\n return new Promise((resolve) => {\n const child = spawn(pm, [\"install\"], {\n cwd: PROJECT_ROOT,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n env: { ...process.env },\n });\n\n child.on(\"close\", (code) => {\n const passed = code === 0;\n resolve({\n content: [{ type: \"text\", text: passed ? \"Dependências instaladas.\" : \"Erro ao instalar dependências.\" }],\n structuredContent: {\n status: passed ? \"success\" : \"failed\",\n message: passed ? \"Dependencies installed\" : \"Install failed\",\n exitCode: code ?? 1,\n },\n });\n });\n });\n }\n);\n\nserver.registerTool(\n \"get_test_coverage\",\n {\n title: \"Obter cobertura de testes\",\n description: \"Roda testes com coverage (Jest, Playwright, Cypress com plugin).\",\n inputSchema: z.object({\n framework: z.enum([\"jest\", \"playwright\", \"cypress\"]).optional().describe(\"Framework. Default: detectado automaticamente.\"),\n }),\n outputSchema: z.object({\n status: z.enum([\"success\", \"failed\", \"not_supported\"]),\n message: z.string(),\n coveragePercent: z.number().optional(),\n output: z.string().optional(),\n }),\n },\n async ({ framework }) => {\n const structure = detectProjectStructure();\n const fw = framework || structure.testFrameworks[0];\n\n if (fw === \"jest\") {\n return new Promise((resolve) => {\n const child = spawn(\"npx\", [\"jest\", \"--coverage\"], {\n cwd: PROJECT_ROOT,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n shell: process.platform === \"win32\",\n env: { ...process.env },\n });\n\n let stdout = \"\";\n if (child.stdout) child.stdout.on(\"data\", (d) => { stdout += d.toString(); });\n\n child.on(\"close\", (code) => {\n const coverageMatch = stdout.match(/All files.*?(\\d+\\.?\\d*)/);\n const coveragePercent = coverageMatch ? parseFloat(coverageMatch[1]) : undefined;\n\n resolve({\n content: [{ type: \"text\", text: `Coverage: ${coveragePercent || \"N/A\"}%` }],\n structuredContent: {\n status: code === 0 ? \"success\" : \"failed\",\n message: code === 0 ? \"Coverage generated\" : \"Coverage failed\",\n coveragePercent,\n output: stdout,\n },\n });\n });\n });\n }\n\n return {\n content: [{ type: \"text\", text: `Coverage não suportado para ${fw} ainda.` }],\n structuredContent: { status: \"not_supported\", message: \"Coverage not supported for this framework\" },\n };\n }\n);\n\nserver.registerTool(\n \"watch_tests\",\n {\n title: \"Rodar testes em modo watch\",\n description: \"Inicia testes em watch mode (Jest, Vitest). Útil para desenvolvimento.\",\n inputSchema: z.object({\n framework: z.enum([\"jest\", \"vitest\"]).optional().describe(\"Framework. Default: detectado.\"),\n }),\n outputSchema: z.object({\n status: z.string(),\n message: z.string(),\n }),\n },\n async ({ framework }) => {\n const structure = detectProjectStructure();\n const fw = framework || (structure.testFrameworks.includes(\"jest\") ? \"jest\" : \"vitest\");\n\n if (!structure.testFrameworks.includes(fw)) {\n return {\n content: [{ type: \"text\", text: `${fw} não detectado no projeto.` }],\n structuredContent: { status: \"not_found\", message: \"Framework not found\" },\n };\n }\n\n return {\n content: [{ type: \"text\", text: `Para watch mode, rode manualmente: npx ${fw} --watch` }],\n structuredContent: {\n status: \"info\",\n message: `Watch mode requires interactive terminal. Run: npx ${fw} --watch`,\n },\n };\n }\n);\n\nserver.registerTool(\n \"create_test_template\",\n {\n title: \"Criar template de teste\",\n description: \"Gera template básico de teste (boilerplate) para o framework escolhido.\",\n inputSchema: z.object({\n framework: z.enum([\"cypress\", \"playwright\", \"jest\"]).describe(\"Framework.\"),\n type: z.enum([\"api\", \"ui\", \"unit\"]).optional().describe(\"Tipo de teste. Default: api.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n template: z.string(),\n suggestedFileName: z.string(),\n }),\n },\n async ({ framework, type = \"api\" }) => {\n let template = \"\";\n let fileName = \"\";\n\n if (framework === \"cypress\") {\n fileName = `${type}-test.cy.js`;\n template = `describe('${type.toUpperCase()} Test', () => {\n it('should pass', () => {\n ${type === \"api\" ? \"cy.request('GET', 'http://localhost:3000/api/health').then((res) => {\\n expect(res.status).to.eq(200);\\n });\" : \"cy.visit('/');\\n cy.get('h1').should('be.visible');\"}\n });\n});`;\n } else if (framework === \"playwright\") {\n fileName = `${type}-test.spec.js`;\n template = `const { test, expect } = require('@playwright/test');\n\ntest.describe('${type.toUpperCase()} Test', () => {\n test('should pass', async ({ ${type === \"api\" ? \"request\" : \"page\"} }) => {\n ${type === \"api\" ? \"const res = await request.get('http://localhost:3000/api/health');\\n expect(res.status()).toBe(200);\" : \"await page.goto('/');\\n await expect(page.locator('h1')).toBeVisible();\"}\n });\n});`;\n } else {\n fileName = `${type}-test.test.js`;\n template = `describe('${type.toUpperCase()} Test', () => {\n test('should pass', ${type === \"api\" ? \"async () => {\\n const res = await fetch('http://localhost:3000/api/health');\\n expect(res.status).toBe(200);\\n }\" : \"() => {\\n expect(true).toBe(true);\\n }\"});\n});`;\n }\n\n return {\n content: [{ type: \"text\", text: `Template criado. Use write_test para gravar.` }],\n structuredContent: { ok: true, template, suggestedFileName: fileName },\n };\n }\n);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n console.error(\"Erro no MCP server:\", err);\n process.exit(1);\n});\n"],"mappings":"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","names":["res","data"]}
1
+ {"version":3,"sources":["../src/index.js"],"sourcesContent":["#!/usr/bin/env node\n/**\n * MCP Lab Agent - Standalone\n * MCP server genérico para QA automation em qualquer projeto.\n * Detecta automaticamente Cypress, Playwright, Jest, estrutura do projeto, etc.\n */\nimport { config } from \"dotenv\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { spawn } from \"node:child_process\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\n\nconst PROJECT_ROOT = process.cwd();\nconfig({ path: path.join(PROJECT_ROOT, \".env\") });\n\nconst server = new McpServer({\n name: \"mcp-lab-agent\",\n version: \"1.0.0\",\n});\n\n// ============================================================================\n// DETECÇÃO AUTOMÁTICA DE ESTRUTURA\n// ============================================================================\n\nfunction detectProjectStructure() {\n const structure = {\n hasTests: false,\n testFrameworks: [],\n testDirs: [],\n hasBackend: false,\n backendDir: null,\n hasFrontend: false,\n frontendDir: null,\n hasMobile: false,\n packageJson: null,\n pythonRequirements: null,\n };\n\n // Detectar Node.js/JavaScript/TypeScript\n const pkgPath = path.join(PROJECT_ROOT, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n structure.packageJson = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n const deps = {\n ...structure.packageJson.dependencies,\n ...structure.packageJson.devDependencies,\n };\n\n // Frameworks E2E/UI\n if (deps.cypress) {\n structure.testFrameworks.push(\"cypress\");\n structure.hasTests = true;\n }\n if (deps[\"@playwright/test\"] || deps.playwright) {\n structure.testFrameworks.push(\"playwright\");\n structure.hasTests = true;\n }\n if (deps.webdriverio || deps[\"@wdio/cli\"]) {\n structure.testFrameworks.push(\"webdriverio\");\n structure.hasTests = true;\n }\n\n // Frameworks Unit/Integration\n if (deps.jest) {\n structure.testFrameworks.push(\"jest\");\n structure.hasTests = true;\n }\n if (deps.vitest) {\n structure.testFrameworks.push(\"vitest\");\n structure.hasTests = true;\n }\n if (deps.mocha) {\n structure.testFrameworks.push(\"mocha\");\n structure.hasTests = true;\n }\n if (deps.jasmine) {\n structure.testFrameworks.push(\"jasmine\");\n structure.hasTests = true;\n }\n\n // Frameworks Mobile\n if (deps.appium || deps[\"appium-webdriverio\"]) {\n structure.testFrameworks.push(\"appium\");\n structure.hasTests = true;\n structure.hasMobile = true;\n }\n if (deps.detox) {\n structure.testFrameworks.push(\"detox\");\n structure.hasTests = true;\n structure.hasMobile = true;\n }\n\n // API Testing\n if (deps.supertest) {\n structure.testFrameworks.push(\"supertest\");\n structure.hasTests = true;\n }\n if (deps[\"@pactum/pactum\"] || deps.pactum) {\n structure.testFrameworks.push(\"pactum\");\n structure.hasTests = true;\n }\n\n // Outros frameworks E2E\n if (deps.testcafe || deps[\"testcafe\"]) {\n structure.testFrameworks.push(\"testcafe\");\n structure.hasTests = true;\n }\n if (deps.nightwatch || deps[\"nightwatch\"]) {\n structure.testFrameworks.push(\"nightwatch\");\n structure.hasTests = true;\n }\n if (deps.puppeteer) {\n structure.testFrameworks.push(\"puppeteer\");\n structure.hasTests = true;\n }\n if (deps.codeceptjs || deps[\"codeceptjs\"]) {\n structure.testFrameworks.push(\"codeceptjs\");\n structure.hasTests = true;\n }\n\n // Backend detection\n if (deps.express || deps.fastify || deps[\"@nestjs/core\"] || deps.koa) {\n structure.hasBackend = true;\n }\n \n // Frontend detection\n if (deps.next || deps.react || deps.vue || deps.svelte || deps.angular) {\n structure.hasFrontend = true;\n }\n }\n\n // Detectar Python (Robot Framework, pytest, etc.)\n const requirementsPath = path.join(PROJECT_ROOT, \"requirements.txt\");\n if (fs.existsSync(requirementsPath)) {\n const requirements = fs.readFileSync(requirementsPath, \"utf8\");\n structure.pythonRequirements = requirements;\n\n if (/robotframework/i.test(requirements)) {\n structure.testFrameworks.push(\"robot\");\n structure.hasTests = true;\n }\n if (/pytest/i.test(requirements)) {\n structure.testFrameworks.push(\"pytest\");\n structure.hasTests = true;\n }\n if (/behave/i.test(requirements)) {\n structure.testFrameworks.push(\"behave\");\n structure.hasTests = true;\n }\n if (/requests/i.test(requirements)) {\n structure.hasBackend = true;\n }\n }\n\n // Detectar pastas de teste (genérico)\n const commonTestDirs = [\n \"tests\", \"test\", \"e2e\", \"cypress\", \"playwright\", \"__tests__\",\n \"specs\", \"spec\", \"integration\", \"unit\", \"functional\", \"robot\",\n \"features\", \"scenarios\", \"mobile\", \"api\",\n // Monorepo: subprojetos por framework\n \"playwright-js\", \"puppeteer-js\", \"testcafe-js\", \"wdio-webdriver-io\",\n \"nightwatch-js\", \"codeceptjs\", \"robot-framework\", \"selenium-python\"\n ];\n for (const dir of commonTestDirs) {\n const fullPath = path.join(PROJECT_ROOT, dir);\n if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {\n structure.testDirs.push(dir);\n }\n }\n\n // Monorepo: escanear subdirs de primeiro nível que parecem ter testes\n const skipDirs = [\"node_modules\", \".git\", \"dist\", \"build\", \".next\", \".venv\"];\n try {\n const rootEntries = fs.readdirSync(PROJECT_ROOT, { withFileTypes: true });\n for (const e of rootEntries) {\n if (!e.isDirectory() || skipDirs.includes(e.name)) continue;\n const subPath = path.join(PROJECT_ROOT, e.name);\n if (structure.testDirs.includes(e.name)) continue;\n // Verificar se há package.json ou tests/ dentro\n const hasPkg = fs.existsSync(path.join(subPath, \"package.json\"));\n const hasTests = fs.existsSync(path.join(subPath, \"tests\")) ||\n fs.existsSync(path.join(subPath, \"test\")) ||\n fs.existsSync(path.join(subPath, \"e2e\")) ||\n fs.existsSync(path.join(subPath, \"__tests__\")) ||\n fs.existsSync(path.join(subPath, \"specs\"));\n if (hasPkg || hasTests) {\n structure.testDirs.push(e.name);\n }\n }\n } catch {}\n\n // Monorepo: detectar frameworks em package.json de subdirs\n for (const dir of structure.testDirs) {\n const subPkg = path.join(PROJECT_ROOT, dir, \"package.json\");\n if (!fs.existsSync(subPkg)) continue;\n try {\n const sub = JSON.parse(fs.readFileSync(subPkg, \"utf8\"));\n const subDeps = { ...(sub.dependencies || {}), ...(sub.devDependencies || {}) };\n const toAdd = [];\n if (subDeps.cypress && !structure.testFrameworks.includes(\"cypress\")) toAdd.push(\"cypress\");\n if ((subDeps[\"@playwright/test\"] || subDeps.playwright) && !structure.testFrameworks.includes(\"playwright\")) toAdd.push(\"playwright\");\n if ((subDeps.webdriverio || subDeps[\"@wdio/cli\"]) && !structure.testFrameworks.includes(\"webdriverio\")) toAdd.push(\"webdriverio\");\n if (subDeps.testcafe && !structure.testFrameworks.includes(\"testcafe\")) toAdd.push(\"testcafe\");\n if (subDeps.nightwatch && !structure.testFrameworks.includes(\"nightwatch\")) toAdd.push(\"nightwatch\");\n if (subDeps.puppeteer && !structure.testFrameworks.includes(\"puppeteer\")) toAdd.push(\"puppeteer\");\n if (subDeps.codeceptjs && !structure.testFrameworks.includes(\"codeceptjs\")) toAdd.push(\"codeceptjs\");\n if (subDeps.jest && !structure.testFrameworks.includes(\"jest\")) toAdd.push(\"jest\");\n toAdd.forEach((fw) => { structure.testFrameworks.push(fw); structure.hasTests = true; });\n } catch {}\n }\n\n // Monorepo: detectar Robot/pytest em requirements.txt de subdirs\n for (const dir of structure.testDirs) {\n const reqPath = path.join(PROJECT_ROOT, dir, \"requirements.txt\");\n if (!fs.existsSync(reqPath)) continue;\n try {\n const req = fs.readFileSync(reqPath, \"utf8\");\n if (/robotframework/i.test(req) && !structure.testFrameworks.includes(\"robot\")) {\n structure.testFrameworks.push(\"robot\");\n structure.hasTests = true;\n }\n if (/pytest|selenium/i.test(req) && !structure.testFrameworks.includes(\"pytest\")) {\n structure.testFrameworks.push(\"pytest\");\n structure.hasTests = true;\n }\n } catch {}\n }\n\n // Detectar backend\n const commonBackendDirs = [\"backend\", \"server\", \"api\", \"src\"];\n for (const dir of commonBackendDirs) {\n const fullPath = path.join(PROJECT_ROOT, dir);\n if (fs.existsSync(fullPath) && !structure.backendDir) {\n const hasServerFile = fs.existsSync(path.join(fullPath, \"server.js\")) ||\n fs.existsSync(path.join(fullPath, \"index.js\")) ||\n fs.existsSync(path.join(fullPath, \"app.js\"));\n if (hasServerFile) {\n structure.backendDir = dir;\n }\n }\n }\n\n // Detectar frontend\n const commonFrontendDirs = [\"frontend\", \"client\", \"web\", \"app\", \"src\"];\n for (const dir of commonFrontendDirs) {\n const fullPath = path.join(PROJECT_ROOT, dir);\n if (fs.existsSync(fullPath) && !structure.frontendDir) {\n const hasAppFile = fs.existsSync(path.join(fullPath, \"App.js\")) ||\n fs.existsSync(path.join(fullPath, \"App.tsx\")) ||\n fs.existsSync(path.join(fullPath, \"index.html\"));\n if (hasAppFile) {\n structure.frontendDir = dir;\n }\n }\n }\n\n return structure;\n}\n\n// ============================================================================\n// PADRÕES UNIVERSAIS DE ARQUIVOS DE TESTE (qualquer framework)\n// ============================================================================\n\nconst UNIVERSAL_TEST_PATTERNS = [\n /\\.(cy|spec|test)\\.(js|ts|jsx|tsx)$/i,\n /_test\\.(js|ts)$/i, // CodeceptJS\n /\\.robot$/i,\n /\\.feature$/i,\n /^(test_.*|.*_test)\\.py$/i,\n /\\.steps?\\.(js|ts|py)$/i,\n /\\.e2e\\.(js|ts)$/i,\n /\\.it\\.(js|ts)$/i,\n];\n\nfunction isTestFile(name) {\n return UNIVERSAL_TEST_PATTERNS.some((re) => re.test(name));\n}\n\nfunction collectTestFiles(structure, options = {}) {\n const { pattern, framework, maxContentFiles = 0 } = options;\n const results = [];\n\n for (const dir of structure.testDirs) {\n const fullPath = path.join(PROJECT_ROOT, dir);\n const walk = (p, base = \"\") => {\n if (!fs.existsSync(p)) return;\n const entries = fs.readdirSync(p, { withFileTypes: true });\n for (const e of entries) {\n const rel = base ? `${base}/${e.name}` : e.name;\n if (e.isDirectory()) {\n if (e.name === \"node_modules\" || e.name === \".git\" || e.name === \".venv\") continue;\n walk(path.join(p, e.name), rel);\n } else if (e.isFile() && isTestFile(e.name)) {\n const filePath = `${dir}/${rel}`;\n if (pattern && !filePath.toLowerCase().includes(pattern.toLowerCase())) continue;\n const inferredFw = inferFrameworkFromFile(e.name, structure, filePath);\n if (framework && framework !== \"all\" && inferredFw !== framework && !matchesFramework(inferredFw, framework)) continue;\n const entry = { path: filePath, inferredFramework: inferredFw };\n if (maxContentFiles > 0 && results.length < maxContentFiles) {\n try {\n entry.content = fs.readFileSync(path.join(PROJECT_ROOT, filePath), \"utf8\");\n } catch {}\n }\n results.push(entry);\n }\n }\n };\n walk(fullPath);\n }\n return results;\n}\n\nfunction inferFrameworkFromFile(name, structure = {}, filePath = \"\") {\n const pathLower = (filePath || \"\").toLowerCase().replace(/\\\\/g, \"/\");\n // Inferir pelo CAMINHO quando há múltiplos frameworks (ex: tests/cypress/, tests/selenium-python/)\n if (/[\\/]cypress[\\/\\-]/.test(pathLower)) return \"cypress\";\n if (/[\\/]playwright[\\/\\-]/.test(pathLower)) return \"playwright\";\n if (/[\\/]wdio[\\/\\-]|[\\/]webdriver[\\/\\-]/.test(pathLower)) return \"webdriverio\";\n if (/[\\/]appium[\\/\\-]/.test(pathLower)) return \"appium\";\n if (/[\\/]selenium-python[\\/]|[\\/]pytest[\\/\\-]/.test(pathLower)) return \"pytest\";\n if (/[\\/]robot[\\/\\-]/.test(pathLower)) return \"robot\";\n if (/[\\/]codecept[\\/\\-]/.test(pathLower)) return \"codeceptjs\";\n if (/[\\/]nightwatch[\\/\\-]/.test(pathLower)) return \"nightwatch\";\n if (/[\\/]testcafe[\\/\\-]/.test(pathLower)) return \"testcafe\";\n if (/[\\/]puppeteer[\\/\\-]/.test(pathLower)) return \"puppeteer\";\n if (/[\\/]behave[\\/\\-]|[\\/]features[\\/]/.test(pathLower)) return \"behave\";\n // Fallback: inferir pela extensão do arquivo\n if (/\\.cy\\.(js|ts|jsx|tsx)/i.test(name)) return \"cypress\";\n if (/_test\\.(js|ts)$/i.test(name)) return \"codeceptjs\";\n if (/\\.spec\\.(js|ts|jsx|tsx)/i.test(name)) {\n if (structure?.testFrameworks?.includes(\"webdriverio\")) return \"webdriverio\";\n if (structure?.testFrameworks?.includes(\"appium\")) return \"appium\";\n return \"playwright\";\n }\n if (/\\.test\\.(js|ts|jsx|tsx)/i.test(name)) return structure?.testFrameworks?.includes(\"vitest\") ? \"vitest\" : \"jest\";\n if (/\\.robot$/i.test(name)) return \"robot\";\n if (/\\.feature$/i.test(name)) return \"behave\";\n if (/\\.(py|steps?\\.py)$/i.test(name) || /^(test_.*|.*_test)\\.py$/i.test(name)) return \"pytest\";\n if (/\\.e2e\\.(js|ts)/i.test(name)) return \"playwright\";\n return \"unknown\";\n}\n\nfunction matchesFramework(inferred, requested) {\n const aliases = { spec: [\"playwright\", \"webdriverio\", \"appium\"] };\n if (inferred === requested) return true;\n return aliases[inferred]?.includes(requested);\n}\n\n// ============================================================================\n// MÉTRICAS DE NEGÓCIO - Helpers\n// ============================================================================\n\nconst METRICS_FILE = path.join(PROJECT_ROOT, \".qa-lab-metrics.json\");\nconst FLOWS_CONFIG_FILE = path.join(PROJECT_ROOT, \"qa-lab-flows.json\");\n\nfunction parseTestRunResult(runOutput, exitCode) {\n let passed = 0;\n let failed = 0;\n const jestMatch = runOutput.match(/Tests:\\s+(\\d+)\\s+passed(?:,\\s*(\\d+)\\s+failed)?/);\n if (jestMatch) {\n passed = parseInt(jestMatch[1], 10);\n failed = jestMatch[2] ? parseInt(jestMatch[2], 10) : 0;\n }\n const cypressPass = runOutput.match(/(\\d+)\\s+passing/);\n const cypressFail = runOutput.match(/(\\d+)\\s+failing/);\n if (cypressPass) passed = parseInt(cypressPass[1], 10);\n if (cypressFail) failed = parseInt(cypressFail[1], 10);\n const pwPass = runOutput.match(/(\\d+)\\s+passed/);\n const pwFail = runOutput.match(/(\\d+)\\s+failed/);\n if (pwPass) passed = parseInt(pwPass[1], 10);\n if (pwFail) failed = parseInt(pwFail[1], 10);\n if (passed === 0 && failed === 0) {\n if (exitCode === 0) passed = 1;\n else failed = 1;\n }\n return { passed, failed };\n}\n\nfunction appendMetricsEvent(event) {\n try {\n let data = { events: [], lastUpdated: new Date().toISOString() };\n if (fs.existsSync(METRICS_FILE)) {\n const raw = fs.readFileSync(METRICS_FILE, \"utf8\");\n try {\n data = JSON.parse(raw);\n } catch {}\n }\n data.events = data.events || [];\n data.events.push({ ...event, timestamp: event.timestamp || new Date().toISOString() });\n data.lastUpdated = new Date().toISOString();\n if (data.events.length > 500) data.events = data.events.slice(-400);\n fs.writeFileSync(METRICS_FILE, JSON.stringify(data, null, 2), \"utf8\");\n } catch {}\n}\n\nfunction extractFailuresFromOutput(runOutput) {\n const failures = [];\n const lines = runOutput.split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (/fail|error|assertion|timeout|element not found|selector/i.test(line)) {\n failures.push({\n test: lines[Math.max(0, i - 1)]?.trim() || \"unknown\",\n message: line.trim().slice(0, 500),\n });\n }\n }\n return failures.slice(0, 20);\n}\n\n// ============================================================================\n// FERRAMENTAS GENÉRICAS\n// ============================================================================\n\nserver.registerTool(\n \"read_file\",\n {\n title: \"Ler qualquer arquivo\",\n description: \"Lê o conteúdo de QUALQUER arquivo do projeto por caminho. Use para specs, page objects, componentes, código fonte - qualquer formato.\",\n inputSchema: z.object({\n path: z.string().describe(\"Caminho relativo ao projeto (ex: cypress/e2e/login.cy.js, src/pages/Login.tsx, tests/login.robot).\"),\n encoding: z.enum([\"utf8\", \"utf-8\"]).optional().describe(\"Encoding. Default: utf8\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n content: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ path: filePath, encoding = \"utf8\" }) => {\n const normalized = filePath.replace(/^\\//, \"\").replace(/\\\\/g, \"/\");\n const fullPath = path.join(PROJECT_ROOT, normalized);\n\n if (!fullPath.startsWith(PROJECT_ROOT)) {\n return {\n content: [{ type: \"text\", text: \"Caminho fora do projeto.\" }],\n structuredContent: { ok: false, error: \"Path outside project\" },\n };\n }\n if (!fs.existsSync(fullPath)) {\n return {\n content: [{ type: \"text\", text: `Arquivo não encontrado: ${normalized}` }],\n structuredContent: { ok: false, error: \"File not found\" },\n };\n }\n const stat = fs.statSync(fullPath);\n if (stat.isDirectory()) {\n return {\n content: [{ type: \"text\", text: \"É um diretório. Use um caminho de arquivo.\" }],\n structuredContent: { ok: false, error: \"Is directory\" },\n };\n }\n\n try {\n const content = fs.readFileSync(fullPath, encoding);\n return {\n content: [{ type: \"text\", text: content }],\n structuredContent: { ok: true, content },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao ler: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\nserver.registerTool(\n \"detect_project\",\n {\n title: \"Detectar estrutura do projeto\",\n description: \"Analisa o projeto e identifica frameworks de teste, pastas, backend, frontend.\",\n inputSchema: z.object({}),\n outputSchema: z.object({\n ok: z.boolean(),\n structure: z.object({\n hasTests: z.boolean(),\n testFrameworks: z.array(z.string()),\n testDirs: z.array(z.string()),\n hasBackend: z.boolean(),\n backendDir: z.string().nullable(),\n hasFrontend: z.boolean(),\n frontendDir: z.string().nullable(),\n }),\n }),\n },\n async () => {\n const structure = detectProjectStructure();\n const summary = [\n `Frameworks de teste: ${structure.testFrameworks.join(\", \") || \"nenhum\"}`,\n `Pastas de teste: ${structure.testDirs.join(\", \") || \"nenhuma\"}`,\n `Backend: ${structure.backendDir || \"não detectado\"}`,\n `Frontend: ${structure.frontendDir || \"não detectado\"}`,\n ].join(\"\\n\");\n\n return {\n content: [{ type: \"text\", text: summary }],\n structuredContent: { ok: true, structure },\n };\n }\n);\n\nserver.registerTool(\n \"run_tests\",\n {\n title: \"Executar testes\",\n description: \"Roda testes do projeto. Suporta: Cypress, Playwright, WebdriverIO, Jest, Vitest, Mocha, Appium, Detox, Robot Framework, pytest, e mais. Detecta automaticamente.\",\n inputSchema: z.object({\n framework: z.enum([\n \"cypress\", \"playwright\", \"webdriverio\", \"jest\", \"vitest\", \"mocha\",\n \"appium\", \"detox\", \"robot\", \"pytest\", \"supertest\", \"pactum\",\n \"testcafe\", \"nightwatch\", \"puppeteer\", \"codeceptjs\", \"npm\"\n ]).optional().describe(\"Framework específico ou 'npm' para npm test.\"),\n spec: z.string().optional().describe(\"Caminho do spec (ex: cypress/e2e/test.cy.js).\"),\n suite: z.string().optional().describe(\"Suite ou pattern (ex: e2e, api).\"),\n explainOnFailure: z.boolean().optional().describe(\"Se true, quando falhar gera automaticamente: O que aconteceu, Por que falhou, O que fazer, Sugestão de correção. Requer API key.\"),\n }),\n outputSchema: z.object({\n status: z.enum([\"passed\", \"failed\", \"not_found\"]),\n message: z.string(),\n exitCode: z.number(),\n runOutput: z.string().optional(),\n }),\n },\n async ({ framework, spec, suite, explainOnFailure }) => {\n const structure = detectProjectStructure();\n \n if (!structure.hasTests) {\n return {\n content: [{ type: \"text\", text: \"Nenhum framework de teste detectado no projeto.\" }],\n structuredContent: {\n status: \"not_found\",\n message: \"No test framework found\",\n exitCode: 1,\n },\n };\n }\n\n let selectedFramework = framework;\n if (!selectedFramework && structure.testFrameworks.length > 0) {\n selectedFramework = structure.testFrameworks[0];\n }\n\n let cmd, args, cwd;\n\n // E2E/UI Frameworks\n if (selectedFramework === \"cypress\") {\n cmd = \"npx\";\n args = spec ? [\"cypress\", \"run\", \"--spec\", spec] : [\"cypress\", \"run\"];\n cwd = structure.testDirs.includes(\"cypress\") \n ? path.join(PROJECT_ROOT, \"cypress\")\n : structure.testDirs[0] \n ? path.join(PROJECT_ROOT, structure.testDirs[0])\n : PROJECT_ROOT;\n } else if (selectedFramework === \"playwright\") {\n cmd = \"npx\";\n args = spec ? [\"playwright\", \"test\", spec] : [\"playwright\", \"test\"];\n cwd = structure.testDirs.includes(\"playwright\")\n ? path.join(PROJECT_ROOT, \"playwright\")\n : structure.testDirs[0]\n ? path.join(PROJECT_ROOT, structure.testDirs[0])\n : PROJECT_ROOT;\n } else if (selectedFramework === \"webdriverio\") {\n cmd = \"npx\";\n args = spec ? [\"wdio\", \"run\", spec] : [\"wdio\", \"run\"];\n cwd = getFrameworkCwd(structure, [\"wdio-webdriver-io\", \"specs\", \"tests\"]);\n } else if (selectedFramework === \"testcafe\") {\n cmd = \"npx\";\n args = spec ? [\"testcafe\", spec] : [\"testcafe\"];\n cwd = getFrameworkCwd(structure, [\"testcafe-js\", \"testcafe\", \"tests\"]);\n } else if (selectedFramework === \"nightwatch\") {\n cmd = \"npx\";\n args = spec ? [\"nightwatch\", \"--test\", spec] : [\"nightwatch\"];\n cwd = getFrameworkCwd(structure, [\"nightwatch-js\", \"nightwatch\", \"tests\"]);\n } else if (selectedFramework === \"puppeteer\") {\n cmd = \"npx\";\n args = spec ? [\"jest\", spec, \"--config\", \"jest.config.js\"] : [\"jest\"];\n cwd = getFrameworkCwd(structure, [\"puppeteer-js\", \"puppeteer\", \"__tests__\"]);\n } else if (selectedFramework === \"codeceptjs\") {\n cmd = \"npx\";\n args = spec ? [\"codeceptjs\", \"run\", \"--grep\", spec] : [\"codeceptjs\", \"run\"];\n cwd = getFrameworkCwd(structure, [\"codeceptjs\", \"tests\"]);\n\n // Unit/Integration Frameworks\n } else if (selectedFramework === \"jest\") {\n cmd = \"npx\";\n args = [\"jest\"];\n if (spec) args.push(spec);\n cwd = PROJECT_ROOT;\n } else if (selectedFramework === \"vitest\") {\n cmd = \"npx\";\n args = [\"vitest\", \"run\"];\n if (spec) args.push(spec);\n cwd = PROJECT_ROOT;\n } else if (selectedFramework === \"mocha\") {\n cmd = \"npx\";\n args = spec ? [\"mocha\", spec] : [\"mocha\"];\n cwd = PROJECT_ROOT;\n \n // Mobile Frameworks\n } else if (selectedFramework === \"appium\") {\n cmd = \"npx\";\n args = spec ? [\"wdio\", \"run\", spec] : [\"wdio\", \"run\"];\n cwd = PROJECT_ROOT;\n } else if (selectedFramework === \"detox\") {\n cmd = \"npx\";\n args = [\"detox\", \"test\"];\n if (spec) args.push(spec);\n cwd = PROJECT_ROOT;\n \n // Python Frameworks\n } else if (selectedFramework === \"robot\") {\n cmd = \"robot\";\n args = spec ? [spec] : [structure.testDirs[0] || \"tests\"];\n cwd = PROJECT_ROOT;\n } else if (selectedFramework === \"pytest\") {\n cmd = \"pytest\";\n args = spec ? [spec] : [];\n cwd = PROJECT_ROOT;\n \n // API Testing\n } else if (selectedFramework === \"supertest\" || selectedFramework === \"pactum\") {\n cmd = \"npm\";\n args = [\"test\"];\n cwd = PROJECT_ROOT;\n \n // Fallback\n } else {\n cmd = \"npm\";\n args = [\"test\"];\n cwd = PROJECT_ROOT;\n }\n\n const startTime = Date.now();\n return new Promise((resolve) => {\n const child = spawn(cmd, args, {\n cwd,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n shell: process.platform === \"win32\",\n env: { ...process.env },\n });\n\n let stdout = \"\";\n let stderr = \"\";\n if (child.stdout) {\n child.stdout.on(\"data\", (d) => {\n const s = d.toString();\n stdout += s;\n process.stdout.write(s);\n });\n }\n if (child.stderr) {\n child.stderr.on(\"data\", (d) => {\n const s = d.toString();\n stderr += s;\n process.stderr.write(s);\n });\n }\n\n child.on(\"close\", (code) => {\n const runOutput = [stdout, stderr].filter(Boolean).join(\"\\n\").trim();\n const passed = code === 0;\n const durationSeconds = Math.round((Date.now() - startTime) / 1000);\n if (!passed && runOutput) {\n try {\n fs.writeFileSync(path.join(PROJECT_ROOT, \".qa-lab-last-failure.log\"), runOutput, \"utf8\");\n } catch {}\n }\n const { passed: p, failed: f } = parseTestRunResult(runOutput, code);\n appendMetricsEvent({\n type: \"test_run\",\n framework: selectedFramework,\n spec: spec || undefined,\n passed: p,\n failed: f,\n durationSeconds,\n exitCode: code ?? 1,\n failures: !passed ? extractFailuresFromOutput(runOutput) : undefined,\n });\n resolve({\n content: [{ type: \"text\", text: passed ? \"Testes executados com sucesso.\" : \"Falha na execução dos testes.\" }],\n structuredContent: {\n status: passed ? \"passed\" : \"failed\",\n message: passed ? \"Tests passed\" : \"Tests failed\",\n exitCode: code ?? 1,\n runOutput: !passed ? runOutput : undefined,\n },\n });\n });\n });\n }\n);\n\nserver.registerTool(\n \"read_project\",\n {\n title: \"Ler estrutura do projeto\",\n description: \"Lê package.json, specs existentes (qualquer framework: Cypress, Playwright, WDIO, Robot, pytest, etc) e retorna contexto. Use includeContent para trazer código de exemplos.\",\n inputSchema: z.object({\n includeContent: z.boolean().optional().describe(\"Se true, inclui conteúdo dos primeiros 3 arquivos de teste como referência. Default: false.\"),\n maxFiles: z.number().optional().describe(\"Máximo de arquivos cujo conteúdo será lido. Default: 3.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n summary: z.string(),\n packageJson: z.object({}).passthrough().optional(),\n testFiles: z.array(z.string()).optional(),\n testFilesWithContent: z.array(z.object({ path: z.string(), content: z.string() })).optional(),\n }),\n },\n async ({ includeContent = false, maxFiles = 3 } = {}) => {\n const structure = detectProjectStructure();\n const collected = collectTestFiles(structure, {\n maxContentFiles: includeContent ? maxFiles : 0,\n });\n\n const testFiles = collected.map((e) => e.path);\n const testFilesWithContent = includeContent\n ? collected.filter((e) => e.content).map((e) => ({ path: e.path, content: e.content }))\n : undefined;\n\n const summary = [\n `Frameworks: ${structure.testFrameworks.join(\", \") || \"nenhum\"}`,\n `Arquivos de teste: ${testFiles.length} (qualquer framework)`,\n `Backend: ${structure.backendDir || \"não detectado\"}`,\n `Frontend: ${structure.frontendDir || \"não detectado\"}`,\n includeContent && testFilesWithContent?.length\n ? `Conteúdo incluído: ${testFilesWithContent.length} arquivo(s) como referência`\n : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n\n return {\n content: [{ type: \"text\", text: summary }],\n structuredContent: {\n ok: true,\n summary,\n packageJson: structure.packageJson,\n testFiles: testFiles.slice(0, 100),\n testFilesWithContent,\n structure,\n },\n };\n }\n);\n\nserver.registerTool(\n \"generate_tests\",\n {\n title: \"Gerar ou traduzir testes com LLM\",\n description: \"Gera spec em QUALQUER framework. Aceita referência de outro framework: leia com read_file e passe em referenceCode. Traduz automaticamente (ex: Robot→Playwright, Cypress→WDIO).\",\n inputSchema: z.object({\n context: z.string().describe(\"Contexto do projeto (read_project) ou descrição.\"),\n request: z.string().describe(\"O que testar (ex: 'logout flow', 'teste de login') ou 'traduzir o teste abaixo'.\"),\n framework: z.enum([\n \"cypress\", \"playwright\", \"webdriverio\", \"jest\", \"vitest\", \"mocha\",\n \"appium\", \"robot\", \"pytest\", \"supertest\", \"behave\", \"detox\"\n ]).optional().describe(\"Framework alvo (detectado do projeto se omitido).\"),\n referenceCode: z.string().optional().describe(\"Código de referência em QUALQUER framework (Cypress, Robot, WDIO, etc). O LLM traduz/adapta para o framework alvo.\"),\n referencePaths: z.array(z.string()).optional().describe(\"Caminhos de arquivos para ler como referência. O agente lê e usa como padrão.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n specContent: z.string().optional(),\n suggestedFileName: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ context, request, framework, referenceCode, referencePaths }) => {\n const structure = detectProjectStructure();\n const fw = framework || structure.testFrameworks[0] || \"cypress\";\n\n let referenceBlock = \"\";\n if (referenceCode) referenceBlock += `\\n\\n--- CÓDIGO DE REFERÊNCIA (use como padrão, traduza/adapte para ${fw}) ---\\n${referenceCode.slice(0, 8000)}`;\n if (referencePaths?.length) {\n for (const p of referencePaths.slice(0, 5)) {\n const full = path.join(PROJECT_ROOT, p.replace(/^\\//, \"\").replace(/\\\\/g, \"/\"));\n if (fs.existsSync(full)) {\n try {\n const content = fs.readFileSync(full, \"utf8\");\n referenceBlock += `\\n\\n--- Arquivo: ${p} ---\\n${content.slice(0, 6000)}`;\n } catch {}\n }\n }\n }\n\n const GROQ_KEY = process.env.GROQ_API_KEY;\n const GEMINI_KEY = process.env.GEMINI_API_KEY;\n const OPENAI_KEY = process.env.OPENAI_API_KEY || process.env.QA_LAB_LLM_API_KEY;\n\n if (!GROQ_KEY && !GEMINI_KEY && !OPENAI_KEY) {\n return {\n content: [{ type: \"text\", text: \"Configure GROQ_API_KEY, GEMINI_API_KEY ou OPENAI_API_KEY no .env\" }],\n structuredContent: { ok: false, error: \"No API key configured\" },\n };\n }\n\n const provider = GROQ_KEY ? \"groq\" : GEMINI_KEY ? \"gemini\" : \"openai\";\n const apiKey = GROQ_KEY || GEMINI_KEY || OPENAI_KEY;\n const baseUrl = provider === \"groq\" \n ? \"https://api.groq.com/openai/v1\"\n : provider === \"gemini\"\n ? \"https://generativelanguage.googleapis.com/v1beta\"\n : \"https://api.openai.com/v1\";\n const model = provider === \"groq\"\n ? \"llama-3.3-70b-versatile\"\n : provider === \"gemini\"\n ? \"gemini-1.5-flash\"\n : \"gpt-4o-mini\";\n\n const hasReference = Boolean(referenceBlock?.trim());\n const systemPrompt = hasReference\n ? `Você é um engenheiro de QA. TRADUZA/ADAPTE o código de referência para o framework ${fw}.\nO código de referência pode estar em QUALQUER framework (Cypress, Robot, Playwright, WDIO, Appium, pytest, etc).\n- Mantenha a MESMA lógica e fluxo de teste\n- Traduza seletores, comandos e asserções para ${fw}\n- Use Page Objects se o projeto já usa\n- Retorne SOMENTE o código, sem markdown`\n : `Você é um engenheiro de QA especializado em ${fw}. Gere APENAS o código do spec, sem explicações.\nFramework: ${fw}\nRegras:\n- Cypress: cy.request(), cy.visit(), cy.get()\n- Playwright: test(), test.describe(), page.goto(), page.locator()\n- WebdriverIO/Appium: describe(), it(), $(), browser.$\n- Jest/Vitest: describe(), test(), expect()\n- Robot: Keywords, [Tags], Steps\n- pytest: def test_*, assert, fixtures\n- Código limpo. Retorne SOMENTE o código, sem markdown`;\n\n const userPrompt = `Contexto do projeto:\n${context.slice(0, 5000)}\n\nGere um teste para: ${request}\nFramework alvo: ${fw}${referenceBlock}`;\n\n try {\n let specContent;\n if (provider === \"gemini\") {\n const url = `${baseUrl}/models/${model}:generateContent?key=${apiKey}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n systemInstruction: { parts: [{ text: systemPrompt }] },\n contents: [{ parts: [{ text: userPrompt }] }],\n generationConfig: { temperature: 0.3, maxOutputTokens: 4096 },\n }),\n });\n const data = await res.json();\n specContent = data.candidates?.[0]?.content?.parts?.[0]?.text || \"\";\n } else {\n const res = await fetch(`${baseUrl}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userPrompt },\n ],\n temperature: 0.3,\n max_tokens: 4096,\n }),\n });\n const data = await res.json();\n specContent = data.choices?.[0]?.message?.content || \"\";\n }\n\n specContent = specContent.replace(/^```(?:js|javascript)?\\n?/i, \"\").replace(/\\n?```\\s*$/i, \"\").trim();\n const fileName = request.toLowerCase().replace(/\\s+/g, \"-\").replace(/[^a-z0-9-]/g, \"\").slice(0, 40);\n\n return {\n content: [{ type: \"text\", text: `Spec gerado (${specContent.length} chars). Use write_test para gravar.` }],\n structuredContent: {\n ok: true,\n specContent,\n suggestedFileName: fileName,\n },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao gerar: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\nfunction getExtensionAndBaseDir(fw, structure) {\n const extMap = {\n cypress: \".cy.js\",\n playwright: \".spec.js\",\n jest: \".test.js\",\n vitest: \".test.js\",\n mocha: \".test.js\",\n webdriverio: \".spec.js\",\n appium: \".spec.js\",\n detox: \".e2e.js\",\n robot: \".robot\",\n pytest: \"_test.py\",\n behave: \".feature\",\n supertest: \".test.js\",\n pactum: \".test.js\",\n };\n const ext = extMap[fw] || \".spec.js\";\n\n const baseMap = {\n cypress: structure.testDirs.includes(\"cypress\") ? \"cypress\" : structure.testDirs[0] || \"tests\",\n playwright: structure.testDirs.includes(\"playwright\") ? \"playwright\" : structure.testDirs[0] || \"tests\",\n webdriverio: structure.testDirs.includes(\"specs\") ? \"specs\" : structure.testDirs[0] || \"tests\",\n appium: structure.testDirs.includes(\"specs\") ? \"specs\" : structure.testDirs[0] || \"tests\",\n robot: structure.testDirs.includes(\"robot\") ? \"robot\" : structure.testDirs[0] || \"tests\",\n behave: structure.testDirs.includes(\"features\") ? \"features\" : structure.testDirs[0] || \"tests\",\n };\n const baseDir = path.join(PROJECT_ROOT, baseMap[fw] || structure.testDirs[0] || \"tests\");\n return { ext, baseDir };\n}\n\nserver.registerTool(\n \"write_test\",\n {\n title: \"Escrever arquivo de teste\",\n description: \"Grava spec no disco. Suporta QUALQUER framework (Cypress, Playwright, WDIO, Appium, Robot, pytest, etc.). Detecta automaticamente pasta e extensão.\",\n inputSchema: z.object({\n name: z.string().describe(\"Nome do arquivo (ex: login-test, logout_spec).\"),\n content: z.string().describe(\"Conteúdo do spec.\"),\n framework: z.enum([\n \"cypress\", \"playwright\", \"jest\", \"vitest\", \"mocha\", \"webdriverio\",\n \"appium\", \"detox\", \"robot\", \"pytest\", \"behave\", \"supertest\"\n ]).optional().describe(\"Framework (detectado automaticamente se omitido).\"),\n subdir: z.string().optional().describe(\"Subpasta (ex: e2e, api). Default: raiz da pasta de testes.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n path: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ name, content, framework, subdir }) => {\n const structure = detectProjectStructure();\n const fw = framework || structure.testFrameworks[0];\n\n if (!fw) {\n return {\n content: [{ type: \"text\", text: \"Nenhum framework de teste detectado.\" }],\n structuredContent: { ok: false, error: \"No test framework\" },\n };\n }\n\n const { ext, baseDir } = getExtensionAndBaseDir(fw, structure);\n const safeName = name\n .replace(/[^a-z0-9-_]/gi, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/_+/g, \"_\")\n .replace(/\\.(cy|spec|test|robot|feature|py)\\.?(js|ts|py)?$/i, \"\")\n .replace(/^[-_]+|[-_]+$/g, \"\");\n const fileName = ext.startsWith(\"_\") ? `${safeName}${ext}` : `${safeName}${ext}`;\n\n const targetDir = subdir ? path.join(baseDir, subdir) : baseDir;\n const filePath = path.join(targetDir, fileName);\n\n try {\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n }\n fs.writeFileSync(filePath, content, \"utf8\");\n return {\n content: [{ type: \"text\", text: `Arquivo gravado: ${filePath}` }],\n structuredContent: { ok: true, path: filePath },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao gravar: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\nserver.registerTool(\n \"analyze_failures\",\n {\n title: \"Analisar falhas de testes\",\n description: \"Recebe output de testes e extrai falhas estruturadas.\",\n inputSchema: z.object({\n runOutput: z.string().describe(\"Output do teste (stdout/stderr).\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n summary: z.string(),\n failures: z.array(z.object({\n test: z.string().optional(),\n message: z.string().optional(),\n stack: z.string().optional(),\n })).optional(),\n }),\n },\n async ({ runOutput }) => {\n const failures = [];\n const lines = runOutput.split(\"\\n\");\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (/fail|error|assertion/i.test(line)) {\n failures.push({\n test: lines[i - 1] || \"unknown\",\n message: line.trim(),\n stack: lines.slice(i, i + 5).join(\"\\n\"),\n });\n }\n }\n\n const summary = failures.length\n ? `${failures.length} falha(s) detectada(s).`\n : \"Nenhuma falha detectada.\";\n\n return {\n content: [{ type: \"text\", text: summary }],\n structuredContent: { ok: true, summary, failures: failures.length ? failures : undefined },\n };\n }\n);\n\n// ============================================================================\n// POR QUE FALHOU? - Explicação de falhas para juniores (escalável)\n// ============================================================================\n\nfunction formatFailureExplanation(data) {\n const lines = [\n \"## O que aconteceu\",\n \"\",\n data.oQueAconteceu || \"\",\n \"\",\n \"## Por que provavelmente falhou\",\n \"\",\n ...(Array.isArray(data.porQueProvavelmenteFalhou)\n ? data.porQueProvavelmenteFalhou.map((s) => `• ${s}`)\n : [data.porQueProvavelmenteFalhou || \"\"]),\n \"\",\n \"## O que fazer agora\",\n \"\",\n ...(Array.isArray(data.oQueFazerAgora)\n ? data.oQueFazerAgora.map((s, i) => `${i + 1}. ${s}`)\n : [data.oQueFazerAgora || \"\"]),\n ];\n if (data.sugestaoCorrecao) {\n lines.push(\"\", \"## Sugestão de correção\", \"\", \"```\" + (data.framework || \"js\"), data.sugestaoCorrecao, \"```\");\n }\n if (data.conceito) {\n lines.push(\"\", \"## Conceito\", \"\", data.conceito);\n }\n return lines.filter(Boolean).join(\"\\n\");\n}\n\nasync function callLlmForExplanation(provider, apiKey, baseUrl, model, systemPrompt, userPrompt) {\n if (provider === \"gemini\") {\n const url = `${baseUrl}/models/${model}:generateContent?key=${apiKey}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n contents: [{ parts: [{ text: systemPrompt + \"\\n\\n\" + userPrompt }] }],\n generationConfig: { temperature: 0.2, maxOutputTokens: 4096 },\n }),\n });\n const data = await res.json();\n return data.candidates?.[0]?.content?.parts?.[0]?.text || \"\";\n }\n const res = await fetch(`${baseUrl}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n model,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userPrompt },\n ],\n temperature: 0.2,\n max_tokens: 4096,\n }),\n });\n const data = await res.json();\n return data.choices?.[0]?.message?.content || \"\";\n}\n\n/** Gera explicação de falha (o que aconteceu, por que, o que fazer, sugestão). Usado por por_que_falhou e run_tests_and_explain. */\nasync function generateFailureExplanation(resolvedOutput, testFilePath = null) {\n const structure = detectProjectStructure();\n const fw = structure.testFrameworks[0] || \"unknown\";\n\n let testCode = \"\";\n if (testFilePath) {\n const normalized = testFilePath.replace(/^\\//, \"\").replace(/\\\\/g, \"/\");\n const fullPath = path.join(PROJECT_ROOT, normalized);\n if (fs.existsSync(fullPath) && !fs.statSync(fullPath).isDirectory()) {\n try {\n testCode = fs.readFileSync(fullPath, \"utf8\");\n } catch {}\n }\n }\n\n const GROQ_KEY = process.env.GROQ_API_KEY;\n const GEMINI_KEY = process.env.GEMINI_API_KEY;\n const OPENAI_KEY = process.env.OPENAI_API_KEY || process.env.QA_LAB_LLM_API_KEY;\n if (!GROQ_KEY && !GEMINI_KEY && !OPENAI_KEY) {\n return { ok: false, error: \"No API key\", formattedText: null };\n }\n\n const provider = GROQ_KEY ? \"groq\" : GEMINI_KEY ? \"gemini\" : \"openai\";\n const apiKey = GROQ_KEY || GEMINI_KEY || OPENAI_KEY;\n const baseUrl = provider === \"groq\"\n ? \"https://api.groq.com/openai/v1\"\n : provider === \"gemini\"\n ? \"https://generativelanguage.googleapis.com/v1beta\"\n : \"https://api.openai.com/v1\";\n const model = provider === \"groq\"\n ? \"llama-3.3-70b-versatile\"\n : provider === \"gemini\"\n ? \"gemini-1.5-flash\"\n : \"gpt-4o-mini\";\n\n const fwHints = {\n webdriverio: \"WebdriverIO (describe/it, $, browser.$)\",\n appium: \"Appium/WebdriverIO (mobile, $, browser.$)\",\n playwright: \"Playwright (test, page, locator)\",\n cypress: \"Cypress (cy.get, cy.click)\",\n jest: \"Jest (describe, test, expect)\",\n vitest: \"Vitest (describe, test, expect)\",\n robot: \"Robot Framework\",\n pytest: \"pytest\",\n };\n\n const systemPrompt = `Você é um mentor de QA. Analise o output de falha e responda em JSON (apenas o JSON, sem markdown) com as chaves:\n- oQueAconteceu: string (explicação em português do que aconteceu, simples)\n- porQueProvavelmenteFalhou: array de strings (lista de possíveis causas, uma por item)\n- oQueFazerAgora: array de strings (passos numerados do que fazer)\n- sugestaoCorrecao: string ou null (código de correção se aplicável, no formato do framework)\n- conceito: string ou null (ex: \"Flaky test = teste intermitente. Geralmente por timing ou seletores frágeis.\")\n- framework: string (framework do projeto)\n\nFramework do projeto: ${fw}. ${fwHints[fw] || \"\"}\nResponda APENAS com o JSON válido, sem texto antes ou depois.`;\n\n const userPrompt = `Output do terminal/log (teste falhou):\n---\n${resolvedOutput.slice(0, 12000)}\n---\n${testCode ? `\\nCódigo do teste que falhou:\\n---\\n${testCode.slice(0, 6000)}\\n---` : \"\"}`;\n\n try {\n let raw = await callLlmForExplanation(provider, apiKey, baseUrl, model, systemPrompt, userPrompt);\n raw = raw.replace(/^```(?:json)?\\s*/i, \"\").replace(/\\s*```\\s*$/i, \"\").trim();\n let data = {};\n try {\n data = JSON.parse(raw);\n } catch {\n data = {\n oQueAconteceu: raw.slice(0, 500) || \"Não foi possível parsear a resposta.\",\n porQueProvavelmenteFalhou: [],\n oQueFazerAgora: [],\n sugestaoCorrecao: null,\n conceito: null,\n framework: fw,\n };\n }\n data.framework = data.framework || fw;\n const formattedText = formatFailureExplanation(data);\n return { ok: true, formattedText, structuredContent: data };\n } catch (err) {\n return { ok: false, error: err.message, formattedText: null };\n }\n}\n\nserver.registerTool(\n \"por_que_falhou\",\n {\n title: \"Por que falhou? Explicação para juniores\",\n description: \"Traduz stack trace em explicação humana. Recebe output do terminal/log, lê o projeto e o teste (se path dado), e retorna: O que aconteceu, Por que falhou, O que fazer, Sugestão de correção, Conceito. Escalável e procedural.\",\n inputSchema: z.object({\n errorOutput: z.string().optional().describe(\"Output do terminal quando o teste falhou. Se vazio, lê automaticamente de .qa-lab-last-failure.log (capturado pelo run_tests). Cole aqui ou deixe vazio para usar última falha.\"),\n testFilePath: z.string().optional().describe(\"Caminho do arquivo de teste que falhou (ex: specs/login.spec.js). Se informado, o agente lê o código e dá sugestão mais precisa.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n oQueAconteceu: z.string().optional(),\n porQueProvavelmenteFalhou: z.array(z.string()).optional(),\n oQueFazerAgora: z.array(z.string()).optional(),\n sugestaoCorrecao: z.string().optional(),\n conceito: z.string().optional(),\n framework: z.string().optional(),\n formattedText: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ errorOutput, testFilePath }) => {\n const structure = detectProjectStructure();\n const fw = structure.testFrameworks[0] || \"unknown\";\n\n let resolvedOutput = errorOutput?.trim() || \"\";\n if (!resolvedOutput) {\n const lastFailurePath = path.join(PROJECT_ROOT, \".qa-lab-last-failure.log\");\n if (fs.existsSync(lastFailurePath)) {\n try {\n resolvedOutput = fs.readFileSync(lastFailurePath, \"utf8\");\n } catch {}\n }\n }\n if (!resolvedOutput) {\n return {\n content: [{\n type: \"text\",\n text: \"Nenhum output de erro fornecido e nenhuma falha recente capturada.\\n\\nComo usar:\\n1. Rode os testes (run_tests) – se falhar, a saída é salva automaticamente.\\n2. Ou cole aqui o output do terminal quando o teste falhou.\\n3. Depois peça: 'Por que falhou?' ou chame por_que_falhou.\",\n }],\n structuredContent: { ok: false, error: \"No error output\" },\n };\n }\n\n let testCode = \"\";\n if (testFilePath) {\n const normalized = testFilePath.replace(/^\\//, \"\").replace(/\\\\/g, \"/\");\n const fullPath = path.join(PROJECT_ROOT, normalized);\n if (fs.existsSync(fullPath) && !fs.statSync(fullPath).isDirectory()) {\n try {\n testCode = fs.readFileSync(fullPath, \"utf8\");\n } catch {}\n }\n }\n\n const GROQ_KEY = process.env.GROQ_API_KEY;\n const GEMINI_KEY = process.env.GEMINI_API_KEY;\n const OPENAI_KEY = process.env.OPENAI_API_KEY || process.env.QA_LAB_LLM_API_KEY;\n\n if (!GROQ_KEY && !GEMINI_KEY && !OPENAI_KEY) {\n return {\n content: [{\n type: \"text\",\n text: \"Configure GROQ_API_KEY, GEMINI_API_KEY ou OPENAI_API_KEY no .env do projeto para usar a explicação com LLM.\",\n }],\n structuredContent: { ok: false, error: \"No API key configured\" },\n };\n }\n\n const provider = GROQ_KEY ? \"groq\" : GEMINI_KEY ? \"gemini\" : \"openai\";\n const apiKey = GROQ_KEY || GEMINI_KEY || OPENAI_KEY;\n const baseUrl = provider === \"groq\"\n ? \"https://api.groq.com/openai/v1\"\n : provider === \"gemini\"\n ? \"https://generativelanguage.googleapis.com/v1beta\"\n : \"https://api.openai.com/v1\";\n const model = provider === \"groq\"\n ? \"llama-3.3-70b-versatile\"\n : provider === \"gemini\"\n ? \"gemini-1.5-flash\"\n : \"gpt-4o-mini\";\n\n const fwHints = {\n webdriverio: \"WebdriverIO (describe/it, $, browser.$)\",\n appium: \"Appium/WebdriverIO (mobile, $, browser.$)\",\n playwright: \"Playwright (test, page, locator)\",\n cypress: \"Cypress (cy.get, cy.click)\",\n jest: \"Jest (describe, test, expect)\",\n vitest: \"Vitest (describe, test, expect)\",\n robot: \"Robot Framework\",\n pytest: \"pytest\",\n };\n\n const systemPrompt = `Você é um mentor de QA. Analise o output de falha e responda em JSON (apenas o JSON, sem markdown) com as chaves:\n- oQueAconteceu: string (explicação em português do que aconteceu, simples)\n- porQueProvavelmenteFalhou: array de strings (lista de possíveis causas, uma por item)\n- oQueFazerAgora: array de strings (passos numerados do que fazer)\n- sugestaoCorrecao: string ou null (código de correção se aplicável, no formato do framework)\n- conceito: string ou null (ex: \"Flaky test = teste intermitente. Geralmente por timing ou seletores frágeis.\")\n- framework: string (framework do projeto)\n\nFramework do projeto: ${fw}. ${fwHints[fw] || \"\"}\nResponda APENAS com o JSON válido, sem texto antes ou depois.`;\n\n const userPrompt = `Output do terminal/log (teste falhou):\n---\n${resolvedOutput.slice(0, 12000)}\n---\n${testCode ? `\\nCódigo do teste que falhou:\\n---\\n${testCode.slice(0, 6000)}\\n---` : \"\"}`;\n\n try {\n let raw = await callLlmForExplanation(provider, apiKey, baseUrl, model, systemPrompt, userPrompt);\n raw = raw.replace(/^```(?:json)?\\s*/i, \"\").replace(/\\s*```\\s*$/i, \"\").trim();\n\n let data = {};\n try {\n data = JSON.parse(raw);\n } catch {\n data = {\n oQueAconteceu: raw.slice(0, 500) || \"Não foi possível parsear a resposta.\",\n porQueProvavelmenteFalhou: [],\n oQueFazerAgora: [],\n sugestaoCorrecao: null,\n conceito: null,\n framework: fw,\n };\n }\n\n data.framework = data.framework || fw;\n const formattedText = formatFailureExplanation(data);\n\n return {\n content: [{ type: \"text\", text: formattedText }],\n structuredContent: {\n ok: true,\n oQueAconteceu: data.oQueAconteceu,\n porQueProvavelmenteFalhou: data.porQueProvavelmenteFalhou,\n oQueFazerAgora: data.oQueFazerAgora,\n sugestaoCorrecao: data.sugestaoCorrecao ?? null,\n conceito: data.conceito ?? null,\n framework: data.framework,\n formattedText,\n },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao analisar: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\n// ============================================================================\n// NOVAS FERRAMENTAS\n// ============================================================================\n\nserver.registerTool(\n \"suggest_fix\",\n {\n title: \"Sugerir correção para falhas\",\n description: \"Recebe análise de falhas e sugere correções (patch, refactor, etc.).\",\n inputSchema: z.object({\n failures: z.array(z.object({\n test: z.string().optional(),\n message: z.string().optional(),\n stack: z.string().optional(),\n })).describe(\"Resultado de analyze_failures.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n suggestions: z.array(z.object({\n test: z.string().optional(),\n description: z.string(),\n fix: z.string().optional(),\n })),\n }),\n },\n async ({ failures }) => {\n const suggestions = [];\n\n for (const f of failures) {\n const msg = f.message || \"\";\n \n if (/element not found|selector|timeout/i.test(msg)) {\n suggestions.push({\n test: f.test,\n description: \"Elemento não encontrado ou timeout\",\n fix: \"Verifique seletores, adicione waits ou aumente timeout. Use data-testid para seletores mais estáveis.\",\n });\n } else if (/expected.*to.*but/i.test(msg)) {\n suggestions.push({\n test: f.test,\n description: \"Asserção falhou\",\n fix: \"Revise o valor esperado. Verifique se o estado da aplicação está correto antes da asserção.\",\n });\n } else if (/network|fetch|ECONNREFUSED/i.test(msg)) {\n suggestions.push({\n test: f.test,\n description: \"Erro de rede ou API não disponível\",\n fix: \"Verifique se o backend está rodando. Confirme a URL e porta da API.\",\n });\n } else {\n suggestions.push({\n test: f.test,\n description: \"Falha detectada\",\n fix: \"Revise o stack trace e o código do teste.\",\n });\n }\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(suggestions, null, 2) }],\n structuredContent: { ok: true, suggestions },\n };\n }\n);\n\n// ============================================================================\n// SELF-HEALING - Sugestão de correção de seletores quando UI muda\n// ============================================================================\n\nserver.registerTool(\n \"suggest_selector_fix\",\n {\n title: \"Sugerir correção de seletor (Self-healing)\",\n description: \"Quando um teste falha por elemento não encontrado (seletor quebrado após mudança de UI), usa LLM para sugerir seletor alternativo mais resiliente. Prioriza data-testid, role, texto acessível.\",\n inputSchema: z.object({\n testFilePath: z.string().describe(\"Caminho do arquivo de teste que falhou (ex: specs/login.spec.js).\"),\n errorOutput: z.string().optional().describe(\"Output do terminal da falha. Se vazio, lê de .qa-lab-last-failure.log.\"),\n framework: z.enum([\"cypress\", \"playwright\", \"webdriverio\", \"appium\"]).optional().describe(\"Framework do teste. Detectado automaticamente se omitido.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n selectorSugerido: z.string().optional(),\n codigoCorrigido: z.string().optional(),\n explicacao: z.string().optional(),\n error: z.string().optional(),\n }),\n },\n async ({ testFilePath, errorOutput, framework }) => {\n const structure = detectProjectStructure();\n const fw = framework || inferFrameworkFromFile(testFilePath.split(\"/\").pop(), structure);\n\n let resolvedOutput = errorOutput;\n if (!resolvedOutput) {\n const logPath = path.join(PROJECT_ROOT, \".qa-lab-last-failure.log\");\n if (fs.existsSync(logPath)) {\n resolvedOutput = fs.readFileSync(logPath, \"utf8\");\n }\n }\n if (!resolvedOutput) {\n return {\n content: [{ type: \"text\", text: \"Nenhum output de erro. Rode os testes primeiro ou forneça errorOutput.\" }],\n structuredContent: { ok: false, error: \"No error output\" },\n };\n }\n\n if (!/element not found|selector|timeout|locator|cy\\.get|page\\.locator/i.test(resolvedOutput)) {\n return {\n content: [{ type: \"text\", text: \"A falha não parece ser de seletor/elemento. Use por_que_falhou ou suggest_fix para outros tipos de falha.\" }],\n structuredContent: { ok: false, error: \"Not a selector-related failure\" },\n };\n }\n\n let testCode = \"\";\n const fullPath = path.join(PROJECT_ROOT, testFilePath.replace(/^\\//, \"\").replace(/\\\\/g, \"/\"));\n if (fs.existsSync(fullPath)) {\n try {\n testCode = fs.readFileSync(fullPath, \"utf8\");\n } catch {}\n }\n\n const GROQ_KEY = process.env.GROQ_API_KEY;\n const GEMINI_KEY = process.env.GEMINI_API_KEY;\n const OPENAI_KEY = process.env.OPENAI_API_KEY || process.env.QA_LAB_LLM_API_KEY;\n if (!GROQ_KEY && !GEMINI_KEY && !OPENAI_KEY) {\n return {\n content: [{ type: \"text\", text: \"Configure GROQ_API_KEY, GEMINI_API_KEY ou OPENAI_API_KEY no .env\" }],\n structuredContent: { ok: false, error: \"No API key configured\" },\n };\n }\n\n const provider = GROQ_KEY ? \"groq\" : GEMINI_KEY ? \"gemini\" : \"openai\";\n const apiKey = GROQ_KEY || GEMINI_KEY || OPENAI_KEY;\n const baseUrl = provider === \"groq\" ? \"https://api.groq.com/openai/v1\" : provider === \"gemini\" ? \"https://generativelanguage.googleapis.com/v1beta\" : \"https://api.openai.com/v1\";\n const model = provider === \"groq\" ? \"llama-3.3-70b-versatile\" : provider === \"gemini\" ? \"gemini-1.5-flash\" : \"gpt-4o-mini\";\n\n const fwHints = {\n cypress: \"Cypress: cy.get('[data-testid=...]'), cy.contains(), cy.get('button').filter(':visible')\",\n playwright: \"Playwright: page.getByRole(), page.getByTestId(), page.locator('button:has-text(\\\"...\\\")')\",\n webdriverio: \"WebdriverIO: $('[data-testid=...]'), $('button=Texto')\",\n appium: \"Appium: $('~accessibility-id'), $('//android.view.View')\",\n };\n\n const systemPrompt = `Você é um especialista em testes E2E. O teste falhou porque um seletor não encontrou o elemento (UI mudou).\nAnalise o erro e o código e responda APENAS em JSON (sem markdown) com as chaves:\n- selectorSugerido: string (o novo seletor recomendado, mais resiliente)\n- codigoCorrigido: string (bloco de código completo corrigido, apenas a parte relevante do teste)\n- explicacao: string (breve explicação em português: por que o antigo falhou e por que o novo é melhor)\n\nPriorize nesta ordem: data-testid > role + accessible name > texto visível > estrutura. Evite classes CSS e IDs que mudam.\n\nFramework: ${fw}. ${fwHints[fw] || \"\"}`;\n\n const userPrompt = `Output do erro:\n---\n${resolvedOutput.slice(0, 8000)}\n---\nCódigo do teste:\n---\n${testCode ? testCode.slice(0, 6000) : \"Não disponível\"}\n---`;\n\n try {\n let raw = await callLlmForExplanation(provider, apiKey, baseUrl, model, systemPrompt, userPrompt);\n raw = raw.replace(/^```(?:json)?\\s*/i, \"\").replace(/\\s*```\\s*$/i, \"\").trim();\n let data = {};\n try {\n data = JSON.parse(raw);\n } catch {\n data = {\n selectorSugerido: null,\n codigoCorrigido: raw.slice(0, 2000),\n explicacao: \"Não foi possível parsear. Resposta do LLM acima.\",\n };\n }\n\n const text = [\n data.explicacao && `## Explicação\\n${data.explicacao}`,\n data.selectorSugerido && `## Seletor sugerido\\n\\`${data.selectorSugerido}\\``,\n data.codigoCorrigido && `## Código corrigido\\n\\`\\`\\`${fw}\\n${data.codigoCorrigido}\\n\\`\\`\\``,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n return {\n content: [{ type: \"text\", text: text || JSON.stringify(data, null, 2) }],\n structuredContent: {\n ok: true,\n selectorSugerido: data.selectorSugerido,\n codigoCorrigido: data.codigoCorrigido,\n explicacao: data.explicacao,\n },\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: `Erro ao chamar LLM: ${err.message}` }],\n structuredContent: { ok: false, error: err.message },\n };\n }\n }\n);\n\nserver.registerTool(\n \"create_bug_report\",\n {\n title: \"Criar relatório de bug\",\n description: \"Gera um bug report estruturado a partir de falhas de teste.\",\n inputSchema: z.object({\n failures: z.array(z.object({\n test: z.string().optional(),\n message: z.string().optional(),\n stack: z.string().optional(),\n })).describe(\"Falhas (de analyze_failures).\"),\n title: z.string().optional().describe(\"Título do bug.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n report: z.string(),\n title: z.string(),\n }),\n },\n async ({ failures, title }) => {\n const bugTitle = title || `Falha em ${failures.length} teste(s)`;\n const lines = [\n `# ${bugTitle}`,\n \"\",\n \"## Resumo\",\n \"\",\n `${failures.length} teste(s) falharam durante a execução.`,\n \"\",\n \"## Falhas detectadas\",\n \"\",\n ];\n\n failures.forEach((f, i) => {\n lines.push(`### ${i + 1}. ${f.test || \"Teste desconhecido\"}`);\n lines.push(\"\");\n lines.push(`**Mensagem:** ${f.message || \"N/A\"}`);\n lines.push(\"\");\n if (f.stack) {\n lines.push(\"**Stack trace:**\");\n lines.push(\"```\");\n lines.push(f.stack);\n lines.push(\"```\");\n lines.push(\"\");\n }\n });\n\n lines.push(\"## Próximos passos\");\n lines.push(\"\");\n lines.push(\"- [ ] Reproduzir localmente\");\n lines.push(\"- [ ] Identificar causa raiz\");\n lines.push(\"- [ ] Aplicar correção\");\n lines.push(\"- [ ] Validar com testes\");\n\n const report = lines.join(\"\\n\");\n\n appendMetricsEvent({ type: \"bug_reported\", failuresCount: failures.length, title: bugTitle });\n\n return {\n content: [{ type: \"text\", text: report }],\n structuredContent: { ok: true, report, title: bugTitle },\n };\n }\n);\n\n// ============================================================================\n// MÉTRICAS DE NEGÓCIO - Relatório agregado\n// ============================================================================\n\nserver.registerTool(\n \"get_business_metrics\",\n {\n title: \"Obter métricas de negócio\",\n description: \"Retorna métricas: tempo até bug, custo por defeito (tempo estimado), cobertura por fluxo. Requer run_tests executados e opcionalmente qa-lab-flows.json.\",\n inputSchema: z.object({\n period: z.enum([\"7d\", \"30d\", \"all\"]).optional().describe(\"Período para analisar. Default: 30d.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n timeToBug: z.object({\n avgHours: z.number(),\n lastFailureAt: z.string().optional(),\n runsWithFailures: z.number(),\n }).optional(),\n costPerDefect: z.object({\n avgMinutesPerDefect: z.number(),\n totalFailures: z.number(),\n estimatedHoursSpent: z.number(),\n }).optional(),\n flowCoverage: z.object({\n totalFlows: z.number(),\n coveredFlows: z.number(),\n percent: z.number(),\n details: z.array(z.object({ flow: z.string(), covered: z.boolean() })),\n }).optional(),\n summary: z.string(),\n }),\n },\n async ({ period = \"30d\" } = {}) => {\n const now = Date.now();\n const msByPeriod = { \"7d\": 7 * 24 * 60 * 60 * 1000, \"30d\": 30 * 24 * 60 * 60 * 1000, all: Infinity };\n const cutoff = now - msByPeriod[period];\n\n let data = { events: [] };\n if (fs.existsSync(METRICS_FILE)) {\n try {\n data = JSON.parse(fs.readFileSync(METRICS_FILE, \"utf8\"));\n } catch {}\n }\n\n const events = (data.events || []).filter((e) => new Date(e.timestamp).getTime() >= cutoff);\n\n const testRuns = events.filter((e) => e.type === \"test_run\");\n const failedRuns = testRuns.filter((e) => (e.failed || 0) > 0);\n const totalFailed = testRuns.reduce((sum, e) => sum + (e.failed || 0), 0);\n const totalDuration = testRuns.reduce((sum, e) => sum + (e.durationSeconds || 0), 0);\n\n let timeToBug = null;\n if (failedRuns.length > 0) {\n const lastFailure = failedRuns[failedRuns.length - 1];\n timeToBug = {\n avgHours: 0,\n lastFailureAt: lastFailure.timestamp,\n runsWithFailures: failedRuns.length,\n };\n if (failedRuns.length >= 2) {\n const deltas = [];\n for (let i = 1; i < failedRuns.length; i++) {\n const prev = new Date(failedRuns[i - 1].timestamp).getTime();\n const curr = new Date(failedRuns[i].timestamp).getTime();\n deltas.push((curr - prev) / (1000 * 60 * 60));\n }\n timeToBug.avgHours = deltas.reduce((a, b) => a + b, 0) / deltas.length;\n }\n }\n\n let costPerDefect = null;\n if (totalFailed > 0) {\n const estimatedMinutesSpent = totalDuration + totalFailed * 5;\n costPerDefect = {\n avgMinutesPerDefect: Math.round(estimatedMinutesSpent / totalFailed),\n totalFailures: totalFailed,\n estimatedHoursSpent: Math.round((estimatedMinutesSpent / 60) * 10) / 10,\n };\n }\n\n let flowCoverage = null;\n if (fs.existsSync(FLOWS_CONFIG_FILE)) {\n try {\n const flowsConfig = JSON.parse(fs.readFileSync(FLOWS_CONFIG_FILE, \"utf8\"));\n const flows = flowsConfig.flows || [];\n const structure = detectProjectStructure();\n const allTestFiles = new Set(collectTestFiles(structure).map((e) => e.path));\n\n const details = flows.map((f) => {\n const testFiles = f.testFiles || [];\n const covered = testFiles.some((tf) => allTestFiles.has(tf) || allTestFiles.has(tf.replace(/\\\\/g, \"/\")));\n return { flow: f.name || f.id || \"?\", covered };\n });\n\n flowCoverage = {\n totalFlows: flows.length,\n coveredFlows: details.filter((d) => d.covered).length,\n percent: flows.length ? Math.round((details.filter((d) => d.covered).length / flows.length) * 100) : 0,\n details,\n };\n } catch {}\n }\n\n const lines = [\n \"## Métricas de negócio\",\n \"\",\n `Período: ${period}`,\n \"\",\n timeToBug\n ? [\n \"### Tempo até bug\",\n `- Última falha: ${timeToBug.lastFailureAt || \"N/A\"}`,\n `- Execuções com falha: ${timeToBug.runsWithFailures}`,\n timeToBug.avgHours > 0 ? `- Média entre falhas: ${timeToBug.avgHours.toFixed(1)}h` : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\")\n : \"\",\n costPerDefect\n ? [\n \"### Custo por defeito (estimativa)\",\n `- Total de falhas: ${costPerDefect.totalFailures}`,\n `- Tempo médio por defeito: ~${costPerDefect.avgMinutesPerDefect} min`,\n `- Horas estimadas gastas: ${costPerDefect.estimatedHoursSpent}h`,\n ].join(\"\\n\")\n : \"\",\n flowCoverage\n ? [\n \"### Cobertura por fluxo\",\n `- Fluxos cobertos: ${flowCoverage.coveredFlows}/${flowCoverage.totalFlows} (${flowCoverage.percent}%)`,\n flowCoverage.details.map((d) => ` - ${d.flow}: ${d.covered ? \"✅\" : \"❌\"}`).join(\"\\n\"),\n ].join(\"\\n\")\n : \"\",\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n if (!timeToBug && !costPerDefect && !flowCoverage) {\n const msg =\n \"Nenhuma métrica disponível. Rode run_tests para gerar dados. Para cobertura por fluxo, crie qa-lab-flows.json.\";\n return {\n content: [{ type: \"text\", text: msg }],\n structuredContent: { ok: false, summary: msg },\n };\n }\n\n const summary = [\n timeToBug && `${timeToBug.runsWithFailures} execuções com falha`,\n costPerDefect && `${costPerDefect.totalFailures} falhas (~${costPerDefect.avgMinutesPerDefect} min/defeito)`,\n flowCoverage && `${flowCoverage.coveredFlows}/${flowCoverage.totalFlows} fluxos cobertos`,\n ]\n .filter(Boolean)\n .join(\" | \");\n\n return {\n content: [{ type: \"text\", text: lines || summary }],\n structuredContent: {\n ok: true,\n timeToBug,\n costPerDefect,\n flowCoverage,\n summary,\n },\n };\n }\n);\n\nserver.registerTool(\n \"list_test_files\",\n {\n title: \"Listar arquivos de teste\",\n description: \"Lista TODOS os arquivos de teste (qualquer framework: Cypress, Playwright, WDIO, Robot, pytest, Behave, etc.) com filtro opcional.\",\n inputSchema: z.object({\n framework: z.enum([\n \"cypress\", \"playwright\", \"jest\", \"webdriverio\", \"appium\", \"robot\", \"pytest\", \"behave\", \"detox\", \"all\"\n ]).optional().describe(\"Filtrar por framework. Default: all.\"),\n pattern: z.string().optional().describe(\"Pattern para filtrar (ex: 'login', 'api').\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n files: z.array(z.string()),\n total: z.number(),\n }),\n },\n async ({ framework = \"all\", pattern } = {}) => {\n const structure = detectProjectStructure();\n const collected = collectTestFiles(structure, { framework, pattern });\n const allFiles = collected.map((e) => e.path);\n\n const summary = `Encontrados ${allFiles.length} arquivo(s) de teste (qualquer framework).`;\n\n return {\n content: [{ type: \"text\", text: `${summary}\\n\\n${allFiles.slice(0, 50).join(\"\\n\")}` }],\n structuredContent: { ok: true, files: allFiles, total: allFiles.length },\n };\n }\n);\n\nserver.registerTool(\n \"run_linter\",\n {\n title: \"Executar linter\",\n description: \"Roda ESLint, Prettier ou linter configurado no projeto.\",\n inputSchema: z.object({\n fix: z.boolean().optional().describe(\"Auto-fix (--fix). Default: false.\"),\n path: z.string().optional().describe(\"Caminho específico (ex: src/). Default: todo o projeto.\"),\n }),\n outputSchema: z.object({\n status: z.enum([\"passed\", \"failed\", \"not_found\"]),\n message: z.string(),\n exitCode: z.number(),\n output: z.string().optional(),\n }),\n },\n async ({ fix, path: targetPath }) => {\n const structure = detectProjectStructure();\n const scripts = structure.packageJson?.scripts || {};\n\n let cmd, args;\n if (scripts.lint) {\n cmd = \"npm\";\n args = [\"run\", \"lint\"];\n } else if (structure.packageJson?.devDependencies?.eslint || structure.packageJson?.dependencies?.eslint) {\n cmd = \"npx\";\n args = [\"eslint\", targetPath || \".\"];\n if (fix) args.push(\"--fix\");\n } else {\n return {\n content: [{ type: \"text\", text: \"Linter não detectado no projeto.\" }],\n structuredContent: { status: \"not_found\", message: \"No linter found\", exitCode: 1 },\n };\n }\n\n return new Promise((resolve) => {\n const child = spawn(cmd, args, {\n cwd: PROJECT_ROOT,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n shell: process.platform === \"win32\",\n env: { ...process.env },\n });\n\n let stdout = \"\";\n let stderr = \"\";\n if (child.stdout) child.stdout.on(\"data\", (d) => { stdout += d.toString(); });\n if (child.stderr) child.stderr.on(\"data\", (d) => { stderr += d.toString(); });\n\n child.on(\"close\", (code) => {\n const output = [stdout, stderr].filter(Boolean).join(\"\\n\").trim();\n const passed = code === 0;\n resolve({\n content: [{ type: \"text\", text: passed ? \"Linter passou.\" : \"Linter encontrou problemas.\" }],\n structuredContent: {\n status: passed ? \"passed\" : \"failed\",\n message: passed ? \"Lint passed\" : \"Lint failed\",\n exitCode: code ?? 1,\n output: !passed ? output : undefined,\n },\n });\n });\n });\n }\n);\n\nserver.registerTool(\n \"install_dependencies\",\n {\n title: \"Instalar dependências\",\n description: \"Roda npm install, yarn install ou pnpm install (detecta automaticamente).\",\n inputSchema: z.object({\n packageManager: z.enum([\"npm\", \"yarn\", \"pnpm\", \"auto\"]).optional().describe(\"Package manager. Default: auto.\"),\n }),\n outputSchema: z.object({\n status: z.enum([\"success\", \"failed\"]),\n message: z.string(),\n exitCode: z.number(),\n }),\n },\n async ({ packageManager = \"auto\" }) => {\n let pm = packageManager;\n \n if (pm === \"auto\") {\n if (fs.existsSync(path.join(PROJECT_ROOT, \"yarn.lock\"))) pm = \"yarn\";\n else if (fs.existsSync(path.join(PROJECT_ROOT, \"pnpm-lock.yaml\"))) pm = \"pnpm\";\n else pm = \"npm\";\n }\n\n return new Promise((resolve) => {\n const child = spawn(pm, [\"install\"], {\n cwd: PROJECT_ROOT,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n env: { ...process.env },\n });\n\n child.on(\"close\", (code) => {\n const passed = code === 0;\n resolve({\n content: [{ type: \"text\", text: passed ? \"Dependências instaladas.\" : \"Erro ao instalar dependências.\" }],\n structuredContent: {\n status: passed ? \"success\" : \"failed\",\n message: passed ? \"Dependencies installed\" : \"Install failed\",\n exitCode: code ?? 1,\n },\n });\n });\n });\n }\n);\n\nserver.registerTool(\n \"get_test_coverage\",\n {\n title: \"Obter cobertura de testes\",\n description: \"Roda testes com coverage (Jest, Playwright, Cypress com plugin).\",\n inputSchema: z.object({\n framework: z.enum([\"jest\", \"playwright\", \"cypress\"]).optional().describe(\"Framework. Default: detectado automaticamente.\"),\n }),\n outputSchema: z.object({\n status: z.enum([\"success\", \"failed\", \"not_supported\"]),\n message: z.string(),\n coveragePercent: z.number().optional(),\n output: z.string().optional(),\n }),\n },\n async ({ framework }) => {\n const structure = detectProjectStructure();\n const fw = framework || structure.testFrameworks[0];\n\n if (fw === \"jest\") {\n return new Promise((resolve) => {\n const child = spawn(\"npx\", [\"jest\", \"--coverage\"], {\n cwd: PROJECT_ROOT,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n shell: process.platform === \"win32\",\n env: { ...process.env },\n });\n\n let stdout = \"\";\n if (child.stdout) child.stdout.on(\"data\", (d) => { stdout += d.toString(); });\n\n child.on(\"close\", (code) => {\n const coverageMatch = stdout.match(/All files.*?(\\d+\\.?\\d*)/);\n const coveragePercent = coverageMatch ? parseFloat(coverageMatch[1]) : undefined;\n\n resolve({\n content: [{ type: \"text\", text: `Coverage: ${coveragePercent || \"N/A\"}%` }],\n structuredContent: {\n status: code === 0 ? \"success\" : \"failed\",\n message: code === 0 ? \"Coverage generated\" : \"Coverage failed\",\n coveragePercent,\n output: stdout,\n },\n });\n });\n });\n }\n\n return {\n content: [{ type: \"text\", text: `Coverage não suportado para ${fw} ainda.` }],\n structuredContent: { status: \"not_supported\", message: \"Coverage not supported for this framework\" },\n };\n }\n);\n\nserver.registerTool(\n \"watch_tests\",\n {\n title: \"Rodar testes em modo watch\",\n description: \"Inicia testes em watch mode (Jest, Vitest). Útil para desenvolvimento.\",\n inputSchema: z.object({\n framework: z.enum([\"jest\", \"vitest\"]).optional().describe(\"Framework. Default: detectado.\"),\n }),\n outputSchema: z.object({\n status: z.string(),\n message: z.string(),\n }),\n },\n async ({ framework }) => {\n const structure = detectProjectStructure();\n const fw = framework || (structure.testFrameworks.includes(\"jest\") ? \"jest\" : \"vitest\");\n\n if (!structure.testFrameworks.includes(fw)) {\n return {\n content: [{ type: \"text\", text: `${fw} não detectado no projeto.` }],\n structuredContent: { status: \"not_found\", message: \"Framework not found\" },\n };\n }\n\n return {\n content: [{ type: \"text\", text: `Para watch mode, rode manualmente: npx ${fw} --watch` }],\n structuredContent: {\n status: \"info\",\n message: `Watch mode requires interactive terminal. Run: npx ${fw} --watch`,\n },\n };\n }\n);\n\nserver.registerTool(\n \"create_test_template\",\n {\n title: \"Criar template de teste\",\n description: \"Gera template básico de teste (boilerplate) para o framework escolhido.\",\n inputSchema: z.object({\n framework: z.enum([\"cypress\", \"playwright\", \"jest\"]).describe(\"Framework.\"),\n type: z.enum([\"api\", \"ui\", \"unit\"]).optional().describe(\"Tipo de teste. Default: api.\"),\n }),\n outputSchema: z.object({\n ok: z.boolean(),\n template: z.string(),\n suggestedFileName: z.string(),\n }),\n },\n async ({ framework, type = \"api\" }) => {\n let template = \"\";\n let fileName = \"\";\n\n if (framework === \"cypress\") {\n fileName = `${type}-test.cy.js`;\n template = `describe('${type.toUpperCase()} Test', () => {\n it('should pass', () => {\n ${type === \"api\" ? \"cy.request('GET', 'http://localhost:3000/api/health').then((res) => {\\n expect(res.status).to.eq(200);\\n });\" : \"cy.visit('/');\\n cy.get('h1').should('be.visible');\"}\n });\n});`;\n } else if (framework === \"playwright\") {\n fileName = `${type}-test.spec.js`;\n template = `const { test, expect } = require('@playwright/test');\n\ntest.describe('${type.toUpperCase()} Test', () => {\n test('should pass', async ({ ${type === \"api\" ? \"request\" : \"page\"} }) => {\n ${type === \"api\" ? \"const res = await request.get('http://localhost:3000/api/health');\\n expect(res.status()).toBe(200);\" : \"await page.goto('/');\\n await expect(page.locator('h1')).toBeVisible();\"}\n });\n});`;\n } else {\n fileName = `${type}-test.test.js`;\n template = `describe('${type.toUpperCase()} Test', () => {\n test('should pass', ${type === \"api\" ? \"async () => {\\n const res = await fetch('http://localhost:3000/api/health');\\n expect(res.status).toBe(200);\\n }\" : \"() => {\\n expect(true).toBe(true);\\n }\"});\n});`;\n }\n\n return {\n content: [{ type: \"text\", text: `Template criado. Use write_test para gravar.` }],\n structuredContent: { ok: true, template, suggestedFileName: fileName },\n };\n }\n);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n console.error(\"Erro no MCP server:\", err);\n process.exit(1);\n});\n"],"mappings":"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","names":["res","data"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-lab-agent",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "MCP server + AI agents for QA automation in any project (Cypress, Playwright, Jest)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",