perf: migrate chat rendering to virtua (#1651)

* refactor: migrate chat history virtualization to virtua

* refactor: render loaded chat history directly

* refactor: finish virtua migration

* perf: defer tool body rendering

* perf: queue deferred tool body mounts

* perf: quiet and defer markdown file probes

* perf: defer markdown code highlighting

* perf: stabilize markdown plugin lists

* perf: defer mermaid markdown rendering

* perf: delay markdown file reference annotation

* perf: attach markdown table listeners on demand

* perf: trim markdown render overhead
This commit is contained in:
Bohdan Triapitsyn
2026-06-15 03:29:40 +03:00
committed by GitHub
parent e372c8d8cb
commit a45376d585
24 changed files with 621 additions and 671 deletions
@@ -2,10 +2,4 @@ export const ACTIVITY_STANDALONE_TOOL_NAMES = new Set<string>(['task']);
export const HIDDEN_INTERNAL_TOOL_NAMES = new Set<string>(['todowrite', 'todoread']);
export const TURN_WINDOW_DEFAULTS = {
initialTurns: 7,
batchTurns: 7,
prefetchBuffer: 16,
} as const;
export const TURN_TEXT_THROTTLE_DEFAULT_MS = 100;
@@ -1,5 +1,4 @@
import type { ChatMessageEntry } from './types';
import { TURN_WINDOW_DEFAULTS } from './constants';
const resolveMessageRole = (message: ChatMessageEntry): string => {
const role = (message.info as { clientRole?: string | null; role?: string | null }).clientRole ?? message.info.role;
@@ -203,46 +202,3 @@ export const buildTurnWindowModel = (messages: ChatMessageEntry[]): TurnWindowMo
turnCount: turnIds.length,
};
};
export const getInitialTurnStart = (
turnCount: number,
initialTurns = TURN_WINDOW_DEFAULTS.initialTurns,
): number => {
if (turnCount <= 0) {
return 0;
}
return turnCount > initialTurns ? turnCount - initialTurns : 0;
};
export const clampTurnStart = (turnStart: number, turnCount: number): number => {
if (turnCount <= 0) {
return 0;
}
if (turnStart <= 0) {
return 0;
}
return Math.min(turnStart, turnCount - 1);
};
export const getTurnWindowSliceStart = (
model: Pick<TurnWindowModel, 'turnMessageStartIndexes'>,
turnStart: number,
): number => {
if (turnStart <= 0) {
return 0;
}
const from = model.turnMessageStartIndexes[turnStart];
return typeof from === 'number' ? from : 0;
};
export const windowMessagesByTurn = (
messages: ChatMessageEntry[],
model: Pick<TurnWindowModel, 'turnMessageStartIndexes'>,
turnStart: number,
): ChatMessageEntry[] => {
const sliceStart = getTurnWindowSliceStart(model, turnStart);
if (sliceStart <= 0) {
return messages;
}
return messages.slice(sliceStart);
};