From 4db264ea8ca26bb0e6eddac20604a68a627ae4bb Mon Sep 17 00:00:00 2001 From: Blomios Date: Mon, 24 Aug 2026 09:43:20 +0200 Subject: [PATCH] =?UTF-8?q?fix(custom-cli):=20cartes=20progress/tools=20vi?= =?UTF-8?q?sibles=20d=C3=A8s=20la=202e=20sollicitation=20malgr=C3=A9=20la?= =?UTF-8?q?=20r=C3=A9utilisation=20du=20progressId=20=E2=80=94=20la=20cl?= =?UTF-8?q?=C3=A9=20d'upsert=20borne=20le=20progressId=20au=20scope=20du?= =?UTF-8?q?=20tour=20au=20lieu=20d'un=20d=C3=A9dup=20global=20sur=20l'hist?= =?UTF-8?q?orique=20=E2=80=94=20#157=20(QA=20verte)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agents/CustomAgentChatView.test.tsx | 112 ++++++++++++++++++ .../features/agents/CustomAgentChatView.tsx | 2 +- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/frontend/src/features/agents/CustomAgentChatView.test.tsx b/frontend/src/features/agents/CustomAgentChatView.test.tsx index dce09046..458e7190 100644 --- a/frontend/src/features/agents/CustomAgentChatView.test.tsx +++ b/frontend/src/features/agents/CustomAgentChatView.test.tsx @@ -1764,6 +1764,118 @@ describe("CustomAgentChatView", () => { expect(screen.getAllByTestId("chat-tool-progress")).toHaveLength(2); }); + it("keeps second-turn progress visible when the provider reuses the same progressId across turns", async () => { + const harness = createStreamingAgentHarness(); + + render( + null) }, + } as unknown as Gateways} + > + + , + ); + + await waitFor(() => + expect(harness.agent.reattachAgentChat).toHaveBeenCalledWith( + "chat-session-1", + expect.any(Function), + ), + ); + + fireEvent.change(screen.getByLabelText(/message CLI custom/), { + target: { value: "first request" }, + }); + fireEvent.click(screen.getByRole("button", { name: "Envoyer" })); + await waitFor(() => expect(harness.emitterCount()).toBe(1)); + + act(() => { + harness.emit(0, { + kind: "progress", + progress: { + progressId: "codex:item:call_1", + source: "providerNative", + kind: "tool", + stage: "started", + label: "shell", + toolName: "shell", + text: "Running first request", + }, + }); + harness.emit(0, { + kind: "progress", + progress: { + progressId: "codex:item:call_1", + source: "providerNative", + kind: "tool", + stage: "completed", + label: "shell", + toolName: "shell", + text: "Done first request", + }, + }); + harness.emit(0, { kind: "final", content: "done first request" }); + }); + await screen.findByText("done first request"); + + fireEvent.change(screen.getByLabelText(/message CLI custom/), { + target: { value: "second request" }, + }); + fireEvent.click(screen.getByRole("button", { name: "Envoyer" })); + await waitFor(() => expect(harness.emitterCount()).toBe(2)); + + act(() => { + harness.emit(1, { + kind: "progress", + progress: { + progressId: "codex:item:call_1", + source: "providerNative", + kind: "tool", + stage: "started", + label: "shell", + toolName: "shell", + text: "Running second request", + }, + }); + }); + + expect(screen.getByText("Running second request")).toBeTruthy(); + + act(() => { + harness.emit(1, { + kind: "progress", + progress: { + progressId: "codex:item:call_1", + source: "providerNative", + kind: "tool", + stage: "completed", + label: "shell", + toolName: "shell", + text: "Done second request", + }, + }); + harness.emit(1, { kind: "final", content: "done second request" }); + }); + + await screen.findByText("done second request"); + expect(screen.getByText("Done first request")).toBeTruthy(); + expect(screen.getByText("Done second request")).toBeTruthy(); + expect(screen.getAllByTestId("chat-tool-progress")).toHaveLength(2); + }); + it("ignores a late first-turn progress chunk but still shows the real second-turn progress from the next callback", async () => { const harness = createStreamingAgentHarness(); diff --git a/frontend/src/features/agents/CustomAgentChatView.tsx b/frontend/src/features/agents/CustomAgentChatView.tsx index dc80bb9d..c7a0529b 100644 --- a/frontend/src/features/agents/CustomAgentChatView.tsx +++ b/frontend/src/features/agents/CustomAgentChatView.tsx @@ -325,7 +325,7 @@ function progressKey(progress: ReplyProgress): string { function progressUpsertKey(progress: ReplyProgress, scope: number): string { const progressId = progress.progressId?.trim(); - if (progressId) return progressId; + if (progressId) return `progress:${scope}:${progressId}`; return `legacy:${scope}:${progressDisplayKey(progress)}`; }