Skip to content

Commit 08df25f

Browse files
committed
fix: dedupe restored agent panes
1 parent 71d1e82 commit 08df25f

1 file changed

Lines changed: 66 additions & 17 deletions

File tree

src/state/workbench.ts

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,23 @@ const collectLeafPaneIds = (node: SessionPaneNode | undefined | null): string[]
304304
return [...collectLeafPaneIds(node.first), ...collectLeafPaneIds(node.second)];
305305
};
306306

307+
const collectLeafSessionIds = (node: SessionPaneNode | undefined | null): string[] => {
308+
if (!node) return [];
309+
if (node.type === "leaf") return [node.sessionId];
310+
return [...collectLeafSessionIds(node.first), ...collectLeafSessionIds(node.second)];
311+
};
312+
313+
const findPaneIdForSessionId = (
314+
node: SessionPaneNode | undefined | null,
315+
sessionId: string,
316+
): string | undefined => {
317+
if (!node) return undefined;
318+
if (node.type === "leaf") {
319+
return node.sessionId === sessionId ? node.id : undefined;
320+
}
321+
return findPaneIdForSessionId(node.first, sessionId) ?? findPaneIdForSessionId(node.second, sessionId);
322+
};
323+
307324
const sanitizePaneLayout = (
308325
node: SessionPaneNode | undefined | null,
309326
fallbackSessionId: string
@@ -330,6 +347,40 @@ const sanitizePaneLayout = (
330347
};
331348
};
332349

350+
const prunePaneLayout = (
351+
node: SessionPaneNode | undefined | null,
352+
validSessionIds: Set<string>,
353+
seenSessionIds: Set<string>,
354+
): SessionPaneNode | null => {
355+
if (!node) return null;
356+
357+
if (node.type === "leaf") {
358+
if (!validSessionIds.has(node.sessionId) || seenSessionIds.has(node.sessionId)) {
359+
return null;
360+
}
361+
seenSessionIds.add(node.sessionId);
362+
return {
363+
type: "leaf",
364+
id: node.id || createId("pane"),
365+
sessionId: node.sessionId,
366+
};
367+
}
368+
369+
const first = prunePaneLayout(node.first, validSessionIds, seenSessionIds);
370+
const second = prunePaneLayout(node.second, validSessionIds, seenSessionIds);
371+
if (!first && !second) return null;
372+
if (!first) return second;
373+
if (!second) return first;
374+
return {
375+
type: "split",
376+
id: node.id || createId("split"),
377+
axis: node.axis === "vertical" ? "vertical" : "horizontal",
378+
ratio: Number.isFinite(node.ratio) ? Math.min(1, Math.max(0, node.ratio)) : 0.5,
379+
first,
380+
second,
381+
};
382+
};
383+
333384
const sanitizeTabSessions = (tab: Tab, locale: Locale): Tab => {
334385
const allSessions = (tab.sessions ?? []).filter(Boolean);
335386
const persistedSessions = allSessions.filter((session) => !session.isDraft);
@@ -340,24 +391,22 @@ const sanitizeTabSessions = (tab: Tab, locale: Locale): Tab => {
340391
: fallbackSessions[0].id;
341392
const validSessionIds = new Set(fallbackSessions.map((session) => session.id));
342393
const sanitizedLayout = sanitizePaneLayout(tab.paneLayout, activeSessionId);
343-
const normalizedLayout = (() => {
344-
const visit = (node: SessionPaneNode): SessionPaneNode => {
345-
if (node.type === "leaf") {
346-
return {
347-
...node,
348-
sessionId: validSessionIds.has(node.sessionId) ? node.sessionId : activeSessionId
349-
};
350-
}
351-
return {
352-
...node,
353-
first: visit(node.first),
354-
second: visit(node.second)
355-
};
356-
};
357-
return visit(sanitizedLayout);
358-
})();
394+
const normalizedBaseLayout = prunePaneLayout(sanitizedLayout, validSessionIds, new Set()) ?? createPaneLayout(activeSessionId);
395+
const coveredSessionIds = new Set(collectLeafSessionIds(normalizedBaseLayout));
396+
const missingSessionIds = fallbackSessions
397+
.map((session) => session.id)
398+
.filter((sessionId) => !coveredSessionIds.has(sessionId));
399+
const normalizedLayout = missingSessionIds.reduce<SessionPaneNode>((layout, sessionId) => ({
400+
type: "split",
401+
id: createId("split"),
402+
axis: "vertical",
403+
ratio: 0.5,
404+
first: layout,
405+
second: createPaneLeaf(sessionId),
406+
}), normalizedBaseLayout);
359407
const leafIds = collectLeafPaneIds(normalizedLayout);
360-
const activePaneId = leafIds.includes(tab.activePaneId) ? tab.activePaneId : leafIds[0];
408+
const activePaneId = findPaneIdForSessionId(normalizedLayout, activeSessionId)
409+
?? (leafIds.includes(tab.activePaneId) ? tab.activePaneId : leafIds[0]);
361410

362411
return {
363412
...tab,

0 commit comments

Comments
 (0)