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");
}