feat(cli): historique de messages navigable haut/bas dans la CLI custom + contrôles de cellule visibles pendant busy — persistance localStorage du transcript custom (CustomAgentChatView), layering des contrôles sous l'overlay busy (LayoutGrid), bump pointeur IdeaSDK (docs plugin minimal + hot reload) (QA verte: 65 tests CustomAgentChatView, 25 tests LayoutGrid chat/layering, npm build frontend OK)

This commit is contained in:
2026-09-08 09:39:35 +02:00
parent 154728b828
commit fc3d124574
6 changed files with 350 additions and 48 deletions

View File

@ -64,6 +64,7 @@ import { LayoutGrid } from "./LayoutGrid";
interface GridSetup {
agentId: string;
otherAgentId: string;
bId: string;
gateways: Gateways;
layout: MockLayoutGateway;
@ -84,6 +85,10 @@ async function makeSplitAgentGrid(): Promise<GridSetup> {
name: "Worker",
profileId: "mock-claude",
});
const otherAgent = await agentGateway.createAgent("p1", {
name: "Reviewer",
profileId: "mock-claude",
});
const initial = await layout.loadLayout("p1");
const aId = leaves(initial)[0].id;
@ -102,6 +107,7 @@ async function makeSplitAgentGrid(): Promise<GridSetup> {
return {
agentId: agent.id,
otherAgentId: otherAgent.id,
bId: "b",
gateways: {
layout,
@ -206,7 +212,7 @@ describe("LayoutGrid — ticket #48 cell control layering", () => {
expect(controls.style.overflow).toBe("hidden");
});
it("does not render persistent cell chrome over the custom CLI surface (#249)", async () => {
it("keeps cell controls available over a busy custom CLI surface (#249)", async () => {
const setup = await makeSplitAgentGrid();
window.localStorage.setItem(`idea.agent-cell-mode.p1.${setup.bId}`, "custom");
setup.workState._setProjectWorkState("p1", {
@ -227,19 +233,47 @@ describe("LayoutGrid — ticket #48 cell control layering", () => {
const customToolbar = screen.getByRole("toolbar", {
name: "custom agent chat actions",
});
const mutate = vi.spyOn(setup.layout, "mutateLayout");
expect(customToolbar.className).toContain("z-20");
expect(screen.queryByLabelText(`agent selector ${setup.bId}`)).toBeNull();
expect(screen.queryByRole("group", {
expect(screen.getByLabelText(`agent selector ${setup.bId}`)).toBeTruthy();
expect(screen.getByRole("group", {
name: `mode CLI agent ${setup.bId}`,
})).toBeNull();
expect(screen.queryByLabelText(`split ${setup.bId} columns`)).toBeNull();
expect(screen.queryByLabelText(`split ${setup.bId} rows`)).toBeNull();
expect(screen.queryByLabelText(`close ${setup.bId}`)).toBeNull();
expect(screen.queryByRole("button", {
})).toBeTruthy();
expect(screen.getByLabelText(`split ${setup.bId} columns`)).toBeTruthy();
expect(screen.getByLabelText(`split ${setup.bId} rows`)).toBeTruthy();
expect(screen.getByLabelText(`close ${setup.bId}`)).toBeTruthy();
expect(screen.getByRole("button", {
name: `cancel current turn ${setup.bId}`,
})).toBeNull();
expect(screen.queryByText("Busy")).toBeNull();
})).toBeTruthy();
expect(screen.getByText("Busy")).toBeTruthy();
fireEvent.click(screen.getByLabelText(`split ${setup.bId} columns`));
await waitFor(() =>
expect(mutate).toHaveBeenCalledWith(
"p1",
expect.objectContaining({
type: "split",
target: setup.bId,
direction: "row",
}),
undefined,
),
);
const selector = screen.getByLabelText(`agent selector ${setup.bId}`);
fireEvent.change(selector, { target: { value: setup.otherAgentId } });
await waitFor(() =>
expect(mutate).toHaveBeenCalledWith(
"p1",
expect.objectContaining({
type: "setCellAgent",
target: setup.bId,
agent: setup.otherAgentId,
}),
undefined,
),
);
});
it("keeps busy Cancel above persistent cell controls and removes History (#151, #160)", async () => {