UNPKG

permamind

Version:

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

170 lines (169 loc) 6.62 kB
import { fetchEvents } from "../../../relay.js"; import { MEMORY_KINDS } from "../../../services/aiMemoryService.js"; // Resolve contact name to address using memories export async function resolveAddress(input, hubId) { if (looksLikeProcessId(input)) { return { requiresVerification: false, resolved: true, value: input }; } try { // Use dedicated kind for efficient filtering const filter = { kinds: [MEMORY_KINDS.CONTACT_MAPPING], limit: 100, }; const _filters = JSON.stringify([filter]); const events = await fetchEvents(hubId, _filters); const addressMatches = []; const inputLower = input.toLowerCase(); for (const event of events) { try { const name = event.contact_name || ""; const address = event.contact_address || ""; if (!name || !address) continue; let confidence = 0; if (name.toLowerCase() === inputLower) { confidence = 0.9; } else if (name.toLowerCase().includes(inputLower)) { confidence = 0.7; } if (confidence > 0) { addressMatches.push({ address, confidence, name, }); } } catch { // Skip invalid entries continue; } } // Sort by confidence addressMatches.sort((a, b) => b.confidence - a.confidence); if (addressMatches.length === 0) { return { requiresVerification: false, resolved: false, verificationMessage: `No contact found for "${input}". Use saveAddressMapping to register this contact.`, }; } if (addressMatches.length === 1 && addressMatches[0].confidence > 0.8) { const match = addressMatches[0]; return { requiresVerification: true, resolved: true, value: match.address, verificationMessage: `Found contact: ${match.name} (${match.address}). Continue?`, }; } // Multiple matches - return all for user selection return { matches: addressMatches.map((m) => m.address), requiresVerification: true, resolved: false, verificationMessage: `Multiple contacts found for "${input}": ${addressMatches .map((m) => `${m.name} (${m.address.slice(0, 8)}...)`) .join(", ")}. Please specify which one to use.`, }; } catch (error) { return { requiresVerification: false, resolved: false, verificationMessage: `Error resolving contact "${input}": ${error instanceof Error ? error.message : "Unknown error"}`, }; } } // Resolve token name/ticker to processId using memories export async function resolveToken(input, hubId) { if (looksLikeProcessId(input)) { return { requiresVerification: false, resolved: true, value: input }; } try { // Use dedicated kind for efficient filtering const filter = { kinds: [MEMORY_KINDS.TOKEN_MAPPING], limit: 100, }; const _filters = JSON.stringify([filter]); const events = await fetchEvents(hubId, _filters); const tokenMatches = []; const inputLower = input.toLowerCase(); for (const event of events) { try { const name = event.token_name || ""; const ticker = event.token_ticker || ""; const processId = event.token_processId || ""; if (!name || !ticker || !processId) continue; let confidence = 0; // Check if input matches ticker if (ticker.toLowerCase() === inputLower) { confidence = 0.9; } // Check if input matches name else if (name.toLowerCase().includes(inputLower)) { confidence = 0.8; } // Partial match else if (name.toLowerCase().includes(inputLower) || ticker.toLowerCase().includes(inputLower)) { confidence = 0.5; } if (confidence > 0) { tokenMatches.push({ confidence, name, processId, ticker, }); } } catch { // Skip invalid entries continue; } } // Sort by confidence tokenMatches.sort((a, b) => b.confidence - a.confidence); if (tokenMatches.length === 0) { return { requiresVerification: false, resolved: false, verificationMessage: `No token found for "${input}". Use saveTokenMapping to register this token.`, }; } if (tokenMatches.length === 1 && tokenMatches[0].confidence > 0.8) { const match = tokenMatches[0]; return { requiresVerification: true, resolved: true, value: match.processId, verificationMessage: `Found token: ${match.name || match.ticker || "Unknown"} (${match.processId}). Continue?`, }; } // Multiple matches or low confidence - return all for user selection return { matches: tokenMatches.map((m) => m.processId), requiresVerification: true, resolved: false, verificationMessage: `Multiple tokens found for "${input}": ${tokenMatches .map((m) => `${m.name || m.ticker || "Unknown"} (${m.processId.slice(0, 8)}...)`) .join(", ")}. Please specify which one to use.`, }; } catch (error) { return { requiresVerification: false, resolved: false, verificationMessage: `Error resolving token "${input}": ${error instanceof Error ? error.message : "Unknown error"}`, }; } } // Check if input looks like a processId (43-character base64-like string) function looksLikeProcessId(input) { return /^[A-Za-z0-9_-]{43}$/.test(input); }