Skip to main content
Glama

myAI Memory Sync

by Jktfe
naturalLanguageParser.ts9.15 kB
/** * Natural Language Command Parser for myAI Memory * * This module processes natural language commands like: * "Use myAI Memory to remember I work at New Model VC" * and converts them to structured updates for the memory template. */ import { templateService } from './services/templateService.js'; import { platformService } from './services/platformService.js'; import { MemoryTemplate } from './types.js'; import { generateTemplate } from './templateParser.js'; // Define section keywords for automatic categorization const sectionKeywords = { 'User Information': [ 'name', 'age', 'location', 'live', 'address', 'phone', 'email', 'birthday', 'work', 'job', 'family', 'spouse', 'child', 'children', 'pet', 'hobby', 'hobbies', 'interest', 'interests', 'education', 'school', 'university', 'wife', 'husband', 'partner', 'daughter', 'son', 'car', 'vehicle', 'house', 'home', 'founded', 'company', 'business' ], 'General Response Style': [ 'response', 'style', 'tone', 'voice', 'formal', 'informal', 'casual', 'professional', 'friendly', 'concise', 'detailed', 'respond', 'emoji', 'language', 'prefer', 'spelling', 'format', 'formatting', 'brevity', 'thorough', 'currency', 'structure' ], 'Coding Preferences': [ 'code', 'coding', 'programming', 'language', 'framework', 'library', 'platform', 'syntax', 'style', 'indent', 'indentation', 'comment', 'documentation', 'naming', 'convention', 'pattern', 'architecture', 'design', 'test', 'testing', 'debug', 'debugging', 'editor', 'IDE', 'terminal', 'compiler', 'interpreter', 'svelte', 'react', 'angular', 'vue', 'node', 'python', 'java', 'javascript', 'typescript' ], 'MCP': [ 'mcp', 'file', 'access', 'permission', 'gitignore', 'credential', 'api', 'key', 'secret', 'token', 'filesystem', 'filesystem', 'filesystem mcp', 'serveMyAPI', 'serve', 'server', 'endpoint', 'host' ] }; /** * Interface for memory item creation */ interface MemoryItem { section: string; content: string; } /** * Parses a natural language command and extracts memory information * @param command The natural language command * @returns A structured memory item or null if not a memory command */ export function parseMemoryCommand(command: string): MemoryItem | null { // Check if this is a memory command with multiple patterns const memoryPatterns = [ /use\s+myai\s+memory\s+to\s+remember\s+(.*)/i, /remember\s+that\s+(.*)/i, /add\s+to\s+my\s+memory\s+that\s+(.*)/i, /use\s+myai\s+memory\s+to\s+add\s+to\s+(.*?)\s+(.*)/i, /update\s+my\s+(.*?)\s+to\s+include\s+that\s+(.*)/i ]; for (const pattern of memoryPatterns) { const match = command.match(pattern); if (match) { // Special handling for "add to section" pattern if (pattern.toString().includes('add\\s+to\\s+(.*?)\\s+')) { const sectionNameFromCommand = match[1].trim(); const content = match[2].trim(); // Find the best section match by checking keyword categories const sectionName = findBestSectionMatch(sectionNameFromCommand); return { section: sectionName, content: content }; } // Special handling for "update my section" pattern if (pattern.toString().includes('update\\s+my\\s+(.*?)\\s+to\\s+include')) { const sectionNameFromCommand = match[1].trim(); const content = match[2].trim(); // Find the best section match by checking keyword categories const sectionName = findBestSectionMatch(sectionNameFromCommand); return { section: sectionName, content: content }; } // Standard match handling for simpler patterns const content = match[1].trim(); const section = determineBestSection(content); return { section, content }; } } return null; } /** * Find the best matching section name from a partial name * @param partialName The partial section name from the command * @returns The full section name */ function findBestSectionMatch(partialName: string): string { const lowercasePartial = partialName.toLowerCase(); // First try exact matches of section names for (const sectionName of Object.keys(sectionKeywords)) { if (sectionName.toLowerCase() === lowercasePartial) { return sectionName; } } // Then try partial matches for (const sectionName of Object.keys(sectionKeywords)) { if (sectionName.toLowerCase().includes(lowercasePartial) || lowercasePartial.includes(sectionName.toLowerCase())) { return sectionName; } } // If no match found, use the partial name directly with proper casing return partialName.split(' ') .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) .join(' '); } /** * Determines the best section for a piece of content based on keywords * @param content The content to categorize * @returns The name of the best matching section */ function determineBestSection(content: string): string { // Default to User Information if no better match is found let bestSection = 'User Information'; let bestScore = 0; // Convert content to lowercase for better matching const lowercaseContent = content.toLowerCase(); // Check each section's keywords for matches for (const [section, keywords] of Object.entries(sectionKeywords)) { let score = 0; for (const keyword of keywords) { if (lowercaseContent.includes(keyword.toLowerCase())) { score++; } } if (score > bestScore) { bestScore = score; bestSection = section; } } return bestSection; } /** * Formats memory content to match template format with -~- prefix * @param content Raw content string * @returns Formatted content string */ function formatContent(content: string): string { // If the content already has a -~- prefix, return as is if (content.trim().startsWith('-~-')) { return content; } // Try to extract a key/value pair const keyValueMatch = content.match(/^(my|i|we)\s+(.*?)\s+is\s+(.*)/i); if (keyValueMatch) { const key = keyValueMatch[2].trim(); const value = keyValueMatch[3].trim(); return `-~- ${key}: ${value}`; } // If there's a colon in the content, try to split on that if (content.includes(':')) { const parts = content.split(':'); if (parts.length >= 2) { const key = parts[0].trim(); const value = parts.slice(1).join(':').trim(); return `-~- ${key}: ${value}`; } } // For statements that don't fit the key/value pattern return `-~- ${content}`; } /** * Processes a memory command, updates the template, and syncs to platforms * @param command The natural language command * @returns Success status and message */ export async function processMemoryCommand(command: string): Promise<{ success: boolean; message: string }> { try { // Initialize services if not already initialized await templateService.initialize(); await platformService.initialize(); // Parse the command const memoryItem = parseMemoryCommand(command); if (!memoryItem) { return { success: false, message: "Not a valid memory command. Use 'Use myAI Memory to remember [your information]'" }; } // Get the current section content let section = await templateService.getSection(memoryItem.section); // If section doesn't exist, create it if (!section) { console.error(`Section "${memoryItem.section}" does not exist, creating it`); const created = await templateService.createSection(memoryItem.section); if (!created) { return { success: false, message: `Failed to create section '${memoryItem.section}'.` }; } // Get the newly created section section = await templateService.getSection(memoryItem.section); } // Format the new content const formattedContent = formatContent(memoryItem.content); // Update the section const success = await templateService.updateSection(memoryItem.section, formattedContent); if (!success) { return { success: false, message: `Failed to update section '${memoryItem.section}'.` }; } // Get the updated template const template = await templateService.getTemplate(); // Generate markdown content from template const templateContent = generateTemplate(template); // Sync to all platforms const results = await platformService.syncAll(templateContent); const successCount = results.filter(r => r.success).length; return { success: true, message: `Added to ${memoryItem.section}. Synced to ${successCount}/${results.length} platforms.` }; } catch (error) { console.error('Error in processMemoryCommand:', error); return { success: false, message: `Error processing memory command: ${error instanceof Error ? error.message : String(error)}` }; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jktfe/myAImemory-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server