95 lines
2.6 KiB
TypeScript
95 lines
2.6 KiB
TypeScript
import type { StreamItem } from "@/types/stream";
|
|
|
|
export const DEFAULT_WEB_PARTIAL_VIRTUALIZATION_THRESHOLD = 100;
|
|
export const DEFAULT_WEB_MOUNTED_RECENT_STREAM_ITEMS = 50;
|
|
|
|
type BottomAnchorE2ETestGlobals = typeof globalThis & {
|
|
__PASEO_E2E_WEB_PARTIAL_VIRTUALIZATION_THRESHOLD?: unknown;
|
|
__PASEO_E2E_WEB_MOUNTED_RECENT_STREAM_ITEMS?: unknown;
|
|
};
|
|
|
|
function readPositiveIntegerOverride(value: unknown): number | null {
|
|
if (!Number.isFinite(value)) {
|
|
return null;
|
|
}
|
|
const normalized = Math.trunc(value as number);
|
|
return normalized > 0 ? normalized : null;
|
|
}
|
|
|
|
export function getWebPartialVirtualizationThreshold(): number {
|
|
const override = readPositiveIntegerOverride(
|
|
(globalThis as BottomAnchorE2ETestGlobals)
|
|
.__PASEO_E2E_WEB_PARTIAL_VIRTUALIZATION_THRESHOLD
|
|
);
|
|
return override ?? DEFAULT_WEB_PARTIAL_VIRTUALIZATION_THRESHOLD;
|
|
}
|
|
|
|
export function getWebMountedRecentStreamItems(): number {
|
|
const override = readPositiveIntegerOverride(
|
|
(globalThis as BottomAnchorE2ETestGlobals)
|
|
.__PASEO_E2E_WEB_MOUNTED_RECENT_STREAM_ITEMS
|
|
);
|
|
return override ?? DEFAULT_WEB_MOUNTED_RECENT_STREAM_ITEMS;
|
|
}
|
|
|
|
export type IndexedStreamItem = {
|
|
item: StreamItem;
|
|
index: number;
|
|
};
|
|
|
|
export type WebVirtualizedHistoryWindow = {
|
|
virtualizedEntries: IndexedStreamItem[];
|
|
mountedEntries: IndexedStreamItem[];
|
|
};
|
|
|
|
export function estimateStreamItemHeight(item: StreamItem): number {
|
|
switch (item.kind) {
|
|
case "user_message":
|
|
return item.images && item.images.length > 0 ? 220 : 96;
|
|
case "assistant_message":
|
|
return 220;
|
|
case "tool_call":
|
|
return 136;
|
|
case "thought":
|
|
return 112;
|
|
case "todo_list":
|
|
return 144;
|
|
case "activity_log":
|
|
return 88;
|
|
case "compaction":
|
|
return 72;
|
|
default:
|
|
return 120;
|
|
}
|
|
}
|
|
|
|
export function findMountedWindowStart(input: {
|
|
items: StreamItem[];
|
|
minMountedCount: number;
|
|
}): number {
|
|
const { items, minMountedCount } = input;
|
|
if (items.length <= minMountedCount) {
|
|
return 0;
|
|
}
|
|
|
|
let startIndex = Math.max(items.length - minMountedCount, 0);
|
|
while (startIndex > 0 && items[startIndex]?.kind !== "user_message") {
|
|
startIndex -= 1;
|
|
}
|
|
return startIndex;
|
|
}
|
|
|
|
export function splitWebVirtualizedHistory(input: {
|
|
entries: IndexedStreamItem[];
|
|
minMountedCount: number;
|
|
}): WebVirtualizedHistoryWindow {
|
|
const startIndex = findMountedWindowStart({
|
|
items: input.entries.map((entry) => entry.item),
|
|
minMountedCount: input.minMountedCount,
|
|
});
|
|
return {
|
|
virtualizedEntries: input.entries.slice(0, startIndex),
|
|
mountedEntries: input.entries.slice(startIndex),
|
|
};
|
|
}
|