Make UI global cache version-aware

Store one cached value per cacheId and overwrite when version changes to prevent unbounded growth from per-version keys.
This commit is contained in:
Shantur Rathore
2026-01-05 19:45:33 +00:00
parent 1377bc6b91
commit 2db62b1d17
5 changed files with 96 additions and 68 deletions

View File

@@ -240,29 +240,33 @@ export default function ToolCall(props: ToolCallProps) {
const store = createMemo(() => messageStoreBus.getOrCreate(props.instanceId))
const createVariantCache = (variant: string | (() => string)) =>
const cacheVersion = createMemo(() => {
if (typeof props.partVersion === "number") {
return String(props.partVersion)
}
if (typeof props.messageVersion === "number") {
return String(props.messageVersion)
}
return "noversion"
})
const createVariantCache = (variant: string | (() => string), version?: () => string) =>
useGlobalCache({
instanceId: () => props.instanceId,
sessionId: () => props.sessionId,
scope: TOOL_CALL_CACHE_SCOPE,
key: () => {
cacheId: () => {
const context = cacheContext()
const resolvedVariant = typeof variant === "function" ? variant() : variant
return makeRenderCacheKey(context.toolCallId || undefined, context.messageId, context.partId, resolvedVariant)
},
version: () => (version ? version() : cacheVersion()),
})
const diffCache = createVariantCache("diff")
const permissionDiffCache = createVariantCache("permission-diff")
const markdownCache = createVariantCache("markdown")
const ansiRunningCache = createVariantCache(() => {
const versionKey = typeof props.partVersion === "number" ? String(props.partVersion) : "noversion"
return `ansi-running:${versionKey}`
})
const ansiFinalCache = createVariantCache(() => {
const versionKey = typeof props.partVersion === "number" ? String(props.partVersion) : "noversion"
return `ansi-final:${versionKey}`
})
const ansiRunningCache = createVariantCache("ansi-running", () => "running")
const ansiFinalCache = createVariantCache("ansi-final")
const runningAnsiRenderer = createAnsiStreamRenderer()
let runningAnsiSource = ""
@@ -736,13 +740,8 @@ export default function ToolCall(props: ToolCallProps) {
throw new Error("Tool call markdown requires a part id")
}
const markdownPart: TextPart = { id: partId, type: "text", text: options.content, version: props.partVersion }
const cached = markdownCache.get<RenderCache>()
if (cached) {
markdownPart.renderCache = cached
}
const handleMarkdownRendered = () => {
markdownCache.set(markdownPart.renderCache)
handleScrollRendered()
props.onContentRendered?.()
}
@@ -751,6 +750,8 @@ export default function ToolCall(props: ToolCallProps) {
<div class={messageClass} ref={(element) => scrollHelpers.registerContainer(element)} onScroll={scrollHelpers.handleScroll}>
<Markdown
part={markdownPart}
instanceId={props.instanceId}
sessionId={props.sessionId}
isDark={isDark()}
disableHighlight={disableHighlight}
onRendered={handleMarkdownRendered}