fix(frontend): persistance immédiate de l'historique des prompts à chaque envoi — #323 (QA verte)
Symptôme: l'historique du composer CLI custom (flèche haut) n'était écrit dans localStorage qu'via un effet sur l'état, sans garantie au moment de l'envoi — une fermeture brutale/crash perdait la dernière entrée. - writeComposerHistory retourne désormais le succès de l'écriture; à chaque envoi, l'entrée est ajoutée et écrite AVANT l'invocation de l'agent (source de vérité par ref + état, réinit de l'index de navigation et du brouillon d'historique) - l'effet d'écriture global est supprimé: l'historique n'est plus réécrit en boucle, seulement aux envois (et lectures au changement de scope projet/layout/node) - si l'écriture échoue, l'envoi part quand même et un avertissement discret « Historique des prompts non sauvegardé. » (role=status) s'affiche au-dessus du composer - tests: persistance vérifiée au moment de l'appel sendAgentChat, envoi conservé + avertissement affiché quand localStorage échoue QA verte sur fix/batch-322-323-session-restore-prompt-history. Aucun push.
This commit is contained in:
@ -864,6 +864,66 @@ describe("CustomAgentChatView", () => {
|
||||
await waitFor(() => expect(composer.value).toBe("remember me"));
|
||||
});
|
||||
|
||||
it("persists an accepted text prompt before invoking the agent", async () => {
|
||||
const historyKey = "idea.custom-chat-history.project-1.layout-1.node-1.agent-1";
|
||||
let historyAtSend: string[] = [];
|
||||
const agent = {
|
||||
launchAgentChat: vi.fn(),
|
||||
reattachAgentChat: vi.fn(async (sessionId: string) => ({ sessionId, scrollback: [] })),
|
||||
sendAgentChat: vi.fn(
|
||||
async (_sessionId: string, _prompt: string, onChunk: (chunk: ReplyChunk) => void) => {
|
||||
historyAtSend = JSON.parse(window.localStorage.getItem(historyKey) ?? "[]");
|
||||
onChunk({ kind: "final", content: "done" });
|
||||
},
|
||||
),
|
||||
cancelAgentChat: vi.fn(async () => {}),
|
||||
closeAgentChat: vi.fn(async () => {}),
|
||||
};
|
||||
render(
|
||||
<DIProvider gateways={{ agent, system: { pickFile: vi.fn(async () => null) } } as unknown as Gateways}>
|
||||
<CustomAgentChatView
|
||||
projectId="project-1"
|
||||
agentId="agent-1"
|
||||
agentName="Worker"
|
||||
profile={profile}
|
||||
cwd="/repo"
|
||||
layoutId="layout-1"
|
||||
nodeId="node-1"
|
||||
sessionId="chat-session-1"
|
||||
conversationId="conversation-1"
|
||||
onSessionId={vi.fn()}
|
||||
onConversationId={vi.fn()}
|
||||
/>
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
const composer = await screen.findByLabelText(/message CLI custom/);
|
||||
fireEvent.change(composer, { target: { value: "persist before send" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
|
||||
await waitFor(() => expect(agent.sendAgentChat).toHaveBeenCalledOnce());
|
||||
expect(historyAtSend).toEqual(["persist before send"]);
|
||||
});
|
||||
|
||||
it("keeps sending when prompt-history persistence fails and reports it discreetly", async () => {
|
||||
const setItem = vi.spyOn(Storage.prototype, "setItem").mockImplementation(() => {
|
||||
throw new Error("storage unavailable");
|
||||
});
|
||||
try {
|
||||
const agent = renderHistoryChat();
|
||||
const composer = await screen.findByLabelText(/message CLI custom/);
|
||||
fireEvent.change(composer, { target: { value: "still send" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: "Envoyer" }));
|
||||
|
||||
await waitFor(() => expect(agent.sendAgentChat).toHaveBeenCalledOnce());
|
||||
expect(screen.getByRole("status").textContent).toContain(
|
||||
"Historique des prompts non sauvegardé.",
|
||||
);
|
||||
} finally {
|
||||
setItem.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("repaints attachment labels from user prompt scrollback", async () => {
|
||||
const agent = {
|
||||
launchAgentChat: vi.fn(),
|
||||
|
||||
Reference in New Issue
Block a user