UNPKG

claude-flow

Version:

Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration

346 lines 12.3 kB
/** * Analyze MCP Tools * Provides diff analysis and classification via MCP protocol */ import { validateGitRef, validatePath } from './validate-input.js'; import { analyzeDiff, assessFileRisk, assessOverallRisk, classifyDiff, suggestReviewers, getGitDiffNumstat, } from '../ruvector/diff-classifier.js'; /** * Diff Analysis Tool * Analyzes git diffs for change risk assessment and classification */ export const analyzeDiffTool = { name: 'analyze_diff', description: 'Analyze git diff for change risk assessment and classification Use when native `git diff` / `grep` / static analysis is wrong because you want LLM-graded change classification, reviewer recommendations, or risk scoring. For literal-text inspection, native tools are fine.', category: 'analyze', tags: ['diff', 'risk', 'classification', 'git'], inputSchema: { type: 'object', properties: { ref: { type: 'string', description: 'Git ref to compare against (e.g., HEAD~1, main..feature, commit hash)', default: 'HEAD', }, includeFileRisks: { type: 'boolean', description: 'Include detailed file-level risk analysis', default: false, }, includeReviewers: { type: 'boolean', description: 'Include recommended reviewers', default: true, }, useRuVector: { type: 'boolean', description: 'Attempt to use ruvector for analysis (graceful fallback if unavailable)', default: true, }, }, }, handler: async (params) => { if (params.ref) { const vRef = validateGitRef(params.ref, 'ref'); if (!vRef.valid) return { error: true, message: vRef.error, ref: params.ref }; } const ref = params.ref || 'HEAD'; const includeFileRisks = params.includeFileRisks !== false; const includeReviewers = params.includeReviewers !== false; const useRuVector = params.useRuVector !== false; try { const result = await analyzeDiff({ ref, useRuVector, }); // Build response const response = { ref: result.ref, timestamp: result.timestamp, files: result.files, risk: result.risk, classification: result.classification, summary: result.summary, }; if (includeFileRisks) { response.fileRisks = result.fileRisks; } if (includeReviewers) { response.recommendedReviewers = result.recommendedReviewers; } return response; } catch (error) { return { error: true, message: error instanceof Error ? error.message : String(error), ref, }; } }, }; /** * Diff Risk Assessment Tool * Focused risk assessment without full analysis */ export const diffRiskTool = { name: 'analyze_diff-risk', description: 'Quick risk assessment for git diff Use when native `git diff` / `grep` / static analysis is wrong because you want LLM-graded change classification, reviewer recommendations, or risk scoring. For literal-text inspection, native tools are fine.', category: 'analyze', tags: ['diff', 'risk', 'git'], inputSchema: { type: 'object', properties: { ref: { type: 'string', description: 'Git ref to compare against', default: 'HEAD', }, }, }, handler: async (params) => { if (params.ref) { const vRef = validateGitRef(params.ref, 'ref'); if (!vRef.valid) return { error: true, message: vRef.error, ref: params.ref }; } const ref = params.ref || 'HEAD'; try { const files = getGitDiffNumstat(ref); const fileRisks = files.map(assessFileRisk); const risk = assessOverallRisk(files, fileRisks); return { ref, risk, summary: `${risk.overall} risk (score: ${risk.score}/100) - ${files.length} files changed`, }; } catch (error) { return { error: true, message: error instanceof Error ? error.message : String(error), ref, }; } }, }; /** * Diff Classification Tool * Classify change type without full analysis */ export const diffClassifyTool = { name: 'analyze_diff-classify', description: 'Classify git diff change type Use when native `git diff` / `grep` / static analysis is wrong because you want LLM-graded change classification, reviewer recommendations, or risk scoring. For literal-text inspection, native tools are fine.', category: 'analyze', tags: ['diff', 'classification', 'git'], inputSchema: { type: 'object', properties: { ref: { type: 'string', description: 'Git ref to compare against', default: 'HEAD', }, }, }, handler: async (params) => { if (params.ref) { const vRef = validateGitRef(params.ref, 'ref'); if (!vRef.valid) return { error: true, message: vRef.error, ref: params.ref }; } const ref = params.ref || 'HEAD'; try { const files = getGitDiffNumstat(ref); const classification = classifyDiff(files); return { ref, classification, files: files.length, }; } catch (error) { return { error: true, message: error instanceof Error ? error.message : String(error), ref, }; } }, }; /** * Diff Reviewers Tool * Suggest reviewers for changes */ export const diffReviewersTool = { name: 'analyze_diff-reviewers', description: 'Suggest reviewers for git diff changes Use when native `git diff` / `grep` / static analysis is wrong because you want LLM-graded change classification, reviewer recommendations, or risk scoring. For literal-text inspection, native tools are fine.', category: 'analyze', tags: ['diff', 'reviewers', 'git'], inputSchema: { type: 'object', properties: { ref: { type: 'string', description: 'Git ref to compare against', default: 'HEAD', }, limit: { type: 'number', description: 'Maximum number of reviewers to suggest', default: 5, }, }, }, handler: async (params) => { if (params.ref) { const vRef = validateGitRef(params.ref, 'ref'); if (!vRef.valid) return { error: true, message: vRef.error, ref: params.ref }; } const ref = params.ref || 'HEAD'; const limit = params.limit || 5; try { const files = getGitDiffNumstat(ref); const fileRisks = files.map(assessFileRisk); const reviewers = suggestReviewers(files, fileRisks); return { ref, recommendedReviewers: reviewers.slice(0, limit), filesAnalyzed: files.length, }; } catch (error) { return { error: true, message: error instanceof Error ? error.message : String(error), ref, }; } }, }; /** * File Risk Tool * Assess risk for a specific file path */ export const fileRiskTool = { name: 'analyze_file-risk', description: 'Assess risk for a specific file change Use when native `git diff` / `grep` / static analysis is wrong because you want LLM-graded change classification, reviewer recommendations, or risk scoring. For literal-text inspection, native tools are fine.', category: 'analyze', tags: ['file', 'risk'], inputSchema: { type: 'object', properties: { path: { type: 'string', description: 'File path to assess', }, additions: { type: 'number', description: 'Number of lines added', default: 0, }, deletions: { type: 'number', description: 'Number of lines deleted', default: 0, }, status: { type: 'string', description: 'File status: added, modified, deleted, renamed', default: 'modified', }, }, required: ['path'], }, handler: async (params) => { const vPath = validatePath(params.path, 'path'); if (!vPath.valid) return { file: params.path, risk: 'unknown', score: 0, reasons: [vPath.error] }; const file = { path: params.path, status: params.status || 'modified', additions: params.additions || 0, deletions: params.deletions || 0, hunks: 1, binary: false, }; const risk = assessFileRisk(file); return { file: file.path, risk: risk.risk, score: risk.score, reasons: risk.reasons, }; }, }; /** * Diff Stats Tool * Get quick diff statistics */ export const diffStatsTool = { name: 'analyze_diff-stats', description: 'Get quick statistics for git diff Use when native `git diff` / `grep` / static analysis is wrong because you want LLM-graded change classification, reviewer recommendations, or risk scoring. For literal-text inspection, native tools are fine.', category: 'analyze', tags: ['diff', 'stats', 'git'], inputSchema: { type: 'object', properties: { ref: { type: 'string', description: 'Git ref to compare against', default: 'HEAD', }, }, }, handler: async (params) => { if (params.ref) { const vRef = validateGitRef(params.ref, 'ref'); if (!vRef.valid) return { error: true, message: vRef.error, ref: params.ref }; } const ref = params.ref || 'HEAD'; try { const files = getGitDiffNumstat(ref); const totalAdditions = files.reduce((sum, f) => sum + f.additions, 0); const totalDeletions = files.reduce((sum, f) => sum + f.deletions, 0); const addedFiles = files.filter(f => f.status === 'added').length; const modifiedFiles = files.filter(f => f.status === 'modified').length; const deletedFiles = files.filter(f => f.status === 'deleted').length; const renamedFiles = files.filter(f => f.status === 'renamed').length; const binaryFiles = files.filter(f => f.binary).length; return { ref, totalFiles: files.length, totalAdditions, totalDeletions, totalChanges: totalAdditions + totalDeletions, byStatus: { added: addedFiles, modified: modifiedFiles, deleted: deletedFiles, renamed: renamedFiles, }, binaryFiles, }; } catch (error) { return { error: true, message: error instanceof Error ? error.message : String(error), ref, }; } }, }; // Export all analyze tools export const analyzeTools = [ analyzeDiffTool, diffRiskTool, diffClassifyTool, diffReviewersTool, fileRiskTool, diffStatsTool, ]; export default analyzeTools; //# sourceMappingURL=analyze-tools.js.map