From db3d41622c8e9b1885490deb0dc7321cab6a8fdc Mon Sep 17 00:00:00 2001 From: can1357 Date: Sat, 31 Jan 2026 13:15:39 +0100 Subject: [PATCH] perf(coding-agent/tools): implemented caching in table and cell renderers to avoid redundant recalculations - Implemented caching in table and cell results renderers to avoid redundant recalculations when width or cell data hasn't changed. - Added cache invalidation logic to clear cached render results when cell data or spinner state changes. --- packages/coding-agent/CHANGELOG.md | 2 +- packages/coding-agent/src/tools/python.ts | 29 +++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 278d47b5b..4e3b5b0c6 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -1,9 +1,9 @@ # Changelog ## [Unreleased] - ### Changed +- Improved rendering performance for Python cell output by implementing caching in the table and cell results renderers - Updated task tool documentation to clarify that subagents can access parent conversation context via a searchable file, reducing need to repeat information in context parameter - Updated plan mode prompt to guide model toward using `edit` tool for incremental plan updates instead of defaulting to `write` diff --git a/packages/coding-agent/src/tools/python.ts b/packages/coding-agent/src/tools/python.ts index 18910f23a..8c59ebd0f 100644 --- a/packages/coding-agent/src/tools/python.ts +++ b/packages/coding-agent/src/tools/python.ts @@ -785,8 +785,15 @@ export const pythonToolRenderer = { return new Text(text, 0, 0); } + // Cache state - cells don't change, only width varies + let cached: { width: number; result: string[] } | undefined; + return { render: (width: number): string[] => { + if (cached && cached.width === width) { + return cached.result; + } + const lines: string[] = []; for (let i = 0; i < cells.length; i++) { const cell = cells[i]; @@ -812,9 +819,12 @@ export const pythonToolRenderer = { lines.push(""); } } + cached = { width, result: lines }; return lines; }, - invalidate: () => {}, + invalidate: () => { + cached = undefined; + }, }; }, @@ -864,8 +874,20 @@ export const pythonToolRenderer = { const cellResults = details?.cells; if (cellResults && cellResults.length > 0) { + // Cache state following Box pattern + let cached: { key: string; width: number; result: string[] } | undefined; + + const buildCacheKey = (spinnerFrame: number | undefined): string => { + return `${expanded}|${previewLines}|${spinnerFrame}`; + }; + return { render: (width: number): string[] => { + const key = buildCacheKey(options.spinnerFrame); + if (cached && cached.key === key && cached.width === width) { + return cached.result; + } + const lines: string[] = []; for (let i = 0; i < cellResults.length; i++) { const cell = cellResults[i]; @@ -921,9 +943,12 @@ export const pythonToolRenderer = { if (warningLine) { lines.push(warningLine); } + cached = { key, width, result: lines }; return lines; }, - invalidate: () => {}, + invalidate: () => { + cached = undefined; + }, }; }