From 8588d7f63bf57e6285daafe035708cc22a99619c Mon Sep 17 00:00:00 2001 From: maria Date: Mon, 7 Sep 2026 22:40:40 -0300 Subject: [PATCH] fix(web): open proactive panels when entering threads (#10610) Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com> --- apps/web/src/components/ChatView.logic.test.ts | 16 ++++++++++------ apps/web/src/components/ChatView.logic.ts | 8 ++++---- apps/web/src/components/ChatView.tsx | 3 ++- apps/web/src/rightPanelStore.test.ts | 4 +++- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/apps/web/src/components/ChatView.logic.test.ts b/apps/web/src/components/ChatView.logic.test.ts index 51ced02334daf329b15936543cc4f157206192a8..b754c9408904b7a734ac4e287ffe345d211be337 100644 --- a/apps/web/src/components/ChatView.logic.test.ts +++ b/apps/web/src/components/ChatView.logic.test.ts @@ -190,7 +190,7 @@ describe("proactive panels", () => { expect(selectActiveRightPanelSurface(useRightPanelStore.getState().byThreadKey, ref)).toEqual( oldPr, ); - expect(shouldOpenProactivePullRequest(loaded.targetKey, "owner/repo:2")).toBe(false); + expect(shouldOpenProactivePullRequest(loaded.targetKey, "owner/repo:2")).toBe(true); expect( shouldOpenProactiveTurnDiff({ previousRunningTurnId: loaded.runningTurnId, @@ -198,7 +198,10 @@ describe("proactive panels", () => { settledTurnId: turnId, turnCompleted: true, }), - ).toBe(false); + ).toBe(true); + expect(panels.openProactive(ref, { id: "diff", kind: "diff" }, loaded.userActionRevision)).toBe( + false, + ); }); it.each(["idle", "loading", "observed"] as const)( @@ -245,8 +248,9 @@ describe("proactive panels", () => { }, ); - it("opens a pull request only after a newly observed link appears", () => { - expect(shouldOpenProactivePullRequest(undefined, "project:repo:42")).toBe(false); + it("opens an existing pull request on entry and follows newly observed links", () => { + expect(shouldOpenProactivePullRequest(undefined, "project:repo:42")).toBe(true); + expect(shouldOpenProactivePullRequest(undefined, null)).toBe(false); expect(shouldOpenProactivePullRequest(null, "project:repo:42")).toBe(true); expect(shouldOpenProactivePullRequest("project:repo:42", "project:repo:42")).toBe(false); expect(shouldOpenProactivePullRequest("project:repo:42", null)).toBe(false); @@ -286,7 +290,7 @@ describe("proactive panels", () => { ).toBe(false); }); - it("opens the diff only when the observed running turn settles", () => { + it("opens a completed diff on entry or when the observed running turn settles", () => { const turnId = TurnId.make("turn-1"); expect( shouldOpenProactiveTurnDiff({ @@ -295,7 +299,7 @@ describe("proactive panels", () => { settledTurnId: turnId, turnCompleted: true, }), - ).toBe(false); + ).toBe(true); expect( shouldOpenProactiveTurnDiff({ previousRunningTurnId: turnId, diff --git a/apps/web/src/components/ChatView.logic.ts b/apps/web/src/components/ChatView.logic.ts index b918a466ba13ba1d70c8fc9c9ddab3124b41595c..c251e8ffba321b26fba4cf53383b4a7db9315013 100644 --- a/apps/web/src/components/ChatView.logic.ts +++ b/apps/web/src/components/ChatView.logic.ts @@ -104,7 +104,7 @@ export function shouldOpenProactivePullRequest( previousTargetKey: string | null | undefined, targetKey: string | null, ): boolean { - return previousTargetKey !== undefined && targetKey !== null && targetKey !== previousTargetKey; + return targetKey !== null && targetKey !== previousTargetKey; } interface ProactivePanelObservation { @@ -158,11 +158,11 @@ export function shouldOpenProactiveTurnDiff(input: { turnCompleted: boolean; }): boolean { return ( - input.previousRunningTurnId !== undefined && - input.previousRunningTurnId !== null && input.runningTurnId === null && input.turnCompleted && - input.settledTurnId === input.previousRunningTurnId + input.settledTurnId !== null && + (input.previousRunningTurnId === undefined || + input.settledTurnId === input.previousRunningTurnId) ); } diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index ce69880b9756052ba5d3b9271e456451ec533060..49d6a6841b1debd01f74ed7010d51562e1ad24df 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -4095,7 +4095,8 @@ export default function ChatView(props: ChatViewProps) { const shouldDeferLink = eligibleLink && !pullRequestsCapabilityKnown; proactivePanelObservationRef.current = { ...observation, - runningTurnId: diffAction === "defer" ? (previousRunningTurnId ?? null) : activeRunningTurnId, + // Preserve first-entry eligibility while the checkpoint or repository is loading. + runningTurnId: diffAction === "defer" ? previousRunningTurnId : activeRunningTurnId, targetKey: shouldDeferLink ? (previousTargetKey ?? null) : linkedThreadPullRequestKey, }; diff --git a/apps/web/src/rightPanelStore.test.ts b/apps/web/src/rightPanelStore.test.ts index 46091d3fd41b83a97682728601cbcdbdaeeade01..dd205adc1e456fdc1841f6c4bbe0cd62205f2ab0 100644 --- a/apps/web/src/rightPanelStore.test.ts +++ b/apps/web/src/rightPanelStore.test.ts @@ -29,15 +29,17 @@ describe("rightPanelStore", () => { }); it.each(["diff-first", "pull-request-first"])( - "keeps the linked pull request above the completed diff with %s delivery", + "prioritizes the linked pull request over browser and diff with %s delivery", (order) => { const store = useRightPanelStore.getState(); + store.openBrowser(refA, "existing-browser"); const revision = store.getUserActionRevision(refA); const requests = order === "diff-first" ? [completedDiff, linkedPullRequest] : [linkedPullRequest, completedDiff]; for (const surface of requests) store.openProactive(refA, surface, revision); + store.reconcileBrowserSurfaces(refA, ["existing-browser", "agent-browser"]); expect( selectActiveRightPanelSurface(useRightPanelStore.getState().byThreadKey, refA), -- 2.54.0