|
|
|
|
|
|
|
|
|
|
|
import memoryManager, { MemoryPressure } from './memoryManager.js'; |
|
|
|
|
|
const reasoningSignatureCache = new Map(); |
|
|
const toolSignatureCache = new Map(); |
|
|
|
|
|
|
|
|
const MAX_REASONING_ENTRIES = 256; |
|
|
const MAX_TOOL_ENTRIES = 256; |
|
|
|
|
|
|
|
|
const ENTRY_TTL_MS = 30 * 60 * 1000; |
|
|
const CLEAN_INTERVAL_MS = 10 * 60 * 1000; |
|
|
|
|
|
function makeKey(sessionId, model) { |
|
|
return `${sessionId || ''}::${model || ''}`; |
|
|
} |
|
|
|
|
|
function pruneMap(map, targetSize) { |
|
|
if (map.size <= targetSize) return; |
|
|
const removeCount = map.size - targetSize; |
|
|
let removed = 0; |
|
|
for (const key of map.keys()) { |
|
|
map.delete(key); |
|
|
removed++; |
|
|
if (removed >= removeCount) break; |
|
|
} |
|
|
} |
|
|
|
|
|
function pruneExpired(map, now) { |
|
|
for (const [key, entry] of map.entries()) { |
|
|
if (!entry || typeof entry.ts !== 'number') continue; |
|
|
if (now - entry.ts > ENTRY_TTL_MS) { |
|
|
map.delete(key); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
memoryManager.registerCleanup((pressure) => { |
|
|
if (pressure === MemoryPressure.MEDIUM) { |
|
|
|
|
|
pruneMap(reasoningSignatureCache, Math.floor(MAX_REASONING_ENTRIES / 2)); |
|
|
pruneMap(toolSignatureCache, Math.floor(MAX_TOOL_ENTRIES / 2)); |
|
|
} else if (pressure === MemoryPressure.HIGH) { |
|
|
|
|
|
pruneMap(reasoningSignatureCache, Math.floor(MAX_REASONING_ENTRIES / 4)); |
|
|
pruneMap(toolSignatureCache, Math.floor(MAX_TOOL_ENTRIES / 4)); |
|
|
} else if (pressure === MemoryPressure.CRITICAL) { |
|
|
|
|
|
reasoningSignatureCache.clear(); |
|
|
toolSignatureCache.clear(); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
setInterval(() => { |
|
|
const now = Date.now(); |
|
|
pruneExpired(reasoningSignatureCache, now); |
|
|
pruneExpired(toolSignatureCache, now); |
|
|
}, CLEAN_INTERVAL_MS).unref?.(); |
|
|
|
|
|
export function setReasoningSignature(sessionId, model, signature) { |
|
|
if (!signature) return; |
|
|
const key = makeKey(sessionId, model); |
|
|
reasoningSignatureCache.set(key, { signature, ts: Date.now() }); |
|
|
|
|
|
pruneMap(reasoningSignatureCache, MAX_REASONING_ENTRIES); |
|
|
} |
|
|
|
|
|
export function getReasoningSignature(sessionId, model) { |
|
|
const key = makeKey(sessionId, model); |
|
|
const entry = reasoningSignatureCache.get(key); |
|
|
if (!entry) return null; |
|
|
const now = Date.now(); |
|
|
if (typeof entry.ts === 'number' && now - entry.ts > ENTRY_TTL_MS) { |
|
|
reasoningSignatureCache.delete(key); |
|
|
return null; |
|
|
} |
|
|
return entry.signature || null; |
|
|
} |
|
|
|
|
|
export function setToolSignature(sessionId, model, signature) { |
|
|
if (!signature) return; |
|
|
const key = makeKey(sessionId, model); |
|
|
toolSignatureCache.set(key, { signature, ts: Date.now() }); |
|
|
pruneMap(toolSignatureCache, MAX_TOOL_ENTRIES); |
|
|
} |
|
|
|
|
|
export function getToolSignature(sessionId, model) { |
|
|
const key = makeKey(sessionId, model); |
|
|
const entry = toolSignatureCache.get(key); |
|
|
if (!entry) return null; |
|
|
const now = Date.now(); |
|
|
if (typeof entry.ts === 'number' && now - entry.ts > ENTRY_TTL_MS) { |
|
|
toolSignatureCache.delete(key); |
|
|
return null; |
|
|
} |
|
|
return entry.signature || null; |
|
|
} |
|
|
|
|
|
|
|
|
export function clearThoughtSignatureCaches() { |
|
|
reasoningSignatureCache.clear(); |
|
|
toolSignatureCache.clear(); |
|
|
} |
|
|
|