Files
tutti/packages/agent/gui/shared/parsedDocumentCache.ts
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

97 lines
2.5 KiB
TypeScript

const MAX_CACHE_ENTRIES = 256;
const MAX_CACHE_SOURCE_CHARS = 2_000_000;
interface ParsedDocumentCacheEntry {
source: string;
value: unknown;
weight: number;
}
const parsedDocumentCache = new Map<string, ParsedDocumentCacheEntry>();
const parsedDocumentCacheStats = {
hits: 0,
misses: 0,
sourceChars: 0
};
export function readParsedDocumentCache<T>(input: {
namespace: string;
identity: string;
source: string;
create: () => T;
}): T {
const key = `${input.namespace}:${input.identity}:${hashCacheSource(input.source)}`;
const cached = parsedDocumentCache.get(key);
if (cached?.source === input.source) {
parsedDocumentCache.delete(key);
parsedDocumentCache.set(key, cached);
parsedDocumentCacheStats.hits += 1;
return cached.value as T;
}
parsedDocumentCacheStats.misses += 1;
const value = input.create();
if (input.source.length > MAX_CACHE_SOURCE_CHARS) {
return value;
}
if (cached) {
parsedDocumentCache.delete(key);
parsedDocumentCacheStats.sourceChars -= cached.weight;
}
const entry = {
source: input.source,
value,
weight: input.source.length
};
parsedDocumentCache.set(key, entry);
parsedDocumentCacheStats.sourceChars += entry.weight;
trimParsedDocumentCache();
return value;
}
export function resetParsedDocumentCacheForTests(): void {
parsedDocumentCache.clear();
parsedDocumentCacheStats.hits = 0;
parsedDocumentCacheStats.misses = 0;
parsedDocumentCacheStats.sourceChars = 0;
}
export function parsedDocumentCacheStatsForTests(): {
entries: number;
hits: number;
misses: number;
sourceChars: number;
} {
return {
entries: parsedDocumentCache.size,
hits: parsedDocumentCacheStats.hits,
misses: parsedDocumentCacheStats.misses,
sourceChars: parsedDocumentCacheStats.sourceChars
};
}
function trimParsedDocumentCache(): void {
while (
parsedDocumentCache.size > MAX_CACHE_ENTRIES ||
parsedDocumentCacheStats.sourceChars > MAX_CACHE_SOURCE_CHARS
) {
const oldest = parsedDocumentCache.entries().next().value as
| [string, ParsedDocumentCacheEntry]
| undefined;
if (!oldest) {
return;
}
parsedDocumentCache.delete(oldest[0]);
parsedDocumentCacheStats.sourceChars -= oldest[1].weight;
}
}
function hashCacheSource(source: string): string {
let hash = 2_166_136_261;
for (let index = 0; index < source.length; index += 1) {
hash ^= source.charCodeAt(index);
hash = Math.imul(hash, 16_777_619);
}
return `${source.length}:${hash >>> 0}`;
}