UNPKG

permamind

Version:

An MCP server that provides an immortal memory layer for AI agents and clients

614 lines (608 loc) 23.7 kB
const service = (permawebDocs) => { return { generateDevelopmentPlan: async (goal, processType) => { try { // Query for process type specific guidance const planQuery = `${processType} development plan ${goal}`; const results = await permawebDocs.query(planQuery, ["ao", "arweave"], 10); // Generate development steps const steps = generateDevelopmentSteps(goal, processType); // Estimate timeline const timeline = estimateTimeline(steps); // Identify prerequisites const prerequisites = identifyPrerequisites(processType); return { goal, prerequisites, processType, resources: results, steps, timeline, }; } catch (error) { throw new Error(`Failed to generate development plan: ${error instanceof Error ? error.message : "Unknown error"}`); } }, getBestPractices: async (category, processType) => { try { // Build category-specific query const practicesQuery = `${category} best practices ${processType || ""}`; const results = await permawebDocs.query(practicesQuery, ["ao", "arweave"], 10); // Generate practices const practices = generateBestPractices(category, processType); // Identify anti-patterns const antiPatterns = generateAntiPatterns(category, processType); return { antiPatterns, category, practices, resources: results, }; } catch (error) { throw new Error(`Failed to get best practices: ${error instanceof Error ? error.message : "Unknown error"}`); } }, getContextAwareGuidance: async (processDefinition, stage, query) => { try { // Build context-aware query const contextQuery = buildProcessContextQuery(processDefinition, stage, query); // Query relevant documentation const results = await permawebDocs.query(contextQuery, ["ao", "arweave"], 10); // Generate stage-specific guidance const guidance = generateStageGuidance(stage, processDefinition, results); // Create action items const actionItems = generateActionItems(stage, processDefinition); // Get relevant examples const examples = getStageExamples(stage, processDefinition); // Create troubleshooting guides const troubleshooting = generateTroubleshootingGuides(stage, processDefinition); return { actionItems, examples, guidance, resources: results, stage, troubleshooting, }; } catch (error) { throw new Error(`Failed to get context-aware guidance: ${error instanceof Error ? error.message : "Unknown error"}`); } }, getInteractiveLearning: async (topic, userLevel) => { try { // Query for learning resources const learningQuery = `${topic} tutorial ${userLevel}`; const results = await permawebDocs.query(learningQuery, ["ao", "arweave"], 10); // Generate learning modules const modules = generateLearningModules(topic, userLevel); // Create exercises const exercises = generateLearningExercises(topic, userLevel); return { exercises, level: userLevel, modules, resources: results, topic, }; } catch (error) { throw new Error(`Failed to get interactive learning: ${error instanceof Error ? error.message : "Unknown error"}`); } }, queryAODevelopmentDocs: async (query, context) => { try { // Enhance query with context const enhancedQuery = buildEnhancedQuery(query, context); // Query AO-specific domains const aoDomains = ["ao", "arweave"]; const results = await permawebDocs.query(enhancedQuery, aoDomains, 15); // Extract development guidance const guidance = extractDevelopmentGuidance(results, context); // Generate code examples const codeExamples = generateCodeExamples(query, context); // Extract best practices const bestPractices = extractBestPractices(results, context); // Identify common pitfalls const commonPitfalls = identifyCommonPitfalls(query, context); // Generate next steps const nextSteps = generateNextSteps(query, context); // Find related topics const relatedTopics = findRelatedTopics(query, context); return { bestPractices, codeExamples, commonPitfalls, nextSteps, primaryGuidance: guidance, relatedTopics, sources: results, }; } catch (error) { throw new Error(`Failed to query AO development docs: ${error instanceof Error ? error.message : "Unknown error"}`); } }, surfaceRelevantPatterns: async (processDefinition, currentTask) => { try { // Build pattern query const patternQuery = `${currentTask} patterns ${processDefinition.name}`; const results = await permawebDocs.query(patternQuery, ["ao", "arweave"], 8); // Generate relevant patterns const patterns = generateRelevantPatterns(processDefinition, currentTask); // Create suggested implementations const suggestedImplementations = generateSuggestedImplementations(processDefinition, currentTask); return { patterns, relevantDocs: results, suggestedImplementations, }; } catch (error) { throw new Error(`Failed to surface relevant patterns: ${error instanceof Error ? error.message : "Unknown error"}`); } }, }; }; // Helper functions const buildEnhancedQuery = (query, context) => { let enhancedQuery = query; if (context?.processType) { enhancedQuery += ` ${context.processType}`; } if (context?.stage) { enhancedQuery += ` ${context.stage}`; } if (context?.framework) { enhancedQuery += ` ${context.framework}`; } if (context?.specificNeeds) { enhancedQuery += ` ${context.specificNeeds.join(" ")}`; } return enhancedQuery; }; const extractDevelopmentGuidance = (results, _context) => { if (results.length === 0) { return "No specific guidance found. Consider checking the AO documentation for general development patterns."; } // Extract key guidance from the most relevant results const topResults = results.slice(0, 3); const guidance = topResults .map((result) => result.content) .join("\n\n") .substring(0, 1000); return guidance; }; const generateCodeExamples = (query, context) => { const examples = []; // Generate examples based on query and context if (query.includes("handler") || context?.stage === "develop") { examples.push({ category: "handler", code: `-- Basic AO Handler in Teal local function handleMessage(msg: AO.Message): AO.Response return { Output = json.encode({ message = "Hello from AO!" }), Messages = {}, Spawns = {}, Assignments = {} } end Handlers.add("hello", Handlers.utils.hasMatchingTag("Action", "Hello"), handleMessage)`, description: "A simple handler for processing AO messages", difficulty: "beginner", language: "teal", tags: ["ao", "handler", "teal"], title: "Basic AO Handler", }); } if (query.includes("test") || context?.stage === "test") { examples.push({ category: "test", code: `// AOLite Test Example import { createAOLiteTestService } from "./AOLiteTestService.js"; const testCase = { id: "test-handler", name: "Test Handler", messages: [{ id: "msg-1", action: "Hello", tags: [{ name: "Action", value: "Hello" }] }], assertions: [{ id: "assert-1", type: "contains", target: "Output", expected: "Hello from AO!" }] };`, description: "Example test case for AO process", difficulty: "intermediate", language: "javascript", tags: ["aolite", "test", "javascript"], title: "AOLite Test Example", }); } return examples; }; const extractBestPractices = (results, context) => { const practices = [ "Use typed development with Teal for better code quality", "Test locally with AOLite before deploying to production", "Follow AO message handling patterns for consistency", "Implement proper error handling in all handlers", "Use meaningful handler names and documentation", ]; // Add context-specific practices if (context?.processType === "token") { practices.push("Implement proper balance checks in transfer handlers"); practices.push("Use denomination for token amount calculations"); } return practices; }; const identifyCommonPitfalls = (query, context) => { const pitfalls = [ "Not handling edge cases in message processing", "Forgetting to validate input parameters", "Inadequate testing before deployment", "Not following AO message structure conventions", "Ignoring gas/computation limits", ]; if (context?.processType === "token") { pitfalls.push("Integer overflow in token calculations"); pitfalls.push("Not checking sender balance before transfers"); } return pitfalls; }; const generateNextSteps = (query, context) => { const steps = [ "Review AO documentation for additional patterns", "Implement comprehensive testing with AOLite", "Test deployment on testnet before mainnet", "Monitor process performance after deployment", ]; if (context?.stage === "develop") { steps.unshift("Complete handler implementation"); steps.unshift("Add proper type definitions"); } return steps; }; const findRelatedTopics = (query, context) => { const topics = [ "AO message handling", "Process communication patterns", "Teal type system", "AOLite testing framework", "Deployment strategies", ]; if (context?.processType === "token") { topics.push("Token economics"); topics.push("Balance management"); } return topics; }; const buildProcessContextQuery = (processDefinition, stage, query) => { const baseQuery = `${stage} ${processDefinition.name}`; if (query) { return `${baseQuery} ${query}`; } return baseQuery; }; const generateStageGuidance = (stage, processDefinition, _results) => { switch (stage) { case "deploy": return `Deployment guidance for ${processDefinition.name}: - Validate all tests pass before deployment - Test on AO testnet first - Monitor process performance after deployment - Have rollback strategy ready`; case "develop": return `Development guidance for ${processDefinition.name}: - Focus on implementing handlers with proper type safety - Use Teal for type-safe AO process development - Follow AO message handling patterns - Implement comprehensive error handling`; case "test": return `Testing guidance for ${processDefinition.name}: - Use AOLite for local testing before deployment - Test all handlers with various input scenarios - Validate message responses and state changes - Implement concurrent testing for performance`; default: return "General development guidance for AO processes"; } }; const generateActionItems = (stage, _processDefinition) => { const items = []; switch (stage) { case "deploy": items.push("Run final test suite"); items.push("Deploy to testnet"); items.push("Monitor process health"); break; case "develop": items.push("Implement remaining handlers"); items.push("Add proper type definitions"); items.push("Validate Teal compilation"); break; case "test": items.push("Create comprehensive test suite"); items.push("Test all handlers with AOLite"); items.push("Validate error handling"); break; } return items; }; const getStageExamples = (stage, _processDefinition) => { // Return stage-specific examples return generateCodeExamples(`${stage} examples`, { stage }); }; const generateTroubleshootingGuides = (_stage, _processDefinition) => { const guides = []; guides.push({ prevention: [ "Test handlers locally with AOLite", "Use proper type definitions", "Implement logging for debugging", ], problem: "Handler not responding to messages", relatedDocs: ["AO Handler Documentation", "Message Processing Guide"], solutions: [ "Check handler registration syntax", "Verify message tag matching", "Validate handler function signature", ], symptoms: ["Messages sent but no response", "Process appears inactive"], }); return guides; }; const generateDevelopmentSteps = (goal, processType) => { const steps = [ { dependencies: [], description: "Study AO documentation and plan process architecture", estimatedTime: "2-4 hours", examples: [], id: "step-1", resources: ["AO Documentation", "Process Examples"], stage: "docs", title: "Research and Planning", }, { dependencies: ["step-1"], description: "Develop process handlers using Teal", estimatedTime: "1-2 days", examples: generateCodeExamples("handler development", { processType }), id: "step-2", resources: ["Teal Compiler", "AO Templates"], stage: "develop", title: "Implement Process Logic", }, { dependencies: ["step-2"], description: "Test process locally using AOLite", estimatedTime: "4-8 hours", examples: generateCodeExamples("testing", { processType }), id: "step-3", resources: ["AOLite Testing Framework"], stage: "test", title: "Local Testing", }, { dependencies: ["step-3"], description: "Deploy process to AO network", estimatedTime: "1-2 hours", examples: [], id: "step-4", resources: ["AO Deployment Tools"], stage: "deploy", title: "Deployment", }, ]; return steps; }; const estimateTimeline = (steps) => { const totalHours = steps.reduce((total, step) => { const hours = step.estimatedTime.match(/(\d+)/); return total + (hours ? parseInt(hours[1]) : 0); }, 0); return `Estimated ${totalHours} hours (${Math.ceil(totalHours / 8)} days)`; }; const identifyPrerequisites = (processType) => { const prerequisites = [ "Basic understanding of AO architecture", "Familiarity with Lua programming", "Teal language knowledge", "Development environment setup", ]; if (processType === "token") { prerequisites.push("Token economics understanding"); } return prerequisites; }; const generateBestPractices = (category, _processType) => { const practices = []; switch (category) { case "ao": practices.push({ description: "Always validate message structure and handle errors gracefully", difficulty: "medium", examples: generateCodeExamples("message handling"), impact: "high", reasoning: "Proper message handling ensures process reliability and user experience", title: "Implement Proper Message Handling", }); break; case "deployment": practices.push({ description: "Always deploy to testnet before mainnet", difficulty: "easy", examples: [], impact: "high", reasoning: "Testnet deployment catches issues without mainnet consequences", title: "Test on Testnet First", }); break; case "teal": practices.push({ description: "Always provide type annotations for function parameters and return values", difficulty: "easy", examples: generateCodeExamples("type annotations"), impact: "high", reasoning: "Type annotations improve code clarity and catch errors at compile time", title: "Use Explicit Type Annotations", }); break; case "testing": practices.push({ description: "Create tests for success, failure, and edge cases", difficulty: "medium", examples: generateCodeExamples("comprehensive testing"), impact: "high", reasoning: "Comprehensive testing prevents production issues and ensures reliability", title: "Test All Handler Scenarios", }); break; } return practices; }; const generateAntiPatterns = (category, _processType) => { const antiPatterns = []; switch (category) { case "ao": antiPatterns.push({ alternatives: [ "Validate all inputs", "Use type guards", "Implement error handling", ], commonIn: ["Simple handlers", "Demo code"], description: "Not validating incoming message structure", examples: [], title: "Ignoring Message Validation", whyBad: "Can lead to runtime errors and security vulnerabilities", }); break; case "teal": antiPatterns.push({ alternatives: [ "Use specific types", "Create proper interfaces", "Use union types", ], commonIn: ["Quick prototypes", "Legacy code migrations"], description: "Overusing 'any' type defeats the purpose of type safety", examples: [], title: "Using 'any' Type Everywhere", whyBad: "Loses type safety benefits and makes code harder to maintain", }); break; } return antiPatterns; }; const generateLearningModules = (topic, userLevel) => { const modules = []; if (topic.includes("ao") || topic.includes("development")) { modules.push({ content: "AO is a hyper-parallel computer built on top of Arweave...", description: "Learn the basics of AO architecture and message handling", examples: generateCodeExamples("ao basics"), id: "ao-basics", nextModules: ["ao-handlers"], prerequisites: [], quiz: [ { correctAnswer: 1, explanation: "AO is a hyper-parallel computer built on Arweave", id: "q1", options: [ "A database", "A hyper-parallel computer", "A programming language", "A testing framework", ], question: "What is AO?", }, ], title: "AO Fundamentals", }); } return modules; }; const generateLearningExercises = (topic, userLevel) => { const exercises = []; exercises.push({ description: "Implement a basic AO handler that responds to messages", difficulty: userLevel, hints: [ "Use json.encode for the output", "Access sender with msg.From", "Return proper AO.Response structure", ], id: "handler-exercise", solution: `local function myHandler(msg: AO.Message): AO.Response return { Output = json.encode({ message = "Hello from " .. msg.From }), Messages = {}, Spawns = {}, Assignments = {} } end`, template: `-- Complete the handler function local function myHandler(msg: AO.Message): AO.Response -- Your code here end Handlers.add("my-handler", Handlers.utils.hasMatchingTag("Action", "MyAction"), myHandler)`, testCases: [ { description: "Should respond with greeting message", expectedOutput: { message: "Hello from test-sender" }, input: { From: "test-sender", Tags: { Action: "MyAction" } }, }, ], title: "Create a Simple Handler", }); return exercises; }; const generateRelevantPatterns = (_processDefinition, currentTask) => { const patterns = []; if (currentTask.includes("handler")) { patterns.push({ description: "Standard pattern for processing AO messages", implementation: { category: "handler", code: `local function handleMessage(msg: AO.Message): AO.Response -- Validate input if not msg.From then return { Output = json.encode({ Error = "Missing sender" }) } end -- Process message local result = processMessage(msg) -- Return response return { Output = json.encode(result), Messages = {}, Spawns = {}, Assignments = {} } end`, description: "Template for AO message handlers", difficulty: "beginner", language: "teal", tags: ["pattern", "handler", "teal"], title: "Basic Message Handler", }, name: "Message Handler Pattern", relatedPatterns: ["Error Handling Pattern", "State Management Pattern"], useCase: "Processing incoming messages in AO processes", variants: [], }); } return patterns; }; const generateSuggestedImplementations = (_processDefinition, currentTask) => { return generateCodeExamples(currentTask, { processType: "generic" }); }; export const createAODevelopmentDocsService = (permawebDocs) => service(permawebDocs);