UNPKG

zignet

Version:

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

430 lines (414 loc) â€ĸ 14.2 kB
const require_chunk = require('./chunk-DWy1uDak.cjs'); const require_config = require('./config-C2ufArDU.cjs'); require('./executor-ON2Rt60w.cjs'); const require_analyze = require('./analyze-CKCU4PaJ.cjs'); const require_compile = require('./compile-F5XWbjXn.cjs'); const require_model_downloader = require('./model-downloader-ioH3AphD.cjs'); let __modelcontextprotocol_sdk_server_index_js = require("@modelcontextprotocol/sdk/server/index.js"); __modelcontextprotocol_sdk_server_index_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_index_js); let __modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js"); __modelcontextprotocol_sdk_server_stdio_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_stdio_js); let __modelcontextprotocol_sdk_types_js = require("@modelcontextprotocol/sdk/types.js"); __modelcontextprotocol_sdk_types_js = require_chunk.__toESM(__modelcontextprotocol_sdk_types_js); let node_llama_cpp = require("node-llama-cpp"); node_llama_cpp = require_chunk.__toESM(node_llama_cpp); //#region src/llm/session.ts var ZigNetLLM = class { model = null; context = null; session = null; config; constructor(config = {}) { this.config = { modelPath: config.modelPath || "", gpuDevice: config.gpuDevice, gpuLayers: config.gpuLayers ?? 35, contextSize: config.contextSize ?? 4096, temperature: config.temperature ?? .7, topP: config.topP ?? .9 }; } /** * Initialize the LLM model and session */ async initialize() { if (this.session) { console.log("â„šī¸ LLM already initialized"); return; } console.log("🚀 Initializing ZigNet LLM..."); if (this.config.gpuDevice !== void 0) { process.env.CUDA_VISIBLE_DEVICES = this.config.gpuDevice; console.log(`đŸŽ¯ GPU device selection: ${this.config.gpuDevice}`); } const modelPath = this.config.modelPath || await require_model_downloader.modelDownloader.ensureModel((progress) => { if (progress.percent % 10 < 1) console.log(`đŸ“Ĩ Downloading model: ${progress.percent.toFixed(1)}%`); }); console.log(`đŸ“Ļ Loading model: ${modelPath}`); console.log(`🎮 GPU layers: ${this.config.gpuLayers}`); this.model = await (await (0, node_llama_cpp.getLlama)()).loadModel({ modelPath, gpuLayers: this.config.gpuLayers }); this.context = await this.model.createContext({ contextSize: this.config.contextSize }); this.session = new node_llama_cpp.LlamaChatSession({ contextSequence: this.context.getSequence(), systemPrompt: `You are ZigNet, an AI assistant specialized in Zig programming language (v0.13-0.15). Your expertise includes: - Explaining Zig syntax, features, and idioms - Understanding comptime, generics, and error handling - Providing code examples and fixes - Referencing official Zig documentation Always: - Generate idiomatic Zig code - Explain Zig-specific concepts clearly - Suggest best practices - Validate syntax mentally before responding When unsure, reference official Zig docs or suggest using 'zig ast-check'.` }); console.log("✅ LLM initialized successfully!"); } /** * Query the LLM with a prompt */ async query(prompt) { if (!this.session) await this.initialize(); if (!this.session) throw new Error("Failed to initialize LLM session"); console.log(`🤔 Querying LLM: ${prompt.substring(0, 50)}...`); return await this.session.prompt(prompt, { temperature: this.config.temperature, topP: this.config.topP }); } /** * Dispose resources */ dispose() { if (this.context) { this.context.dispose(); this.context = null; } if (this.model) { this.model.dispose(); this.model = null; } this.session = null; console.log("đŸ—‘ī¸ LLM resources disposed"); } }; /** * Singleton instance */ let globalLLM = null; /** * Get or create the global LLM instance */ async function getLLM(config) { if (!globalLLM) { if (!config) { const { MODEL_PATH, GPU_DEVICE, GPU_LAYERS, CONTEXT_SIZE, TEMPERATURE, TOP_P } = await Promise.resolve().then(() => require("./config.cjs")); config = { modelPath: MODEL_PATH, gpuDevice: GPU_DEVICE, gpuLayers: GPU_LAYERS, contextSize: CONTEXT_SIZE, temperature: TEMPERATURE, topP: TOP_P }; } globalLLM = new ZigNetLLM(config); await globalLLM.initialize(); } return globalLLM; } //#endregion //#region src/tools/docs.ts /** * Get Zig documentation for a specific topic */ async function getZigDocs(args) { const { topic, detail_level = "intermediate" } = args; console.log(`📚 Getting Zig docs for: ${topic} (${detail_level})`); const prompt = `Explain the following Zig programming concept: "${topic}" ${{ basic: "Provide a brief, beginner-friendly explanation.", intermediate: "Provide a detailed explanation with practical examples.", advanced: "Provide an in-depth explanation covering edge cases, best practices, and advanced patterns." }[detail_level]} Format your response as: 1. A clear definition/explanation 2. One or more code examples 3. Key points to remember Be specific to Zig versions 0.13-0.15.`; try { const response = await (await getLLM()).query(prompt); const examples = extractCodeBlocks(response); return { topic, documentation: response, examples: examples.length > 0 ? examples : void 0 }; } catch (error) { throw new Error(`Failed to get Zig docs: ${error instanceof Error ? error.message : String(error)}`); } } /** * Extract code blocks from markdown text */ function extractCodeBlocks(text) { const codeBlockRegex = /```(?:zig)?\n([\s\S]*?)```/g; const blocks = []; let match; while ((match = codeBlockRegex.exec(text)) !== null) blocks.push(match[1].trim()); return blocks; } //#endregion //#region src/tools/suggest.ts /** * Suggest fixes for Zig compilation errors */ async function suggestFix(args) { const { error_message, code_context, error_type = "semantic" } = args; console.log(`💡 Suggesting fix for: ${error_message.substring(0, 50)}...`); const prompt = `You are analyzing a Zig compilation error. Help fix it. Error Message: \`\`\` ${error_message} \`\`\` ${code_context ? `Code Context:\n\`\`\`zig\n${code_context}\n\`\`\`\n` : ""} Error Type: ${error_type} Provide: 1. A brief summary of what's wrong 2. 1-3 concrete fix suggestions with code examples 3. Explanation of why each fix works Format your response clearly with code blocks for fixes.`; try { const response = await (await getLLM()).query(prompt); const fixes = parseFixes(response); return { error_summary: extractErrorSummary(response), suggested_fixes: fixes, explanation: response }; } catch (error) { throw new Error(`Failed to suggest fix: ${error instanceof Error ? error.message : String(error)}`); } } /** * Extract error summary from LLM response */ function extractErrorSummary(response) { return response.split("\n").filter((line) => line.trim())[0] || "Error analysis"; } /** * Parse fix suggestions from LLM response */ function parseFixes(response) { const fixes = []; const codeBlockRegex = /```(?:zig)?\n([\s\S]*?)```/g; const codeBlocks = []; let match; while ((match = codeBlockRegex.exec(response)) !== null) codeBlocks.push(match[1].trim()); const fixPattern = /(?:Fix|Option|Solution)\s*\d*[:.]\s*([^\n]+)/gi; const descriptions = []; while ((match = fixPattern.exec(response)) !== null) descriptions.push(match[1].trim()); for (let i = 0; i < Math.max(descriptions.length, codeBlocks.length); i++) fixes.push({ description: descriptions[i] || `Fix option ${i + 1}`, code_after: codeBlocks[i] || "// See explanation above", rationale: `Addresses the ${extractErrorSummary(response)}` }); if (fixes.length === 0) fixes.push({ description: "Suggested fix", code_after: codeBlocks[0] || "// See detailed explanation", rationale: "Based on error analysis" }); return fixes; } //#endregion //#region src/mcp-server.ts /** * Create and configure the MCP server */ function createServer() { const server = new __modelcontextprotocol_sdk_server_index_js.Server({ name: "zignet", version: "0.15.2-h" }, { capabilities: { tools: {} } }); /** * Handler for listing available tools */ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListToolsRequestSchema, async () => { return { tools: [ { name: "analyze_zig", description: "Analyze Zig code for syntax errors, type mismatches, and semantic issues using the official Zig compiler", inputSchema: { type: "object", properties: { code: { type: "string", description: "Zig source code to analyze" }, zig_version: { type: "string", enum: require_config.SUPPORTED_ZIG_VERSIONS, description: `Zig version to use for validation (default: ${require_config.DEFAULT_ZIG_VERSION})` } }, required: ["code"] } }, { name: "compile_zig", description: "Format Zig code using the official Zig formatter", inputSchema: { type: "object", properties: { code: { type: "string", description: "Zig source code to format" }, zig_version: { type: "string", enum: require_config.SUPPORTED_ZIG_VERSIONS, description: `Zig version to use for formatting (default: ${require_config.DEFAULT_ZIG_VERSION})` } }, required: ["code"] } }, { name: "get_zig_docs", description: "Retrieve Zig documentation for specific topics", inputSchema: { type: "object", properties: { topic: { type: "string", description: "Topic to get documentation for (e.g., 'comptime', 'generics')" } }, required: ["topic"] } }, { name: "suggest_fix", description: "Get intelligent suggestions for fixing Zig code errors", inputSchema: { type: "object", properties: { error: { type: "string", description: "Error message to get fix suggestions for" }, code: { type: "string", description: "Code context where the error occurred" } }, required: ["error", "code"] } } ] }; }); /** * Handler for tool execution */ server.setRequestHandler(__modelcontextprotocol_sdk_types_js.CallToolRequestSchema, async (request) => { const { name, arguments: args = {} } = request.params; switch (name) { case "analyze_zig": { const code = args.code; const zig_version = args.zig_version; if (!code) throw new Error("Missing required argument: code"); return { content: [{ type: "text", text: require_analyze.formatAnalyzeResult(await require_analyze.analyzeZig({ code, zig_version })) }] }; } case "compile_zig": { const compileArgs = args; if (!compileArgs.code) throw new Error("Missing required argument: code"); return { content: [{ type: "text", text: require_compile.formatCompileResult(await require_compile.compileZig({ code: compileArgs.code, zig_version: compileArgs.zig_version })) }] }; } case "get_zig_docs": { const docsArgs = args; if (!docsArgs.topic) throw new Error("Missing required argument: topic"); const result = await getZigDocs({ topic: docsArgs.topic, detail_level: docsArgs.detail_level }); return { content: [{ type: "text", text: `# Zig Documentation: ${result.topic}\n\n${result.documentation}` }] }; } case "suggest_fix": { const fixArgs = args; if (!fixArgs.error_message) throw new Error("Missing required argument: error_message"); const result = await suggestFix({ error_message: fixArgs.error_message, code_context: fixArgs.code_context, error_type: fixArgs.error_type }); const fixesText = result.suggested_fixes.map((fix, i) => `## Fix ${i + 1}: ${fix.description}\n\n\`\`\`zig\n${fix.code_after}\n\`\`\`\n\n**Rationale**: ${fix.rationale}`).join("\n\n"); return { content: [{ type: "text", text: `# Error Fix Suggestions\n\n**Error**: ${result.error_summary}\n\n${fixesText}\n\n## Full Analysis\n\n${result.explanation}` }] }; } default: throw new Error(`Unknown tool: ${name}`); } }); return server; } /** * Main entry point */ async function main() { console.error("🚀 ZigNet MCP Server starting..."); console.error(`📋 Configuration:`); console.error(` - Zig versions: ${require_config.SUPPORTED_ZIG_VERSIONS.join(", ")}`); console.error(` - Default version: ${require_config.DEFAULT_ZIG_VERSION}`); const { modelDownloader: modelDownloader$1 } = await Promise.resolve().then(() => require("./model-downloader-CID2GL8m.cjs")); const modelAvailable = modelDownloader$1.isModelAvailable(); console.error(`🤖 Model status:`); if (modelAvailable) console.error(` ✅ Model ready: ${modelDownloader$1.getModelPath()}`); else { console.error(` đŸ“Ĩ Model not found - downloading now...`); console.error(` 📍 Target: ${modelDownloader$1.getModelPath()}`); try { let lastLoggedPercent = -1; await modelDownloader$1.ensureModel((progress) => { const currentMilestone = Math.floor(progress.percent / 5) * 5; if (currentMilestone > lastLoggedPercent && currentMilestone % 5 === 0) { console.error(` đŸ“Ļ Download progress: ${currentMilestone}% (${(progress.downloaded / 1024 / 1024).toFixed(0)}MB / ${(progress.total / 1024 / 1024).toFixed(0)}MB)`); lastLoggedPercent = currentMilestone; } }); console.error(` ✅ Model downloaded successfully!`); } catch (error) { console.error(` âš ī¸ Model download failed: ${error}`); console.error(` â„šī¸ LLM tools (get_zig_docs, suggest_fix) will not be available`); console.error(` â„šī¸ Deterministic tools (analyze_zig, compile_zig) will still work`); } } const server = createServer(); const transport = new __modelcontextprotocol_sdk_server_stdio_js.StdioServerTransport(); await server.connect(transport); console.error("✅ ZigNet MCP Server running on stdio"); console.error("📡 Available tools: analyze_zig, compile_zig, get_zig_docs, suggest_fix"); } main().catch((error) => { console.error("Fatal error:", error); process.exit(1); }); //#endregion //# sourceMappingURL=mcp-server.cjs.map