Fix duplicate Codex plan approval panels

This commit is contained in:
Mohamed Boudra
2026-05-01 11:42:30 +07:00
parent eee4a772d7
commit fa0af97aa6
7 changed files with 142 additions and 2 deletions
@@ -0,0 +1,63 @@
import { expect, test } from "./fixtures";
import { buildHostWorkspaceRoute } from "@/utils/host-routes";
import { allowPermission, waitForPermissionPrompt } from "./helpers/app";
import { connectTerminalClient } from "./helpers/terminal-perf";
import { createTempGitRepo } from "./helpers/workspace";
function getServerId(): string {
const serverId = process.env.E2E_SERVER_ID;
if (!serverId) {
throw new Error("E2E_SERVER_ID is not set.");
}
return serverId;
}
test.describe("Codex plan approval", () => {
test("shows a single actionable plan panel and removes it after implementation starts", async ({
page,
}) => {
test.setTimeout(180_000);
const repo = await createTempGitRepo("codex-plan-approval-");
const client = await connectTerminalClient();
try {
const workspaceResult = await client.openProject(repo.path);
if (!workspaceResult.workspace) {
throw new Error(workspaceResult.error ?? `Failed to open project ${repo.path}`);
}
const agent = await client.createAgent({
provider: "codex",
cwd: repo.path,
title: "Codex plan approval e2e",
model: "gpt-5.4-mini",
thinkingOptionId: "low",
featureValues: { plan_mode: true, fast_mode: true },
initialPrompt:
"Create a concise plan to add a README note. Present the plan only and wait for approval.",
});
const agentUrl = `${buildHostWorkspaceRoute(
getServerId(),
repo.path,
)}?open=${encodeURIComponent(`agent:${agent.id}`)}`;
await page.goto(agentUrl);
await waitForPermissionPrompt(page, 120_000);
await expect(page.getByTestId("permission-plan-card")).toHaveCount(1);
await expect(page.getByTestId("timeline-plan-card")).toHaveCount(0);
await allowPermission(page);
await expect(page.getByTestId("permission-plan-card")).toHaveCount(0, {
timeout: 30_000,
});
await expect(page.getByTestId("timeline-plan-card")).toHaveCount(0);
} finally {
await client.close();
await repo.cleanup();
}
});
});
@@ -24,6 +24,10 @@ export interface TerminalPerfDaemonClient {
cwd: string;
title?: string;
modeId?: string;
model?: string;
thinkingOptionId?: string;
featureValues?: Record<string, unknown>;
initialPrompt?: string;
}): Promise<{ id: string; status: string }>;
sendAgentMessage(agentId: string, text: string): Promise<void>;
subscribeTerminal(
@@ -1129,6 +1129,7 @@ function PermissionRequestCard({
description={description}
text={planMarkdown}
footer={footer}
testID="permission-plan-card"
disableOuterSpacing
/>
);
@@ -1141,7 +1142,12 @@ function PermissionRequestCard({
{description ? <Text style={permissionStyles.description}>{description}</Text> : null}
{planMarkdown ? (
<PlanCard title="Proposed plan" text={planMarkdown} disableOuterSpacing />
<PlanCard
title="Proposed plan"
text={planMarkdown}
testID="permission-plan-card"
disableOuterSpacing
/>
) : null}
{!isPlanRequest ? (
+1
View File
@@ -2973,6 +2973,7 @@ export const ToolCall = memo(function ToolCall({
<PlanCard
title="Plan"
text={effectiveDetail.text}
testID="timeline-plan-card"
disableOuterSpacing={disableOuterSpacing}
/>
);
+3 -1
View File
@@ -199,12 +199,14 @@ export function PlanCard({
text,
footer,
disableOuterSpacing = false,
testID,
}: {
title?: string;
description?: string;
text: string;
footer?: ReactNode;
disableOuterSpacing?: boolean;
testID?: string;
}) {
const { theme } = useUnistyles();
const markdownStyles = createMarkdownStyles(theme);
@@ -231,7 +233,7 @@ export function PlanCard({
);
return (
<View style={containerStyle}>
<View testID={testID} style={containerStyle}>
<Text style={titleStyle}>{title}</Text>
{description ? <Text style={descriptionStyle}>{description}</Text> : null}
<Markdown style={markdownStyles} rules={markdownRules}>