Skip to main content
Glama
diff.tsโ€ข6.53 kB
/** * Diff Command - Generate unified diff patch for code changes */ import chalk from 'chalk'; import { readFileSync } from 'fs'; import { MCPClient, MCPResponse } from '../client.js'; import { basename, extname } from 'path'; import { displayEscalation, promptEscalationConfirm } from '../utils/escalation.js'; import { shouldUseClaudeCode, promptClaudeCodeInsteadOfEscalation, executeWithClaudeCode, createTaskSummary } from '../utils/claudeIntegration.js'; export async function diffCommand( filePath: string, options: { prompt?: string; endpoint?: string; apiKey?: string; username?: string; password?: string; apply?: boolean; useClaudeCode?: boolean; } ): Promise<void> { const client = new MCPClient(options.endpoint, options.apiKey, options.username, options.password); let fileContent: string; let fileName: string; let language: string; // Read file try { fileContent = readFileSync(filePath, 'utf-8'); fileName = basename(filePath); language = detectLanguage(filePath); console.log(chalk.dim(`๐Ÿ“– Read file: ${fileName} (${language})\n`)); } catch (error) { console.error(chalk.red(`โŒ Cannot read file: ${filePath}`)); console.error(chalk.dim(error instanceof Error ? error.message : String(error))); process.exit(1); } const prompt = options.prompt || 'Please suggest improvements and provide a unified diff patch.'; console.log(chalk.dim('โณ Requesting diff from MCP server...\n')); const context = client.getCurrentContext(); // Add file info to context if (context.context) { context.context.filename = filePath; context.context.language = language; } // Include file content in message const fullMessage = `${prompt}\n\nFile: ${filePath}\nLanguage: ${language}\n\n\`\`\`${language}\n${fileContent}\n\`\`\``; try { let response = await client.send({ mode: 'diff', message: fullMessage, budget: 0, // Free tier for diff generation ...context, }); // Handle escalation confirmation if required if (response.requiresEscalationConfirm && response.suggestedLayer) { const currentLayer = response.metadata?.layer || 'L0'; const shouldEscalate = await promptEscalationConfirm( currentLayer, response.suggestedLayer, response.escalationReason || 'Quality improvement needed' ); if (shouldEscalate) { console.log(chalk.cyan(`\n๐Ÿ”„ Escalating to ${response.suggestedLayer}...\n`)); const escalatedMessage = response.optimizedPrompt || fullMessage; response = await client.send({ mode: 'diff', message: escalatedMessage, budget: 0, // Free tier for diff generation ...context, }); } } printResponse(response); // If --apply flag is set and patch exists if (options.apply && response.patch) { console.log(chalk.yellow('\nโš ๏ธ Apply patch functionality not yet implemented')); console.log(chalk.dim('To apply manually: save patch to file.patch and run:')); console.log(chalk.dim(' git apply file.patch')); console.log(chalk.dim(' or')); console.log(chalk.dim(' patch -p1 < file.patch\n')); } } catch (error) { process.exit(1); } } /** * Detect programming language from file extension */ function detectLanguage(filePath: string): string { const ext = extname(filePath).toLowerCase(); const langMap: Record<string, string> = { '.js': 'javascript', '.ts': 'typescript', '.jsx': 'javascript', '.tsx': 'typescript', '.py': 'python', '.java': 'java', '.c': 'c', '.cpp': 'cpp', '.go': 'go', '.rs': 'rust', '.rb': 'ruby', '.php': 'php', }; return langMap[ext] || 'text'; } /** * Print diff response with patch */ function printResponse(response: any): void { const { message, patch, model, tokens, cost } = response; // Print explanation message console.log(chalk.cyan('โ•”' + 'โ•'.repeat(58) + 'โ•—')); console.log(chalk.cyan('โ•‘') + chalk.bold(' MCP DIFF RESPONSE ').padEnd(58) + chalk.cyan('โ•‘')); console.log(chalk.cyan('โ•š' + 'โ•'.repeat(58) + 'โ•\n')); console.log(chalk.white(message || 'Diff generated')); console.log(); // Print patch if available if (patch) { console.log(chalk.yellow('โ•”' + 'โ•'.repeat(58) + 'โ•—')); console.log(chalk.yellow('โ•‘') + chalk.bold(' UNIFIED DIFF PATCH ').padEnd(58) + chalk.yellow('โ•‘')); console.log(chalk.yellow('โ•š' + 'โ•'.repeat(58) + 'โ•\n')); // Syntax highlight diff printHighlightedDiff(patch); console.log(); console.log(chalk.dim('๐Ÿ’ก Tip: To apply this patch, save it to a file and run:')); console.log(chalk.dim(' git apply <patch-file>')); console.log(chalk.dim(' or')); console.log(chalk.dim(' patch < <patch-file>\n')); } else { console.log(chalk.yellow('โš ๏ธ No patch generated by AI\n')); } // Display escalation if present if (response.escalation?.required) { displayEscalation(response.escalation); } if (model) { const totalTokens = tokens?.total || 0; const costStr = cost ? `$${cost.toFixed(4)}` : ''; console.log(chalk.dim(`๐Ÿ“Š Model: ${model} | Tokens: ${totalTokens} ${costStr ? `| Cost: ${costStr}` : ''}\n`)); } } /** * Print diff with syntax highlighting */ function printHighlightedDiff(diff: string): void { const lines = diff.split('\n'); for (const line of lines) { if (line.startsWith('+++') || line.startsWith('---')) { console.log(chalk.bold.white(line)); } else if (line.startsWith('+')) { console.log(chalk.green(line)); } else if (line.startsWith('-')) { console.log(chalk.red(line)); } else if (line.startsWith('@@')) { console.log(chalk.cyan(line)); } else if (line.startsWith('diff --git')) { console.log(chalk.yellow(line)); } else { console.log(chalk.dim(line)); } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/babasida246/ai-mcp-gateway'

If you have feedback or need assistance with the MCP directory API, please join our Discord server