(args: any)
| 383 | } |
| 384 | |
| 385 | async function toolGetCoverage(args: any): Promise<string> { |
| 386 | const result = await getScanResult(args.directory); |
| 387 | const cov = result.testCoverage; |
| 388 | if (!cov || cov.testFiles.length === 0) { |
| 389 | return "No test files detected. Add test files matching *.test.ts, *.spec.ts, test_*.py, *_test.go, etc."; |
| 390 | } |
| 391 | |
| 392 | const httpRoutes = result.routes.filter( |
| 393 | (r) => !["QUERY", "MUTATION", "SUBSCRIPTION", "RPC", "WS", "WS-ROOM"].includes(r.method) |
| 394 | ); |
| 395 | const uncoveredRoutes = httpRoutes.filter( |
| 396 | (r) => !cov.testedRoutes.includes(`${r.method}:${r.path}`) |
| 397 | ); |
| 398 | const uncoveredModels = result.schemas |
| 399 | .filter((m) => !m.name.startsWith("enum:") && !cov.testedModels.includes(m.name)); |
| 400 | |
| 401 | const lines = [ |
| 402 | `Test Coverage: ${cov.coveragePercent}%`, |
| 403 | `Test files: ${cov.testFiles.length}`, |
| 404 | `Covered routes: ${cov.testedRoutes.length}/${httpRoutes.length}`, |
| 405 | `Covered models: ${cov.testedModels.length}/${result.schemas.filter((m) => !m.name.startsWith("enum:")).length}`, |
| 406 | "", |
| 407 | ]; |
| 408 | |
| 409 | if (uncoveredRoutes.length > 0) { |
| 410 | lines.push(`Uncovered routes (${uncoveredRoutes.length}):`); |
| 411 | for (const r of uncoveredRoutes.slice(0, 20)) { |
| 412 | lines.push(` ${r.method} ${r.path} — ${r.file}`); |
| 413 | } |
| 414 | if (uncoveredRoutes.length > 20) lines.push(` ... +${uncoveredRoutes.length - 20} more`); |
| 415 | lines.push(""); |
| 416 | } |
| 417 | |
| 418 | if (uncoveredModels.length > 0) { |
| 419 | lines.push(`Uncovered models: ${uncoveredModels.map((m) => m.name).join(", ")}`); |
| 420 | } |
| 421 | |
| 422 | return lines.join("\n"); |
| 423 | } |
| 424 | |
| 425 | async function toolGetKnowledge(args: any): Promise<string> { |
| 426 | const dir = args.directory ? resolve(args.directory) : process.cwd(); |
nothing calls this directly
no test coverage detected