fix(frontend): Separate pause state from agent loading (#12041)

Co-authored-by: amanape <83104063+amanape@users.noreply.github.com>
This commit is contained in:
Mariam Saeed 2025-12-16 15:39:15 +02:00 committed by GitHub
parent 49740a463f
commit 3b7b2fd8cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 84 additions and 8 deletions

View File

@ -0,0 +1,71 @@
import { render, screen } from "@testing-library/react";
import { describe, it, expect, vi } from "vitest";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { MemoryRouter } from "react-router";
import { AgentStatus } from "#/components/features/controls/agent-status";
import { AgentState } from "#/types/agent-state";
import { useAgentState } from "#/hooks/use-agent-state";
import { useConversationStore } from "#/state/conversation-store";
vi.mock("#/hooks/use-agent-state");
vi.mock("#/hooks/use-conversation-id", () => ({
useConversationId: () => ({ conversationId: "test-id" }),
}));
const wrapper = ({ children }: { children: React.ReactNode }) => (
<MemoryRouter>
<QueryClientProvider client={new QueryClient()}>
{children}
</QueryClientProvider>
</MemoryRouter>
);
const renderAgentStatus = ({
isPausing = false,
}: { isPausing?: boolean } = {}) =>
render(
<AgentStatus
handleStop={vi.fn()}
handleResumeAgent={vi.fn()}
isPausing={isPausing}
/>,
{ wrapper },
);
describe("AgentStatus - isLoading logic", () => {
it("should show loading when curAgentState is INIT", () => {
vi.mocked(useAgentState).mockReturnValue({
curAgentState: AgentState.INIT,
});
renderAgentStatus();
expect(screen.getByTestId("agent-loading-spinner")).toBeInTheDocument();
});
it("should show loading when isPausing is true, even if shouldShownAgentLoading is false", () => {
vi.mocked(useAgentState).mockReturnValue({
curAgentState: AgentState.AWAITING_USER_INPUT,
});
renderAgentStatus({ isPausing: true });
expect(screen.getByTestId("agent-loading-spinner")).toBeInTheDocument();
});
it("should NOT update global shouldShownAgentLoading when only isPausing is true", () => {
vi.mocked(useAgentState).mockReturnValue({
curAgentState: AgentState.AWAITING_USER_INPUT,
});
renderAgentStatus({ isPausing: true });
// Loading spinner shows (because isPausing)
expect(screen.getByTestId("agent-loading-spinner")).toBeInTheDocument();
// But global state should be false (because shouldShownAgentLoading is false)
const { shouldShownAgentLoading } = useConversationStore.getState();
expect(shouldShownAgentLoading).toBe(false);
});
});

View File

@ -59,13 +59,15 @@ export function AgentStatus({
);
const shouldShownAgentLoading =
isPausing ||
curAgentState === AgentState.INIT ||
curAgentState === AgentState.LOADING ||
(webSocketStatus === "CONNECTING" && taskStatus !== "ERROR") ||
isTaskPolling(taskStatus) ||
isTaskPolling(subConversationTaskStatus);
// For UI rendering - includes pause state
const isLoading = shouldShownAgentLoading || isPausing;
const shouldShownAgentError =
curAgentState === AgentState.ERROR ||
curAgentState === AgentState.RATE_LIMITED ||
@ -93,25 +95,28 @@ export function AgentStatus({
<div
className={cn(
"bg-[#525252] box-border content-stretch flex flex-row gap-[3px] items-center justify-center overflow-clip px-0.5 py-1 relative rounded-[100px] shrink-0 size-6 transition-all duration-200 active:scale-95",
!shouldShownAgentLoading &&
!isLoading &&
(shouldShownAgentStop || shouldShownAgentResume) &&
"hover:bg-[#737373] cursor-pointer",
)}
>
{shouldShownAgentLoading && <AgentLoading />}
{!shouldShownAgentLoading && shouldShownAgentStop && (
{isLoading && <AgentLoading />}
{!isLoading && shouldShownAgentStop && (
<ChatStopButton handleStop={handleStop} />
)}
{!shouldShownAgentLoading && shouldShownAgentResume && (
{!isLoading && shouldShownAgentResume && (
<ChatResumeAgentButton
onAgentResumed={handleResumeAgent}
disabled={disabled}
/>
)}
{!shouldShownAgentLoading && shouldShownAgentError && (
<CircleErrorIcon className="w-4 h-4" />
{!isLoading && shouldShownAgentError && (
<CircleErrorIcon
className="w-4 h-4"
data-testid="circle-error-icon"
/>
)}
{!shouldShownAgentLoading &&
{!isLoading &&
!shouldShownAgentStop &&
!shouldShownAgentResume &&
!shouldShownAgentError && <ClockIcon className="w-4 h-4" />}