Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,20 @@ export const EditorGroup: React.FC<EditorGroupProps> = ({
}
}, [group.activeTabId, group.tabs, isKeepAliveTerminalTab]);

// Fast lookup set for cached tabs
const cachedTabs = cachedTabsRef.current;

// Tabs to render (active + cached). Hidden terminal tabs stay mounted so
// reopening a terminal reuses the xterm buffer instead of replaying history.
// Child-session tabs retain only their lightweight wrapper; that wrapper
// unmounts its transcript while inactive and owns reading state until close.
const tabsToRender = useMemo(() => {
const result = group.tabs.filter(t =>
(!t.isHidden && isCanvasTabVisibleForSession(t, activeSessionId) && (t.content.type === 'btw-session' || t.id === effectiveActiveTabId || cachedTabsRef.current.has(t.id))) ||
(!t.isHidden && isCanvasTabVisibleForSession(t, activeSessionId) && (t.content.type === 'btw-session' || t.id === effectiveActiveTabId || cachedTabs.has(t.id))) ||
(t.isHidden && isKeepAliveTerminalTab(t))
);
return result;
}, [group.tabs, effectiveActiveTabId, activeSessionId, isKeepAliveTerminalTab]);
}, [group.tabs, effectiveActiveTabId, activeSessionId, isKeepAliveTerminalTab, cachedTabs]);

const handleContentChange = useCallback((content: PanelContent | null) => {
if (content && group.activeTabId) {
Expand Down
10 changes: 9 additions & 1 deletion src/web-ui/src/app/scenes/settings/SettingsNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,18 @@ function resolvePhrases(i18n: I18nApi, phrases: readonly SettingsSearchPhrase[])
return parts.join(' ');
}

const searchIndexCache = new WeakMap<I18nApi, SettingsSearchRow[]>();

function buildSettingsSearchIndex(t: SettingsT, i18n: I18nApi): SettingsSearchRow[] {
const cached = searchIndexCache.get(i18n);
if (cached) return cached;

const categoryLabels = new Map(SETTINGS_CATEGORIES.map((category) => [
category.id,
translateString(t, category.labelKey, category.id),
]));

return SETTINGS_PAGE_MANIFESTS.flatMap((page) => {
const rows = SETTINGS_PAGE_MANIFESTS.flatMap((page) => {
const categoryLabel = categoryLabels.get(page.categoryId) ?? page.categoryId;
const pageLabel = translateString(t, page.labelKey, page.id);
const description = translateString(t, page.descriptionKey, '');
Expand Down Expand Up @@ -106,6 +111,9 @@ function buildSettingsSearchIndex(t: SettingsT, i18n: I18nApi): SettingsSearchRo
}),
];
});

searchIndexCache.set(i18n, rows);
return rows;
}

function highlightFirstMatch(text: string, query: string): React.ReactNode {
Expand Down
10 changes: 9 additions & 1 deletion src/web-ui/src/flow_chat/components/btw/BtwSessionPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,15 @@ const BtwSessionPanelContent: React.FC<BtwSessionPanelProps & { viewState: BtwPa
? t(resolveSubagentNameKey(childSessionId ?? ''))
: displayTitle?.trim() || resolveSessionTitle(childSession, childTitleFallback);
const headerModelName = childKind === 'subagent' ? childSession?.config?.modelName?.trim() : undefined;
const [projectSession] = useState(createSessionVirtualItemProjector);
const projectSession = useMemo(
() => {
if (!viewState.projectSession) {
viewState.projectSession = createSessionVirtualItemProjector();
}
return viewState.projectSession;
},
[viewState],
);
const sessionVirtualItems = useMemo(
() => projectSession(childSession ?? null),
[childSession, projectSession],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface BtwPanelViewState {
expandedToolCapsules?: ReadonlySet<string>;
restoredReviewLocation?: string;
restoring: boolean;
projectSession?: (session: any) => any;
}

export function createBtwPanelViewState(): BtwPanelViewState {
Expand Down
Loading