import { z } from "zod";
import { exec } from "child_process";
import { promisify } from "util";
import * as fs from "fs/promises";
import * as path from "path";
import * as os from "os";
const execAsync = promisify(exec);
export const validateCodeSchema = {
name: "validate_code",
description:
"Validates code syntax and formatting using available linters (e.g., Prettier). usage: providing code snippets to check for correctness before finalizing.",
inputSchema: z.object({
code: z.string().describe("The code content to validate."),
language: z
.string()
.describe(
"The programming language (e.g., 'typescript', 'python', 'json').",
),
}),
};
export async function validateCodeHandler(args: any) {
const { code, language } = args;
// Create a temporary file to run validation against
const tmpDir = os.tmpdir();
const fileName = `validate_${Date.now()}.${getExt(language)}`;
const filePath = path.join(tmpDir, fileName);
try {
await fs.writeFile(filePath, code);
// Default to Prettier for supported languages
if (
[
"javascript",
"typescript",
"json",
"css",
"html",
"markdown",
"yaml",
].includes(language)
) {
try {
// Check syntax and formatting
await execAsync(`npx prettier --check "${filePath}"`);
// If checking passed, it's valid code (mostly)
return {
content: [
{ type: "text", text: "✅ Code is valid and formatted correctly." },
],
};
} catch (error: any) {
// Prettier error output usually contains the syntax error details
return {
content: [
{
type: "text",
text: `❌ Validation Failed:\n${error.stdout || error.stderr || error.message}`,
},
],
};
}
}
// Fallback for other languages (mock validation for now, or add specific compilers like `python -m py_compile`)
if (language === "python") {
try {
await execAsync(`python -m py_compile "${filePath}"`);
return {
content: [{ type: "text", text: "✅ Python syntax is valid." }],
};
} catch (error: any) {
return {
content: [
{ type: "text", text: `❌ Python Syntax Error:\n${error.stderr}` },
],
};
}
}
return {
content: [
{
type: "text",
text: `⚠️ No specific validator configured for ${language}, but code was received.`,
},
],
};
} catch (err: any) {
return {
content: [
{
type: "text",
text: `System Error during validation: ${err.message}`,
},
],
};
} finally {
// Cleanup
try {
await fs.unlink(filePath);
} catch {}
}
}
function getExt(lang: string): string {
const map: Record<string, string> = {
typescript: "ts",
javascript: "js",
python: "py",
rust: "rs",
go: "go",
html: "html",
css: "css",
json: "json",
};
return map[lang] || "txt";
}