vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
186 lines (185 loc) • 9.9 kB
JavaScript
import path from 'path';
import { generateHeuristicComment } from './astAnalyzer.js';
export function formatCodeMapToMarkdown(codeMap, projectRoot) {
let markdownOutput = `# Code Map for ${path.basename(projectRoot)}\n\n`;
markdownOutput += `Processed ${codeMap.files.length} files.\n`;
const errorFiles = codeMap.files.filter(f => f.comment?.startsWith("Error processing file"));
if (errorFiles.length > 0) {
markdownOutput += `${errorFiles.length} file(s) encountered errors during processing.\n`;
}
markdownOutput += `\n`;
for (const fileInfo of codeMap.files) {
markdownOutput += `## File: ${fileInfo.relativePath}\n`;
if (fileInfo.comment) {
markdownOutput += `*${fileInfo.comment.split('\n')[0]}*\n\n`;
}
else {
markdownOutput += `*${generateHeuristicComment(path.basename(fileInfo.relativePath), 'file')}*\n\n`;
}
if (fileInfo.imports.length > 0) {
markdownOutput += `### Imports\n`;
fileInfo.imports.forEach(imp => {
let displayPath = imp.path;
if (imp.path === 'unknown' && imp.nodeText) {
const es6ImportMatch = imp.nodeText.match(/from\s+['"]([^'"]+)['"]/);
if (es6ImportMatch && es6ImportMatch[1]) {
displayPath = es6ImportMatch[1];
}
else {
const requireMatch = imp.nodeText.match(/require\s*\(\s*['"]([^'"]+)['"]\s*\)/);
if (requireMatch && requireMatch[1]) {
displayPath = requireMatch[1];
}
else {
const dynamicImportMatch = imp.nodeText.match(/import\s*\(\s*['"]([^'"]+)['"]\s*\)/);
if (dynamicImportMatch && dynamicImportMatch[1]) {
displayPath = dynamicImportMatch[1];
}
else {
displayPath = imp.importedItems && imp.importedItems.length > 0 ?
`${imp.importedItems[0]} (imported)` : 'module import';
}
}
}
}
let impDetails = imp.importedItems && imp.path !== 'unknown' ?
`(${imp.importedItems.join(', ')})` : '';
if (imp.isDefault && imp.importedItems && imp.importedItems.length > 0 && imp.path !== 'unknown') {
impDetails = `${imp.importedItems[0]} (default)`;
if (imp.importedItems.length > 1) {
impDetails += `, { ${imp.importedItems.slice(1).join(', ')} }`;
}
}
else if (imp.isDefault && imp.path !== 'unknown') {
impDetails = `(default)`;
}
const isResolved = imp.path !== 'unknown' &&
(imp.path.startsWith('/') || imp.path.includes(':\\') || imp.path.match(/^[a-zA-Z]:\//));
const isExternalPackage = imp.isExternalPackage ||
(!imp.path.startsWith('.') && !imp.path.startsWith('/') && imp.path !== 'unknown');
const isProjectFile = imp.isProjectFile ||
(imp.path.startsWith('./') || imp.path.startsWith('../'));
if (isResolved) {
const originalPath = imp.originalPath || imp.path;
const resolvedPath = imp.path;
const fileName = path.basename(resolvedPath);
markdownOutput += `- \`${originalPath}\` → \`${fileName}\` ${impDetails}\n`;
markdownOutput += ` *Resolved to: ${resolvedPath}*\n`;
}
else if (isProjectFile) {
const originalPath = imp.originalPath || imp.path;
markdownOutput += `- \`${originalPath}\` ${impDetails}\n`;
if (imp.path !== originalPath) {
markdownOutput += ` *Project file: ${imp.path}*\n`;
}
}
else if (isExternalPackage) {
const packageName = imp.packageName || (imp.path.startsWith('@') ?
imp.path.split('/').slice(0, 2).join('/') :
imp.path.split('/')[0]);
markdownOutput += `- \`${displayPath}\` ${impDetails}\n`;
if (packageName && packageName !== imp.path) {
markdownOutput += ` *Package: ${packageName}*\n`;
}
}
else if (imp.path === 'unknown') {
markdownOutput += `- \`${displayPath}\` ${impDetails}\n`;
if (imp.nodeText) {
const cleanNodeText = imp.nodeText.replace(/\s+/g, ' ').trim();
const snippet = cleanNodeText.length > 50 ?
cleanNodeText.substring(0, 47) + '...' :
cleanNodeText;
markdownOutput += ` *Import snippet: \`${snippet}\`*\n`;
}
else {
markdownOutput += ` *Note: This is an unresolved import. It might be a built-in module, an external package, or a local file.*\n`;
}
}
else {
markdownOutput += `- \`${displayPath}\` ${impDetails}\n`;
}
});
markdownOutput += `\n`;
}
if (fileInfo.classes.length > 0) {
markdownOutput += `### Classes\n`;
for (const classInfo of fileInfo.classes) {
markdownOutput += `- **${classInfo.name}**`;
if (classInfo.parentClass)
markdownOutput += ` (extends ${classInfo.parentClass})`;
if (classInfo.comment)
markdownOutput += ` — *${classInfo.comment.split('\n')[0]}*\n`;
else
markdownOutput += `\n`;
if (classInfo.properties && classInfo.properties.length > 0) {
classInfo.properties.forEach(prop => {
markdownOutput += ` - \`${prop.name}${prop.type ? `: ${prop.type}` : ''}\``;
if (prop.comment)
markdownOutput += ` — *${prop.comment.split('\n')[0]}*\n`;
else
markdownOutput += `\n`;
});
}
for (const method of classInfo.methods) {
markdownOutput += ` - \`${method.signature}\``;
if (method.comment)
markdownOutput += ` — *${method.comment.split('\n')[0]}*\n`;
else
markdownOutput += `\n`;
}
}
markdownOutput += `\n`;
}
if (fileInfo.functions.length > 0) {
markdownOutput += `### Functions\n`;
for (const funcInfo of fileInfo.functions) {
markdownOutput += `- \`${funcInfo.signature}\``;
if (funcInfo.comment)
markdownOutput += ` — *${funcInfo.comment.split('\n')[0]}*\n`;
else
markdownOutput += `\n`;
}
markdownOutput += `\n`;
}
markdownOutput += `\n---\n\n`;
}
return markdownOutput;
}
export function optimizeMarkdownOutput(markdown, maxLength = 80000) {
if (markdown.length <= maxLength) {
return markdown;
}
const diagramsMarker = "\n## File Dependency Diagram";
const diagramsStart = markdown.indexOf(diagramsMarker);
const detailedStructureMarker = "\n## File: ";
let detailedStructureStart = markdown.indexOf(detailedStructureMarker);
if (detailedStructureStart === -1) {
detailedStructureStart = markdown.length / 2;
}
const truncationMessage = "\n\n... (Output truncated due to length constraints. Some file details might be omitted)";
const availableLengthForDetails = maxLength - (diagramsStart > -1 ? diagramsStart : detailedStructureStart) - truncationMessage.length;
if (diagramsStart > -1 && diagramsStart < maxLength * 0.75) {
const introAndDiagrams = markdown.substring(0, diagramsStart);
let detailsToKeep = "";
if (detailedStructureStart > diagramsStart && availableLengthForDetails > 0) {
const detailsSection = markdown.substring(diagramsStart);
const lastNewline = detailsSection.substring(0, availableLengthForDetails).lastIndexOf('\n## File: ');
detailsToKeep = lastNewline > 0 ? detailsSection.substring(0, lastNewline) : detailsSection.substring(0, availableLengthForDetails);
}
else if (availableLengthForDetails > 0) {
const detailsSection = markdown.substring(detailedStructureStart);
const lastNewline = detailsSection.substring(0, availableLengthForDetails).lastIndexOf('\n## File: ');
detailsToKeep = lastNewline > 0 ? detailsSection.substring(0, lastNewline) : detailsSection.substring(0, availableLengthForDetails);
return markdown.substring(0, detailedStructureStart) + detailsToKeep + truncationMessage;
}
return introAndDiagrams + detailsToKeep + truncationMessage;
}
else {
let truncatedMarkdown = markdown.substring(0, maxLength - truncationMessage.length);
const lastNewline = truncatedMarkdown.lastIndexOf('\n');
if (lastNewline > 0) {
truncatedMarkdown = truncatedMarkdown.substring(0, lastNewline);
}
return truncatedMarkdown + truncationMessage;
}
}