UNPKG

echonodesync

Version:

Autonomous, pluggable, secure memory bridge for agent/human/ritual ecosystems (DreamWeaver, EchoThreads, etc.)

95 lines (87 loc) 3 kB
#!/usr/bin/env node // 🧠🌸 EchoNodeSync: getMemory implementation (HTTP backend only) // Retrieves a memory value for a given key from the /api/memory HTTP backend. // Caches successful GETs as .mia/<key>.json for efficiency. const fs = require('fs'); const path = require('path'); const fetch = require('node-fetch'); const os = require('os'); function stripQuotes(str) { if (!str) return str; return str.replace(/^['"]+|['"]+$/g, '').trim(); } function resolveApiUrl() { if (process.env.ECHONODESYNC_API_URL) return stripQuotes(process.env.ECHONODESYNC_API_URL); const envPaths = [ path.resolve(process.cwd(), '.env'), path.resolve(os.homedir(), '.env') ]; for (const envPath of envPaths) { if (fs.existsSync(envPath)) { const lines = fs.readFileSync(envPath, 'utf8').split(/\r?\n/); for (const line of lines) { const match = line.match(/^\s*ECHONODESYNC_API_URL\s*=\s*(.+)\s*$/); if (match) return stripQuotes(match[1]); } } } return 'http://localhost:3000/api/memory'; } function resolveSecret() { if (process.env.ECHONODESYNC_SECRET) return stripQuotes(process.env.ECHONODESYNC_SECRET); const envPaths = [ path.resolve(process.cwd(), '.env'), path.resolve(os.homedir(), '.env') ]; for (const envPath of envPaths) { if (fs.existsSync(envPath)) { const lines = fs.readFileSync(envPath, 'utf8').split(/\r?\n/); for (const line of lines) { const match = line.match(/^\s*ECHONODESYNC_SECRET\s*=\s*(.+)\s*$/); if (match) return stripQuotes(match[1]); } } } return null; } const BASE_URL = resolveApiUrl().replace(/\/+$/, ''); // Remove trailing slashes const SECRET = resolveSecret(); const CACHE_DIR = path.join(__dirname, '../.mia'); async function getMemory(key) { // Compose URL as per OpenAPI: /api/memory?key=KEY const url = `${BASE_URL}?key=${encodeURIComponent(key)}`; try { const headers = {}; if (SECRET) headers['Authorization'] = `Bearer ${SECRET}`; const res = await fetch(url, { headers }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); // Cache result as .mia/<key>.json if (!fs.existsSync(CACHE_DIR)) fs.mkdirSync(CACHE_DIR); fs.writeFileSync(path.join(CACHE_DIR, `${key}.json`), JSON.stringify(data, null, 2)); console.log(data.value); return data.value; } catch (err) { console.error(`Failed to fetch memory for key '${key}':`, err.message); process.exit(1); } } if (require.main === module) { let key; const argv = process.argv.slice(2); if (argv.includes('--key')) { const keyIdx = argv.indexOf('--key'); key = argv[keyIdx + 1]; if (!key) { console.error('Usage: get-memory --key <key>'); process.exit(1); } } else if (argv.length === 1) { key = argv[0]; } else { console.error('Usage: get-memory <key> | get-memory --key <key>'); process.exit(1); } getMemory(key); } module.exports = getMemory;