115 lines
3.3 KiB
JavaScript
115 lines
3.3 KiB
JavaScript
/**
|
|
* Signature Cache
|
|
* In-memory cache for Gemini thoughtSignatures
|
|
*
|
|
* Gemini models require thoughtSignature on tool calls, but Claude Code
|
|
* strips non-standard fields. This cache stores signatures by tool_use_id
|
|
* so they can be restored in subsequent requests.
|
|
*
|
|
* Also caches thinking block signatures with model family for cross-model
|
|
* compatibility checking.
|
|
*/
|
|
|
|
import { GEMINI_SIGNATURE_CACHE_TTL_MS, MIN_SIGNATURE_LENGTH } from '../constants.js';
|
|
|
|
const signatureCache = new Map();
|
|
const thinkingSignatureCache = new Map();
|
|
|
|
/**
|
|
* Store a signature for a tool_use_id
|
|
* @param {string} toolUseId - The tool use ID
|
|
* @param {string} signature - The thoughtSignature to cache
|
|
*/
|
|
export function cacheSignature(toolUseId, signature) {
|
|
if (!toolUseId || !signature) return;
|
|
signatureCache.set(toolUseId, {
|
|
signature,
|
|
timestamp: Date.now()
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get a cached signature for a tool_use_id
|
|
* @param {string} toolUseId - The tool use ID
|
|
* @returns {string|null} The cached signature or null if not found/expired
|
|
*/
|
|
export function getCachedSignature(toolUseId) {
|
|
if (!toolUseId) return null;
|
|
const entry = signatureCache.get(toolUseId);
|
|
if (!entry) return null;
|
|
|
|
// Check TTL
|
|
if (Date.now() - entry.timestamp > GEMINI_SIGNATURE_CACHE_TTL_MS) {
|
|
signatureCache.delete(toolUseId);
|
|
return null;
|
|
}
|
|
|
|
return entry.signature;
|
|
}
|
|
|
|
/**
|
|
* Clear expired entries from the cache
|
|
* Can be called periodically to prevent memory buildup
|
|
*/
|
|
export function cleanupCache() {
|
|
const now = Date.now();
|
|
for (const [key, entry] of signatureCache) {
|
|
if (now - entry.timestamp > GEMINI_SIGNATURE_CACHE_TTL_MS) {
|
|
signatureCache.delete(key);
|
|
}
|
|
}
|
|
for (const [key, entry] of thinkingSignatureCache) {
|
|
if (now - entry.timestamp > GEMINI_SIGNATURE_CACHE_TTL_MS) {
|
|
thinkingSignatureCache.delete(key);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the current cache size (for debugging)
|
|
* @returns {number} Number of entries in the cache
|
|
*/
|
|
export function getCacheSize() {
|
|
return signatureCache.size;
|
|
}
|
|
|
|
/**
|
|
* Cache a thinking block signature with its model family
|
|
* @param {string} signature - The thinking signature to cache
|
|
* @param {string} modelFamily - The model family ('claude' or 'gemini')
|
|
*/
|
|
export function cacheThinkingSignature(signature, modelFamily) {
|
|
if (!signature || signature.length < MIN_SIGNATURE_LENGTH) return;
|
|
thinkingSignatureCache.set(signature, {
|
|
modelFamily,
|
|
timestamp: Date.now()
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get the cached model family for a thinking signature
|
|
* @param {string} signature - The signature to look up
|
|
* @returns {string|null} 'claude', 'gemini', or null if not found/expired
|
|
*/
|
|
export function getCachedSignatureFamily(signature) {
|
|
if (!signature) return null;
|
|
const entry = thinkingSignatureCache.get(signature);
|
|
if (!entry) return null;
|
|
|
|
// Check TTL
|
|
if (Date.now() - entry.timestamp > GEMINI_SIGNATURE_CACHE_TTL_MS) {
|
|
thinkingSignatureCache.delete(signature);
|
|
return null;
|
|
}
|
|
|
|
return entry.modelFamily;
|
|
}
|
|
|
|
/**
|
|
* Get the current thinking signature cache size (for debugging)
|
|
* @returns {number} Number of entries in the thinking signature cache
|
|
*/
|
|
export function getThinkingCacheSize() {
|
|
return thinkingSignatureCache.size;
|
|
}
|