fix(layout): retirer les affichages Busy et Cancel de la cellule agent au lancement sur une tâche — #277 (retrait badge Busy, bouton Cancel/interruptCurrentTurn et layer z turnActions; états inbox/tâches de fond et composer busy préservés; QA verte ré-exécutée: 25/25 tests LayoutGrid cellControlsLayering/chat)
This commit is contained in:
@ -243,10 +243,10 @@ describe("LayoutGrid — ticket #48 cell control layering", () => {
|
|||||||
expect(screen.getByLabelText(`split ${setup.bId} columns`)).toBeTruthy();
|
expect(screen.getByLabelText(`split ${setup.bId} columns`)).toBeTruthy();
|
||||||
expect(screen.getByLabelText(`split ${setup.bId} rows`)).toBeTruthy();
|
expect(screen.getByLabelText(`split ${setup.bId} rows`)).toBeTruthy();
|
||||||
expect(screen.getByLabelText(`close ${setup.bId}`)).toBeTruthy();
|
expect(screen.getByLabelText(`close ${setup.bId}`)).toBeTruthy();
|
||||||
expect(screen.getByRole("button", {
|
expect(screen.queryByRole("button", {
|
||||||
name: `cancel current turn ${setup.bId}`,
|
name: `cancel current turn ${setup.bId}`,
|
||||||
})).toBeTruthy();
|
})).toBeNull();
|
||||||
expect(screen.getByText("Busy")).toBeTruthy();
|
expect(screen.queryByText("Busy")).toBeNull();
|
||||||
|
|
||||||
fireEvent.click(screen.getByLabelText(`split ${setup.bId} columns`));
|
fireEvent.click(screen.getByLabelText(`split ${setup.bId} columns`));
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
@ -276,7 +276,7 @@ describe("LayoutGrid — ticket #48 cell control layering", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps busy Cancel above persistent cell controls and removes History (#151, #160)", async () => {
|
it("hides busy controls while keeping persistent cell controls and History removed (#277)", async () => {
|
||||||
const setup = await makeSplitAgentGrid();
|
const setup = await makeSplitAgentGrid();
|
||||||
await setup.layout.mutateLayout("p1", {
|
await setup.layout.mutateLayout("p1", {
|
||||||
type: "setCellConversation",
|
type: "setCellConversation",
|
||||||
@ -297,24 +297,13 @@ describe("LayoutGrid — ticket #48 cell control layering", () => {
|
|||||||
renderGrid(setup.gateways, { onOpenConversation: vi.fn() });
|
renderGrid(setup.gateways, { onOpenConversation: vi.fn() });
|
||||||
await flush();
|
await flush();
|
||||||
|
|
||||||
act(() => setup.system.emit(busy(setup.agentId, true)));
|
expect(screen.queryByRole("button", {
|
||||||
|
|
||||||
const cancel = await screen.findByRole("button", {
|
|
||||||
name: `cancel current turn ${setup.bId}`,
|
name: `cancel current turn ${setup.bId}`,
|
||||||
});
|
})).toBeNull();
|
||||||
const status = screen
|
expect(screen.queryByText("Busy")).toBeNull();
|
||||||
.getAllByRole("status")
|
|
||||||
.find((element) => element.textContent === "Busy") as HTMLElement;
|
|
||||||
const { controls } = controlsFor(setup.bId);
|
const { controls } = controlsFor(setup.bId);
|
||||||
|
|
||||||
expect(status).toBeTruthy();
|
expect(controls.style.zIndex).toBe("5");
|
||||||
expect(cancel.style.position).toBe("absolute");
|
|
||||||
expect(status.style.top).toBe("24px");
|
|
||||||
expect(status.style.zIndex).toBe("3");
|
|
||||||
expect(cancel.style.top).toBe("24px");
|
|
||||||
expect(cancel.style.right).toBe("20px");
|
|
||||||
expect(cancel.style.zIndex).toBe("6");
|
|
||||||
expect(Number(cancel.style.zIndex)).toBeGreaterThan(Number(controls.style.zIndex));
|
|
||||||
expect(screen.queryByRole("button", {
|
expect(screen.queryByRole("button", {
|
||||||
name: `open cell conversation ${setup.bId}`,
|
name: `open cell conversation ${setup.bId}`,
|
||||||
})).toBeNull();
|
})).toBeNull();
|
||||||
|
|||||||
@ -219,11 +219,11 @@ describe("LayoutGrid custom agent CLI (#147)", () => {
|
|||||||
|
|
||||||
expect(await screen.findByTestId("custom-agent-chat-view")).toBeTruthy();
|
expect(await screen.findByTestId("custom-agent-chat-view")).toBeTruthy();
|
||||||
expect(screen.queryByTestId("target-announcements-overlay")).toBeNull();
|
expect(screen.queryByTestId("target-announcements-overlay")).toBeNull();
|
||||||
expect(screen.getByText("Busy · Main")).toBeTruthy();
|
expect(screen.queryByText("Busy · Main")).toBeNull();
|
||||||
expect(screen.getByLabelText(`agent selector ${leaf.id}`)).toBeTruthy();
|
expect(screen.getByLabelText(`agent selector ${leaf.id}`)).toBeTruthy();
|
||||||
expect(screen.getByRole("button", {
|
expect(screen.queryByRole("button", {
|
||||||
name: `cancel current turn ${leaf.id}`,
|
name: `cancel current turn ${leaf.id}`,
|
||||||
})).toBeTruthy();
|
})).toBeNull();
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
expect(screen.getByLabelText(/message CLI custom/)).toHaveProperty(
|
expect(screen.getByLabelText(/message CLI custom/)).toHaveProperty(
|
||||||
"disabled",
|
"disabled",
|
||||||
|
|||||||
@ -395,7 +395,6 @@ function StoppedAgentCellPanel({
|
|||||||
* status/error 3 (in-cell status strip, launch-error banner, notices)
|
* status/error 3 (in-cell status strip, launch-error banner, notices)
|
||||||
* full-cell veils 4 (write-portal + F3 overlays; mutually exclusive)
|
* full-cell veils 4 (write-portal + F3 overlays; mutually exclusive)
|
||||||
* cell controls 5 (always on top and clickable)
|
* cell controls 5 (always on top and clickable)
|
||||||
* turn actions 6 (busy-state actions; Cancel must stay visible)
|
|
||||||
*
|
*
|
||||||
* The terminal/chat body must create its own z-index 0 stacking context. Custom
|
* The terminal/chat body must create its own z-index 0 stacking context. Custom
|
||||||
* CLI views can legitimately contain local high-z children (for example their
|
* CLI views can legitimately contain local high-z children (for example their
|
||||||
@ -405,7 +404,6 @@ const CELL_Z = {
|
|||||||
banner: 3,
|
banner: 3,
|
||||||
veil: 4,
|
veil: 4,
|
||||||
controls: 5,
|
controls: 5,
|
||||||
turnActions: 6,
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const CUSTOM_CHAT_COMPOSER_DEFAULT_HEIGHT = 64;
|
const CUSTOM_CHAT_COMPOSER_DEFAULT_HEIGHT = 64;
|
||||||
@ -446,7 +444,6 @@ function LeafView({
|
|||||||
const siblingIndex = parentSplit ? (parentSplit.index === 0 ? 1 : 0) : 0;
|
const siblingIndex = parentSplit ? (parentSplit.index === 0 ? 1 : 0) : 0;
|
||||||
const {
|
const {
|
||||||
agent: agentGateway,
|
agent: agentGateway,
|
||||||
input,
|
|
||||||
profile: profileGateway,
|
profile: profileGateway,
|
||||||
system,
|
system,
|
||||||
terminal,
|
terminal,
|
||||||
@ -812,16 +809,6 @@ function LeafView({
|
|||||||
}
|
}
|
||||||
}, [agentId, freshRestartedSession, liveAgents]);
|
}, [agentId, freshRestartedSession, liveAgents]);
|
||||||
|
|
||||||
async function interruptCurrentTurn(): Promise<void> {
|
|
||||||
if (!agentId || !input) return;
|
|
||||||
try {
|
|
||||||
await input.interrupt(projectId, agentId);
|
|
||||||
await refreshWorkState();
|
|
||||||
} catch (err) {
|
|
||||||
setBusyNotice({ message: describeNotice(err) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function requestMode(target: AgentCellMode): void {
|
function requestMode(target: AgentCellMode): void {
|
||||||
if (!effectiveCustomCliAvailable || target === cellMode) return;
|
if (!effectiveCustomCliAvailable || target === cellMode) return;
|
||||||
if (session) setPendingModeSwitch({ target });
|
if (session) setPendingModeSwitch({ target });
|
||||||
@ -1323,33 +1310,7 @@ function LeafView({
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{agentId && busyByWorkState && (
|
{agentId && (inboxDepth > 0 || completedBackgroundTasks.length > 0) && (
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
aria-label={`cancel current turn ${id}`}
|
|
||||||
title="Cancel current turn"
|
|
||||||
onClick={() => void interruptCurrentTurn()}
|
|
||||||
disabled={!input}
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
top: 24,
|
|
||||||
right: 20,
|
|
||||||
zIndex: CELL_Z.turnActions,
|
|
||||||
flexShrink: 0,
|
|
||||||
border: "1px solid var(--color-danger, #d45a5a)",
|
|
||||||
borderRadius: 3,
|
|
||||||
background: "var(--color-surface, #1e1e1e)",
|
|
||||||
color: "var(--color-danger, #d45a5a)",
|
|
||||||
cursor: input ? "pointer" : "default",
|
|
||||||
fontSize: 11,
|
|
||||||
padding: "1px 6px",
|
|
||||||
pointerEvents: "auto",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
{agentId && (busyByWorkState || inboxDepth > 0 || completedBackgroundTasks.length > 0) && (
|
|
||||||
<div
|
<div
|
||||||
role="status"
|
role="status"
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
@ -1357,38 +1318,15 @@ function LeafView({
|
|||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: 24,
|
top: 24,
|
||||||
left: 4,
|
left: 4,
|
||||||
right: busyByWorkState ? 76 : undefined,
|
|
||||||
zIndex: CELL_Z.banner,
|
zIndex: CELL_Z.banner,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
maxWidth: busyByWorkState ? undefined : "calc(100% - 8px)",
|
maxWidth: "calc(100% - 8px)",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: 4,
|
gap: 4,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{busyByWorkState && (
|
|
||||||
<span
|
|
||||||
title={delegatedTicket?.requesterLabel ?? activeTicket?.taskPreview}
|
|
||||||
style={{
|
|
||||||
maxWidth: 180,
|
|
||||||
overflow: "hidden",
|
|
||||||
textOverflow: "ellipsis",
|
|
||||||
whiteSpace: "nowrap",
|
|
||||||
border: "1px solid var(--color-warning, #d49b3a)",
|
|
||||||
borderRadius: 3,
|
|
||||||
background: "rgba(212, 155, 58, 0.16)",
|
|
||||||
color: "var(--color-warning, #d49b3a)",
|
|
||||||
padding: "1px 6px",
|
|
||||||
fontSize: 11,
|
|
||||||
fontWeight: 600,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{delegatedTicket
|
|
||||||
? `Busy · ${delegatedTicket.requesterLabel}`
|
|
||||||
: "Busy"}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{!busyByWorkState && inboxDepth > 0 && (
|
{!busyByWorkState && inboxDepth > 0 && (
|
||||||
<span
|
<span
|
||||||
title={`${inboxDepth} pending message${inboxDepth === 1 ? "" : "s"}`}
|
title={`${inboxDepth} pending message${inboxDepth === 1 ? "" : "s"}`}
|
||||||
|
|||||||
Reference in New Issue
Block a user