diff --git a/packages/ui/src/features/code-review/components/CommentAnnotation.test.tsx b/packages/ui/src/features/code-review/components/CommentAnnotation.test.tsx new file mode 100644 index 0000000000..464083677f --- /dev/null +++ b/packages/ui/src/features/code-review/components/CommentAnnotation.test.tsx @@ -0,0 +1,50 @@ +import { Theme } from "@radix-ui/themes"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { useReviewDraftsStore } from "../reviewDraftsStore"; +import { CommentAnnotation } from "./CommentAnnotation"; + +const { sendPromptToAgent } = vi.hoisted(() => ({ + sendPromptToAgent: vi.fn(), +})); + +vi.mock("../../sessions/sendPromptToAgent", () => ({ sendPromptToAgent })); + +describe("CommentAnnotation", () => { + beforeEach(() => { + vi.clearAllMocks(); + useReviewDraftsStore.setState({ drafts: {}, batchEnabled: {} }); + }); + + it("keeps expanded review open when sending an inline comment", async () => { + const user = userEvent.setup(); + const onDismiss = vi.fn(); + + render( + + + , + ); + + await user.type( + screen.getByPlaceholderText("Describe the changes you'd like..."), + "Use the shared helper", + ); + await user.click(screen.getByRole("button", { name: "Submit" })); + + expect(sendPromptToAgent).toHaveBeenCalledWith( + "task-1", + expect.stringContaining("Use the shared helper"), + { keepReviewExpanded: true }, + ); + expect(onDismiss).toHaveBeenCalledOnce(); + }); +}); diff --git a/packages/ui/src/features/code-review/components/CommentAnnotation.tsx b/packages/ui/src/features/code-review/components/CommentAnnotation.tsx index b1daf5d772..d328befc33 100644 --- a/packages/ui/src/features/code-review/components/CommentAnnotation.tsx +++ b/packages/ui/src/features/code-review/components/CommentAnnotation.tsx @@ -110,6 +110,7 @@ export function CommentAnnotation({ sendPromptToAgent( taskId, buildInlineCommentPrompt(filePath, startLine, endLine, side, text), + { keepReviewExpanded: true }, ); }, [ taskId, diff --git a/packages/ui/src/features/code-review/components/PendingReviewBar.test.tsx b/packages/ui/src/features/code-review/components/PendingReviewBar.test.tsx new file mode 100644 index 0000000000..3310021424 --- /dev/null +++ b/packages/ui/src/features/code-review/components/PendingReviewBar.test.tsx @@ -0,0 +1,54 @@ +import { Theme } from "@radix-ui/themes"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { useReviewDraftsStore } from "../reviewDraftsStore"; +import { PendingReviewBar } from "./PendingReviewBar"; + +const { sendPromptToAgent } = vi.hoisted(() => ({ + sendPromptToAgent: vi.fn(), +})); + +vi.mock("../../sessions/sendPromptToAgent", () => ({ sendPromptToAgent })); + +describe("PendingReviewBar", () => { + beforeEach(() => { + vi.clearAllMocks(); + useReviewDraftsStore.setState({ + drafts: { + "task-1": [ + { + id: "draft-1", + taskId: "task-1", + filePath: "src/example.ts", + startLine: 8, + endLine: 10, + side: "additions", + text: "Use the shared helper", + createdAt: 1, + }, + ], + }, + batchEnabled: { "task-1": true }, + }); + }); + + it("keeps expanded review open when sending batched comments", async () => { + const user = userEvent.setup(); + + render( + + + , + ); + + await user.click(screen.getByRole("button", { name: "Send to agent" })); + + expect(sendPromptToAgent).toHaveBeenCalledWith( + "task-1", + expect.stringContaining("Use the shared helper"), + { keepReviewExpanded: true }, + ); + expect(useReviewDraftsStore.getState().getDraftCount("task-1")).toBe(0); + }); +}); diff --git a/packages/ui/src/features/code-review/components/PendingReviewBar.tsx b/packages/ui/src/features/code-review/components/PendingReviewBar.tsx index 104480c07a..c2951b35fa 100644 --- a/packages/ui/src/features/code-review/components/PendingReviewBar.tsx +++ b/packages/ui/src/features/code-review/components/PendingReviewBar.tsx @@ -18,7 +18,7 @@ export function PendingReviewBar({ taskId }: PendingReviewBarProps) { const handleSend = () => { const prompt = buildBatchedInlineCommentsPrompt(drafts); if (!prompt) return; - sendPromptToAgent(taskId, prompt); + sendPromptToAgent(taskId, prompt, { keepReviewExpanded: true }); clearDrafts(taskId); }; diff --git a/packages/ui/src/features/code-review/components/PrCommentThread.test.tsx b/packages/ui/src/features/code-review/components/PrCommentThread.test.tsx index 7f14fe2ee9..1142e061c4 100644 --- a/packages/ui/src/features/code-review/components/PrCommentThread.test.tsx +++ b/packages/ui/src/features/code-review/components/PrCommentThread.test.tsx @@ -80,10 +80,12 @@ describe("PrCommentThread", () => { expect(sendPromptToAgent).toHaveBeenCalledWith( "task-1", expect.stringContaining("Could this use the shared helper?"), + { keepReviewExpanded: true }, ); expect(sendPromptToAgent).toHaveBeenCalledWith( "task-1", expect.stringContaining("Check whether this helper already exists"), + { keepReviewExpanded: true }, ); await waitFor(() => expect( diff --git a/packages/ui/src/features/code-review/components/PrCommentThread.tsx b/packages/ui/src/features/code-review/components/PrCommentThread.tsx index 3addfc943c..936230b998 100644 --- a/packages/ui/src/features/code-review/components/PrCommentThread.tsx +++ b/packages/ui/src/features/code-review/components/PrCommentThread.tsx @@ -347,6 +347,7 @@ export function PrCommentThread({ const success = await sendPromptToAgent( taskId, buildChatAboutPrCommentPrompt(filePath, endLine, side, comments, text), + { keepReviewExpanded: true }, ); setIsSendingChat(false); if (success) { diff --git a/packages/ui/src/features/sessions/sendPromptToAgent.test.ts b/packages/ui/src/features/sessions/sendPromptToAgent.test.ts index 7b6c070dd7..8e95c8d185 100644 --- a/packages/ui/src/features/sessions/sendPromptToAgent.test.ts +++ b/packages/ui/src/features/sessions/sendPromptToAgent.test.ts @@ -105,4 +105,19 @@ describe("sendPromptToAgent", () => { ); }, ); + + it("keeps expanded review open when requested", () => { + mockSender.mockResolvedValueOnce(undefined); + reviewState.mode = "expanded"; + panelState.taskLayouts = { "task-1": { panelTree: {} } }; + + sendPromptToAgent("task-1", "hello", { keepReviewExpanded: true }); + + expect(reviewState.setReviewMode).not.toHaveBeenCalled(); + expect(panelState.setActiveTab).toHaveBeenCalledWith( + "task-1", + "panel-logs", + DEFAULT_TAB_IDS.LOGS, + ); + }); }); diff --git a/packages/ui/src/features/sessions/sendPromptToAgent.ts b/packages/ui/src/features/sessions/sendPromptToAgent.ts index 907bd1f2b1..a05cba85b2 100644 --- a/packages/ui/src/features/sessions/sendPromptToAgent.ts +++ b/packages/ui/src/features/sessions/sendPromptToAgent.ts @@ -10,13 +10,14 @@ import { type AgentPromptSender, } from "./agentPromptSender"; -/** - * Sends a prompt to the agent session for a task, collapses the review - * panel to split mode if expanded, and switches to the logs/chat tab. - */ +interface SendPromptToAgentOptions { + keepReviewExpanded?: boolean; +} + export function sendPromptToAgent( taskId: string, prompt: string | ContentBlock[], + options: SendPromptToAgentOptions = {}, ): Promise { const sendPromise = resolveService(AGENT_PROMPT_SENDER)( taskId, @@ -33,7 +34,7 @@ export function sendPromptToAgent( }); const { getReviewMode, setReviewMode } = useReviewNavigationStore.getState(); - if (getReviewMode(taskId) === "expanded") { + if (!options.keepReviewExpanded && getReviewMode(taskId) === "expanded") { setReviewMode(taskId, "split"); }