UNPKG

zignet

Version:

MCP server for Zig — AI-powered code analysis, validation, and documentation with fine-tuned LLM

294 lines (291 loc) 8.77 kB
import { n as DEFAULT_ZIG_VERSION } from "./config-BtEBjBiA.js"; import { execSync } from "child_process"; import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, unlinkSync, writeFileSync } from "fs"; import { join } from "path"; import { homedir, tmpdir } from "os"; //#region src/zig/manager.ts /** * Detect system-installed Zig version * @returns Zig version string (e.g., "0.15.0") or null if not found */ function detectSystemZig() { try { const version = execSync("zig version", { encoding: "utf-8", stdio: [ "pipe", "pipe", "ignore" ] }).trim(); console.log(`🔍 Found system Zig: ${version}`); return version; } catch { return null; } } /** * Get path to system Zig binary (if available) * @returns Absolute path to system zig binary or null */ function getSystemZigPath() { try { return execSync(process.platform === "win32" ? "where zig" : "which zig", { encoding: "utf-8", stdio: [ "pipe", "pipe", "ignore" ] }).trim(); } catch { return null; } } /** * Detect current platform */ function detectPlatform() { const platform = process.platform; const arch = process.arch; let detectedPlatform; let detectedArch; if (platform === "linux") detectedPlatform = "linux"; else if (platform === "darwin") detectedPlatform = "macos"; else if (platform === "win32") detectedPlatform = "windows"; else throw new Error(`Unsupported platform: ${platform}`); if (arch === "x64") detectedArch = "x86_64"; else if (arch === "arm64") detectedArch = "aarch64"; else throw new Error(`Unsupported architecture: ${arch}`); return { platform: detectedPlatform, arch: detectedArch, ext: detectedPlatform === "windows" ? ".zip" : ".tar.xz" }; } /** * Get Zig download URL for a specific version */ function getZigDownloadUrl(version) { const { platform, arch, ext } = detectPlatform(); const zigPlatform = { linux: "linux", macos: "macos", windows: "windows" }[platform]; return `https://ziglang.org/download/${version}/${parseFloat(version) >= .15 ? `zig-${arch}-${zigPlatform}-${version}${ext}` : `zig-${zigPlatform}-${arch}-${version}${ext}`}`; } /** * Get cache directory for Zig installations */ function getZigCacheDir() { const cacheDir = join(homedir(), ".zignet", "zig-versions"); if (!existsSync(cacheDir)) mkdirSync(cacheDir, { recursive: true }); return cacheDir; } /** * Get installation path for a specific Zig version */ function getZigInstallPath(version) { return join(getZigCacheDir(), version); } /** * Get Zig binary path for a specific version */ function getZigBinaryPath(version) { const installPath = getZigInstallPath(version); const { platform, arch } = detectPlatform(); const binaryName = platform === "windows" ? "zig.exe" : "zig"; const zigPlatform = { linux: "linux", macos: "macos", windows: "windows" }[platform]; return join(installPath, parseFloat(version) >= .15 ? `zig-${arch}-${zigPlatform}-${version}` : `zig-${zigPlatform}-${arch}-${version}`, binaryName); } /** * Check if a specific Zig version is installed */ function isZigInstalled(version) { return existsSync(getZigBinaryPath(version)); } /** * Download and install a specific Zig version */ function installZig(version) { if (isZigInstalled(version)) { console.log(`✅ Zig ${version} already installed`); return; } console.log(`📥 Downloading Zig ${version}...`); const url = getZigDownloadUrl(version); const installPath = getZigInstallPath(version); if (!existsSync(installPath)) mkdirSync(installPath, { recursive: true }); try { const { platform } = detectPlatform(); if (platform === "windows") { const tempFile = join(installPath, `zig-${version}.zip`); console.log(`📥 Downloading ${url}...`); execSync(`powershell -Command "(New-Object System.Net.WebClient).DownloadFile('${url}', '${tempFile}')"`, { stdio: "inherit" }); console.log(`📦 Extracting Zig ${version}...`); try { execSync(`tar -xf "${tempFile}" -C "${installPath}"`, { stdio: "inherit" }); } catch { console.warn("⚠️ tar.exe not found, falling back to Expand-Archive (slower)..."); execSync(`powershell -Command "Expand-Archive -Path '${tempFile}' -DestinationPath '${installPath}' -Force"`, { stdio: "inherit" }); } execSync(`del "${tempFile}"`, { stdio: "inherit" }); } else { const tempFile = join(installPath, `zig-${version}.tar.xz`); execSync(`curl -fSL "${url}" -o "${tempFile}"`, { stdio: "inherit" }); console.log(`📦 Extracting Zig ${version}...`); execSync(`tar -xJf "${tempFile}" -C "${installPath}"`, { stdio: "inherit" }); execSync(`rm "${tempFile}"`); } const binaryPath = getZigBinaryPath(version); if (!existsSync(binaryPath)) throw new Error(`Installation failed: binary not found at ${binaryPath}`); chmodSync(binaryPath, 493); console.log(`✅ Zig ${version} installed successfully at ${binaryPath}`); } catch (error) { const message = error instanceof Error ? error.message : String(error); throw new Error(`Failed to install Zig ${version}: ${message}`); } } /** * Ensure a specific Zig version is installed (install if needed) * First checks system PATH, then falls back to downloading * @param version Zig version to ensure * @returns Absolute path to Zig binary */ function ensureZig(version) { if (isZigInstalled(version)) return getZigBinaryPath(version); if (detectSystemZig() === version) { const systemPath = getSystemZigPath(); if (systemPath) { console.log(`✅ Using system Zig ${version} at ${systemPath}`); return systemPath; } } console.log(`📥 Zig ${version} not found in system, downloading...`); installZig(version); return getZigBinaryPath(version); } //#endregion //#region src/zig/executor.ts /** * Parse Zig compiler output to extract diagnostics * * Zig error format: * /tmp/file.zig:2:5: error: expected type 'i32', found '[]const u8' * return "hello"; * ^~~~~~~~~~~~~~ */ function parseZigOutput(output) { const diagnostics = []; const lines = output.split("\n"); for (let i = 0; i < lines.length; i++) { const line = lines[i]; const match = line.match(/^(.+?):(\d+):(\d+):\s+(error|warning|note):\s+(.+)$/); if (match) { const [, file, lineNum, colNum, severity, message] = match; diagnostics.push({ message: message.trim(), file, line: parseInt(lineNum, 10), column: parseInt(colNum, 10), severity }); } else if (line.trim().startsWith("error:")) diagnostics.push({ message: line.replace(/^error:\s+/, "").trim(), severity: "error" }); } return diagnostics; } /** * Execute Zig AST check on code * * @param code - Zig source code to check * @param version - Zig version to use (default: from ZIG_DEFAULT env var) * @returns Result with success status and diagnostics */ function zigAstCheck(code, version = DEFAULT_ZIG_VERSION) { const zigBinary = ensureZig(version); const tempFile = join(mkdtempSync(join(tmpdir(), "zignet-")), "check.zig"); try { writeFileSync(tempFile, code, "utf8"); try { return { success: true, output: execSync(`"${zigBinary}" ast-check "${tempFile}"`, { encoding: "utf8", stdio: "pipe" }).trim(), diagnostics: [] }; } catch (error) { const errorObj = error; const stderr = (errorObj.stderr ?? errorObj.stdout ?? Buffer.from("")).toString(); const diagnostics = parseZigOutput(stderr); return { success: false, output: stderr.trim(), diagnostics }; } } finally { try { unlinkSync(tempFile); } catch {} } } /** * Execute Zig format on code * * @param code - Zig source code to format * @param version - Zig version to use (default: from ZIG_DEFAULT env var) * @returns Formatted code or error */ function zigFormat(code, version = DEFAULT_ZIG_VERSION) { const zigBinary = ensureZig(version); const tempFile = join(mkdtempSync(join(tmpdir(), "zignet-")), "format.zig"); try { writeFileSync(tempFile, code, "utf8"); try { execSync(`"${zigBinary}" fmt --check "${tempFile}"`, { encoding: "utf8", stdio: "pipe" }); return { success: true, output: code, diagnostics: [] }; } catch { try { execSync(`"${zigBinary}" fmt "${tempFile}"`, { stdio: "pipe" }); return { success: true, output: readFileSync(tempFile, "utf8"), diagnostics: [] }; } catch (fmtError) { const errorObj = fmtError; const stderr = (errorObj.stderr ?? errorObj.stdout ?? Buffer.from("")).toString(); const diagnostics = parseZigOutput(stderr); return { success: false, output: stderr.trim(), diagnostics }; } } } finally { try { unlinkSync(tempFile); } catch {} } } //#endregion export { zigFormat as n, zigAstCheck as t }; //# sourceMappingURL=executor-CUKaN4qu.js.map