Spaces:
Paused
Paused
File size: 4,306 Bytes
34367da | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | import { Router } from 'express';
import { MemoryRepository } from './memoryRepository.js';
import { MemoryEntityInput, CmaContextRequest } from '@widget-tdc/mcp-types';
export const memoryRouter = Router();
const memoryRepo = new MemoryRepository();
// Simple in-memory cache with TTL
class SimpleCache {
private cache = new Map<string, { data: any; expiry: number }>();
set(key: string, data: any, ttlMs: number = 300000): void { // 5 min default
this.cache.set(key, { data, expiry: Date.now() + ttlMs });
}
get(key: string): any | null {
const entry = this.cache.get(key);
if (!entry) return null;
if (Date.now() > entry.expiry) {
this.cache.delete(key);
return null;
}
return entry.data;
}
clear(): void {
this.cache.clear();
}
}
const contextCache = new SimpleCache();
// Ingest a memory entity
memoryRouter.post('/ingest', async (req, res) => {
try {
const input: MemoryEntityInput = req.body;
if (!input.orgId || !input.entityType || !input.content) {
return res.status(400).json({
error: 'Missing required fields: orgId, entityType, content',
});
}
const entityId = await memoryRepo.ingestEntity(input);
// Clear context cache when new memory is added to ensure freshness
contextCache.clear();
res.json({
success: true,
id: entityId,
});
} catch (error: any) {
console.error('Memory ingest error:', error);
res.status(500).json({
success: false,
error: error.message,
});
}
});
// Get contextual prompt with memories
memoryRouter.post('/contextual-prompt', async (req, res) => {
try {
const request: CmaContextRequest = req.body;
if (!request.orgId || !request.userId || !request.userQuery) {
return res.status(400).json({
error: 'Missing required fields: orgId, userId, userQuery',
});
}
// Create cache key from request parameters
const cacheKey = `${request.orgId}:${request.userId}:${request.userQuery}:${JSON.stringify(request.keywords || [])}:${request.widgetData || ''}`;
// Check cache first
const cachedResult = contextCache.get(cacheKey);
if (cachedResult) {
return res.json({
success: true,
...cachedResult,
cached: true,
});
}
// Search for relevant memories with enhanced semantic search
const memories = await memoryRepo.searchEntities({
orgId: request.orgId,
userId: request.userId,
keywords: request.keywords || [],
limit: 5,
});
// Build enhanced contextual prompt with semantic scoring
const memoryContext = memories.map(m => {
const score = m.semanticScore ? ` (semantic score: ${(m.semanticScore * 100).toFixed(1)}%)` : '';
return `[${m.entity_type}] ${m.content} (importance: ${m.importance})${score}`;
}).join('\n');
const prompt = `
Context from memory (enhanced with semantic search):
${memoryContext}
Widget data:
${request.widgetData || 'None'}
User query:
${request.userQuery}
Please provide a hyper-contextual response considering the semantic relationships and importance scores above.
`.trim();
const result = {
prompt,
memories: memories.map(m => ({
id: m.id,
content: m.content,
importance: m.importance,
semanticScore: m.semanticScore,
})),
};
// Cache the result for 5 minutes
contextCache.set(cacheKey, result, 300000);
res.json({
success: true,
...result,
cached: false,
});
} catch (error: any) {
console.error('Contextual prompt error:', error);
res.status(500).json({
success: false,
error: error.message,
});
}
});
// Search memories
memoryRouter.post('/search', async (req, res) => {
try {
const query = req.body;
const memories = await memoryRepo.searchEntities(query);
res.json({
success: true,
memories,
count: memories.length,
});
} catch (error: any) {
console.error('Memory search error:', error);
res.status(500).json({
success: false,
error: error.message,
});
}
});
|