zignet
Version:
MCP server for Zig — AI-powered code analysis, validation, and documentation with fine-tuned LLM
294 lines (291 loc) • 8.77 kB
JavaScript
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