fix(frontend): Consider start task job error status for loading indicators (#11670)

This commit is contained in:
sp.wack
2025-11-07 19:24:29 +04:00
committed by GitHub
parent 1e3f1de773
commit 7acee16de5
3 changed files with 55 additions and 6 deletions

View File

@@ -1,5 +1,5 @@
import { describe, it, expect } from "vitest";
import { getStatusCode, getIndicatorColor, IndicatorColor } from "../status";
import { getStatusCode, getIndicatorColor, IndicatorColor } from "#/utils/status";
import { AgentState } from "#/types/agent-state";
import { I18nKey } from "#/i18n/declaration";
@@ -87,6 +87,36 @@ describe("getStatusCode", () => {
// Should return runtime status since no agent state
expect(result).toBe("STATUS$STARTING_RUNTIME");
});
it("should prioritize task ERROR status over websocket CONNECTING state", () => {
// Test case: Task has errored but websocket is still trying to connect
const result = getStatusCode(
{ id: "", message: "", type: "info", status_update: true }, // statusMessage
"CONNECTING", // webSocketStatus (stuck connecting)
null, // conversationStatus
null, // runtimeStatus
AgentState.LOADING, // agentState
"ERROR", // taskStatus (ERROR)
);
// Should return error message, not "Connecting..."
expect(result).toBe(I18nKey.AGENT_STATUS$ERROR_OCCURRED);
});
it("should show Connecting when task is working and websocket is connecting", () => {
// Test case: Task is in progress and websocket is connecting normally
const result = getStatusCode(
{ id: "", message: "", type: "info", status_update: true }, // statusMessage
"CONNECTING", // webSocketStatus
null, // conversationStatus
null, // runtimeStatus
AgentState.LOADING, // agentState
"WORKING", // taskStatus (in progress)
);
// Should show connecting message since task hasn't errored
expect(result).toBe(I18nKey.CHAT_INTERFACE$CONNECTING);
});
});
describe("getIndicatorColor", () => {

View File

@@ -13,6 +13,7 @@ import { useConversationStore } from "#/state/conversation-store";
import CircleErrorIcon from "#/icons/circle-error.svg?react";
import { useAgentState } from "#/hooks/use-agent-state";
import { useUnifiedWebSocketStatus } from "#/hooks/use-unified-websocket-status";
import { useTaskPolling } from "#/hooks/query/use-task-polling";
export interface AgentStatusProps {
className?: string;
@@ -35,6 +36,7 @@ export function AgentStatus({
const { curStatusMessage } = useStatusStore();
const webSocketStatus = useUnifiedWebSocketStatus();
const { data: conversation } = useActiveConversation();
const { taskStatus } = useTaskPolling();
const statusCode = getStatusCode(
curStatusMessage,
@@ -42,17 +44,24 @@ export function AgentStatus({
conversation?.status || null,
conversation?.runtime_status || null,
curAgentState,
taskStatus,
);
const isTaskLoading =
taskStatus && taskStatus !== "ERROR" && taskStatus !== "READY";
const shouldShownAgentLoading =
isPausing ||
curAgentState === AgentState.INIT ||
curAgentState === AgentState.LOADING ||
webSocketStatus === "CONNECTING";
(webSocketStatus === "CONNECTING" && taskStatus !== "ERROR") ||
isTaskLoading;
const shouldShownAgentError =
curAgentState === AgentState.ERROR ||
curAgentState === AgentState.RATE_LIMITED;
curAgentState === AgentState.RATE_LIMITED ||
webSocketStatus === "DISCONNECTED" ||
taskStatus === "ERROR";
const shouldShownAgentStop = curAgentState === AgentState.RUNNING;
@@ -61,7 +70,8 @@ export function AgentStatus({
// Update global state when agent loading condition changes
useEffect(() => {
setShouldShownAgentLoading(shouldShownAgentLoading);
if (shouldShownAgentLoading)
setShouldShownAgentLoading(shouldShownAgentLoading);
}, [shouldShownAgentLoading, setShouldShownAgentLoading]);
return (

View File

@@ -4,6 +4,7 @@ import { AgentState } from "#/types/agent-state";
import { ConversationStatus } from "#/types/conversation-status";
import { StatusMessage } from "#/types/message";
import { RuntimeStatus } from "#/types/runtime-status";
import { V1AppConversationStartTaskStatus } from "#/api/conversation-service/v1-conversation-service.types";
export enum IndicatorColor {
BLUE = "bg-blue-500",
@@ -103,8 +104,15 @@ export function getStatusCode(
conversationStatus: ConversationStatus | null,
runtimeStatus: RuntimeStatus | null,
agentState: AgentState | null,
taskStatus?: V1AppConversationStartTaskStatus | null,
) {
// Handle conversation and runtime stopped states
// PRIORITY 1: Handle task error state (when start-tasks API returns ERROR)
// This must come first to prevent "Connecting..." from showing when task has errored
if (taskStatus === "ERROR") {
return I18nKey.AGENT_STATUS$ERROR_OCCURRED;
}
// PRIORITY 2: Handle conversation and runtime stopped states
if (conversationStatus === "STOPPED" || runtimeStatus === "STATUS$STOPPED") {
return I18nKey.CHAT_INTERFACE$STOPPED;
}
@@ -134,7 +142,8 @@ export function getStatusCode(
return runtimeStatus;
}
// Handle WebSocket connection states
// PRIORITY 3: Handle WebSocket connection states
// Note: WebSocket may be stuck in CONNECTING when task errors, so we check taskStatus first
if (webSocketStatus === "DISCONNECTED") {
return I18nKey.CHAT_INTERFACE$DISCONNECTED;
}