fix: local Agent Manager diff review parity (fullscreen + comments) (#6598)

* fix: add local-session fullscreen diff review parity in Agent Manager

* fix: remove redundant local check in review diff selection
This commit is contained in:
Marius
2026-03-05 14:13:05 +01:00
committed by GitHub
parent 1c23b4f772
commit 1bbae32c89
@@ -329,12 +329,12 @@ const AgentManagerContent: Component = () => {
const [diffLoading, setDiffLoading] = createSignal(false)
const [diffWidth, setDiffWidth] = createSignal(Math.round(window.innerWidth * 0.5))
// Full-screen review state (in-memory, per worktree)
const [reviewOpenByWorktree, setReviewOpenByWorktree] = createSignal<Record<string, boolean>>({})
const [reviewCommentsByWorktree, setReviewCommentsByWorktree] = createSignal<Record<string, ReviewComment[]>>({})
// Full-screen review state (in-memory, per sidebar context: local/worktree)
const [reviewOpenByContext, setReviewOpenByContext] = createSignal<Record<string, boolean>>({})
const [reviewCommentsByContext, setReviewCommentsByContext] = createSignal<Record<string, ReviewComment[]>>({})
const [reviewActive, setReviewActive] = createSignal(false)
const [reviewDiffStyle, setReviewDiffStyle] = createSignal<"unified" | "split">("unified")
// reviewOpen (memo below) controls tab presence for selected worktree.
// reviewOpen (memo below) controls tab presence for selected context.
// Per-worktree git stats (diff additions/deletions, commits missing from origin)
const [worktreeStats, setWorktreeStats] = createSignal<Record<string, WorktreeGitStats>>({})
@@ -358,33 +358,33 @@ const AgentManagerContent: Component = () => {
const reviewOpen = createMemo(() => {
const sel = selection()
if (!sel || sel === LOCAL) return false
return reviewOpenByWorktree()[sel] === true
if (sel === null) return false
return reviewOpenByContext()[sel] === true
})
const setReviewOpenForWorktree = (worktreeId: string, open: boolean) => {
setReviewOpenByWorktree((prev) => {
if (prev[worktreeId] === open) return prev
return { ...prev, [worktreeId]: open }
const setReviewOpenForContext = (context: string, open: boolean) => {
setReviewOpenByContext((prev) => {
if (prev[context] === open) return prev
return { ...prev, [context]: open }
})
}
const setReviewOpenForSelection = (open: boolean) => {
const sel = selection()
if (!sel || sel === LOCAL) return
setReviewOpenForWorktree(sel, open)
if (sel === null) return
setReviewOpenForContext(sel, open)
}
const reviewComments = createMemo(() => {
const sel = selection()
if (!sel || sel === LOCAL) return [] as ReviewComment[]
return reviewCommentsByWorktree()[sel] ?? []
if (sel === null) return [] as ReviewComment[]
return reviewCommentsByContext()[sel] ?? []
})
const setReviewCommentsForSelection = (comments: ReviewComment[]) => {
const sel = selection()
if (!sel || sel === LOCAL) return
setReviewCommentsByWorktree((prev) => ({ ...prev, [sel]: comments }))
if (sel === null) return
setReviewCommentsByContext((prev) => ({ ...prev, [sel]: comments }))
}
const applyStateForSelection = createMemo(() => {
@@ -633,14 +633,14 @@ const AgentManagerContent: Component = () => {
createEffect(() => {
const ids = new Set(worktrees().map((wt) => wt.id))
setReviewOpenByWorktree((prev) => {
const next = Object.fromEntries(Object.entries(prev).filter(([id]) => ids.has(id)))
setReviewOpenByContext((prev) => {
const next = Object.fromEntries(Object.entries(prev).filter(([id]) => id === LOCAL || ids.has(id)))
if (Object.keys(next).length === Object.keys(prev).length) return prev
return next
})
setReviewCommentsByWorktree((prev) => {
const next = Object.fromEntries(Object.entries(prev).filter(([id]) => ids.has(id)))
setReviewCommentsByContext((prev) => {
const next = Object.fromEntries(Object.entries(prev).filter(([id]) => id === LOCAL || ids.has(id)))
if (Object.keys(next).length === Object.keys(prev).length) return prev
return next
})
@@ -722,7 +722,7 @@ const AgentManagerContent: Component = () => {
createEffect(() => {
const sel = selection()
if (!sel || sel === LOCAL) {
if (sel === null) {
if (reviewActive()) setReviewActive(false)
return
}
@@ -903,6 +903,7 @@ const AgentManagerContent: Component = () => {
session.clearCurrentSession()
vscode.postMessage({ type: "agentManager.showExistingLocalTerminal" })
}
setReviewActive(remembered === REVIEW_TAB_ID && reviewOpenByContext()[LOCAL] === true)
}
const selectWorktree = (worktreeId: string) => {
@@ -919,7 +920,7 @@ const AgentManagerContent: Component = () => {
} else {
session.setCurrentSessionID(undefined)
}
setReviewActive(remembered === REVIEW_TAB_ID && reviewOpenByWorktree()[worktreeId] === true)
setReviewActive(remembered === REVIEW_TAB_ID && reviewOpenByContext()[worktreeId] === true)
}
onMount(() => {
@@ -1288,9 +1289,13 @@ const AgentManagerContent: Component = () => {
return
}
if (review) {
// Review tab is open but no specific session — try using any session in the worktree
const sel = selection()
if (sel && sel !== LOCAL) {
// Review tab is open but no specific session — use local sentinel for local,
// or any session in the selected worktree.
if (sel === LOCAL) {
vscode.postMessage({ type: "agentManager.startDiffWatch", sessionId: LOCAL })
return
}
if (sel) {
const managed = managedSessions().find((ms) => ms.worktreeId === sel)
if (managed) {
vscode.postMessage({ type: "agentManager.startDiffWatch", sessionId: managed.id })
@@ -1311,9 +1316,9 @@ const AgentManagerContent: Component = () => {
const openReviewTab = () => {
const sel = selection()
if (!sel || sel === LOCAL) return
if (sel === null) return
setDiffOpen(false)
setReviewOpenForWorktree(sel, true)
setReviewOpenForContext(sel, true)
setReviewActive(true)
}
@@ -1333,16 +1338,18 @@ const AgentManagerContent: Component = () => {
setReviewOpenForSelection(false)
}
// Data for the review tab: use current session's diff data, or first available for the worktree
// Data for the review tab: use local diff data for local context,
// current session for selected worktree context, or first available in that worktree.
const reviewDiffs = createMemo(() => {
const data = diffDatas()
const sel = selection()
const id = session.currentSessionID()
if (sel === LOCAL) return data[LOCAL] ?? []
if (id && data[id]) {
const current = managedSessions().find((s) => s.id === id)
if (sel && sel !== LOCAL && current?.worktreeId === sel) return data[id]!
if (sel && current?.worktreeId === sel) return data[id]!
}
if (!sel || sel === LOCAL) return []
if (!sel) return []
const ids = managedSessions()
.filter((s) => s.worktreeId === sel)
.map((s) => s.id)
@@ -1569,8 +1576,9 @@ const AgentManagerContent: Component = () => {
const tabIds = createMemo(() => {
const ids = activeTabs().map((s) => s.id)
const sel = selection()
if (!sel || sel === LOCAL) return ids
if (sel === null) return ids
const current = reviewOpen() ? [...ids, REVIEW_TAB_ID] : ids
if (sel === LOCAL) return current
return applyTabOrder(
current.map((id) => ({ id })),
worktreeTabOrder()[sel],
@@ -1588,7 +1596,12 @@ const AgentManagerContent: Component = () => {
if (typeof from !== "string" || typeof to !== "string") return
const sel = selection()
if (sel === LOCAL) {
setLocalSessionIDs((prev) => reorderTabs(prev, from, to) ?? prev)
setLocalSessionIDs((prev) => {
const ids = reviewOpen() ? [...prev, REVIEW_TAB_ID] : prev
const reordered = reorderTabs(ids, from, to)
if (!reordered) return prev
return reordered.filter((id) => id !== REVIEW_TAB_ID)
})
return
}
if (sel) {
@@ -2423,7 +2436,7 @@ const AgentManagerContent: Component = () => {
</>
)
})()}
<Show when={selection() !== LOCAL}>
<Show when={selection() !== null}>
<Tooltip value={t("command.review.toggle")} placement="bottom">
<IconButton
icon="expand"
@@ -2573,7 +2586,7 @@ const AgentManagerContent: Component = () => {
comments={reviewComments()}
onCommentsChange={setReviewCommentsForSelection}
onClose={() => setDiffOpen(false)}
onExpand={selection() !== LOCAL ? openReviewTab : undefined}
onExpand={selection() !== null ? openReviewTab : undefined}
onOpenFile={(file) => {
const id = session.currentSessionID()
if (id) vscode.postMessage({ type: "agentManager.openFile", sessionId: id, filePath: file })