Fix bottom anchoring and Claude wake routing
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
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),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user