mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-01-08 22:38:05 -05:00
feat(frontend): adding status indicator and unit test (#12111)
Co-authored-by: Chloe <chloe@openhands.com> Co-authored-by: sp.wack <83104063+amanape@users.noreply.github.com>
This commit is contained in:
48
frontend/__tests__/components/chat-status-indicator.test.tsx
Normal file
48
frontend/__tests__/components/chat-status-indicator.test.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import ChatStatusIndicator from "#/components/features/chat/chat-status-indicator";
|
||||
|
||||
vi.mock("#/icons/debug-stackframe-dot.svg?react", () => ({
|
||||
default: (props: any) => (
|
||||
<svg data-testid="debug-stackframe-dot" {...props} />
|
||||
),
|
||||
}));
|
||||
|
||||
describe("ChatStatusIndicator", () => {
|
||||
it("renders the status indicator with status text", () => {
|
||||
render(
|
||||
<ChatStatusIndicator
|
||||
status="Waiting for sandbox"
|
||||
statusColor="#FFD600"
|
||||
/>
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByTestId("chat-status-indicator"),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText("Waiting for sandbox")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("passes the statusColor to the DebugStackframeDot icon", () => {
|
||||
render(
|
||||
<ChatStatusIndicator
|
||||
status="Error"
|
||||
statusColor="#FF684E"
|
||||
/>
|
||||
);
|
||||
|
||||
const icon = screen.getByTestId("debug-stackframe-dot");
|
||||
expect(icon).toHaveAttribute("color", "#FF684E");
|
||||
});
|
||||
|
||||
it("renders the DebugStackframeDot icon", () => {
|
||||
render(
|
||||
<ChatStatusIndicator
|
||||
status="Loading"
|
||||
statusColor="#FFD600"
|
||||
/>
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("debug-stackframe-dot")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -24,6 +24,8 @@ import { useGetTrajectory } from "#/hooks/mutation/use-get-trajectory";
|
||||
import { useUnifiedUploadFiles } from "#/hooks/mutation/use-unified-upload-files";
|
||||
import { OpenHandsAction } from "#/types/core/actions";
|
||||
import { useEventStore } from "#/stores/use-event-store";
|
||||
import { useAgentState } from "#/hooks/use-agent-state";
|
||||
import { AgentState } from "#/types/agent-state";
|
||||
|
||||
vi.mock("#/context/ws-client-provider");
|
||||
vi.mock("#/hooks/query/use-config");
|
||||
@@ -59,6 +61,12 @@ vi.mock("#/hooks/use-conversation-name-context-menu", () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("#/hooks/use-agent-state", () => ({
|
||||
useAgentState: vi.fn(() => ({
|
||||
curAgentState: AgentState.AWAITING_USER_INPUT,
|
||||
})),
|
||||
}));
|
||||
|
||||
// Helper function to render with Router context
|
||||
const renderChatInterfaceWithRouter = () =>
|
||||
renderWithProviders(
|
||||
@@ -344,6 +352,28 @@ describe("ChatInterface - Empty state", () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('ChatInterface - Status Indicator', () => {
|
||||
it("should render ChatStatusIndicator when agent is not awaiting user input / conversation is NOT ready", () => {
|
||||
vi.mocked(useAgentState).mockReturnValue({
|
||||
curAgentState: AgentState.LOADING,
|
||||
});
|
||||
|
||||
renderChatInterfaceWithRouter();
|
||||
|
||||
expect(screen.getByTestId("chat-status-indicator")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should NOT render ChatStatusIndicator when agent is awaiting user input / conversation is ready", () => {
|
||||
vi.mocked(useAgentState).mockReturnValue({
|
||||
curAgentState: AgentState.AWAITING_USER_INPUT,
|
||||
});
|
||||
|
||||
renderChatInterfaceWithRouter();
|
||||
|
||||
expect(screen.queryByTestId("chat-status-indicator")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip("ChatInterface - General functionality", () => {
|
||||
beforeAll(() => {
|
||||
// mock useScrollToBottom hook
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
import { test, expect } from "vitest";
|
||||
import { describe, it, expect, vi, test } from "vitest";
|
||||
import {
|
||||
formatTimestamp,
|
||||
getExtension,
|
||||
removeApiKey,
|
||||
} from "../../src/utils/utils";
|
||||
import { getStatusText } from "#/utils/utils";
|
||||
import { AgentState } from "#/types/agent-state";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
|
||||
// Mock translations
|
||||
const t = (key: string) => {
|
||||
const translations: { [key: string]: string } = {
|
||||
COMMON$WAITING_FOR_SANDBOX: "Waiting For Sandbox",
|
||||
COMMON$STOPPING: "Stopping",
|
||||
COMMON$STARTING: "Starting",
|
||||
COMMON$SERVER_STOPPED: "Server stopped",
|
||||
COMMON$RUNNING: "Running",
|
||||
CONVERSATION$READY: "Ready",
|
||||
CONVERSATION$ERROR_STARTING_CONVERSATION: "Error starting conversation",
|
||||
};
|
||||
return translations[key] || key;
|
||||
};
|
||||
|
||||
test("removeApiKey", () => {
|
||||
const data = [{ args: { LLM_API_KEY: "key", LANGUAGE: "en" } }];
|
||||
@@ -23,3 +40,143 @@ test("formatTimestamp", () => {
|
||||
const eveningDate = new Date("2021-10-10T22:10:10.000").toISOString();
|
||||
expect(formatTimestamp(eveningDate)).toBe("10/10/2021, 22:10:10");
|
||||
});
|
||||
|
||||
describe("getStatusText", () => {
|
||||
it("returns STOPPING when pausing", () => {
|
||||
const result = getStatusText({
|
||||
isPausing: true,
|
||||
isTask: false,
|
||||
taskStatus: null,
|
||||
taskDetail: null,
|
||||
isStartingStatus: false,
|
||||
isStopStatus: false,
|
||||
curAgentState: AgentState.RUNNING,
|
||||
t,
|
||||
});
|
||||
|
||||
expect(result).toBe(t(I18nKey.COMMON$STOPPING));
|
||||
});
|
||||
|
||||
it("formats task status when polling a task", () => {
|
||||
const result = getStatusText({
|
||||
isPausing: false,
|
||||
isTask: true,
|
||||
taskStatus: "WAITING_FOR_SANDBOX",
|
||||
taskDetail: null,
|
||||
isStartingStatus: false,
|
||||
isStopStatus: false,
|
||||
curAgentState: AgentState.RUNNING,
|
||||
t,
|
||||
});
|
||||
|
||||
expect(result).toBe(t(I18nKey.COMMON$WAITING_FOR_SANDBOX));
|
||||
});
|
||||
|
||||
it("returns task detail when task status is ERROR and detail exists", () => {
|
||||
const result = getStatusText({
|
||||
isPausing: false,
|
||||
isTask: true,
|
||||
taskStatus: "ERROR",
|
||||
taskDetail: "Sandbox failed",
|
||||
isStartingStatus: false,
|
||||
isStopStatus: false,
|
||||
curAgentState: AgentState.RUNNING,
|
||||
t,
|
||||
});
|
||||
|
||||
expect(result).toBe("Sandbox failed");
|
||||
});
|
||||
|
||||
it("returns translated error when task status is ERROR and no detail", () => {
|
||||
const result = getStatusText({
|
||||
isPausing: false,
|
||||
isTask: true,
|
||||
taskStatus: "ERROR",
|
||||
taskDetail: null,
|
||||
isStartingStatus: false,
|
||||
isStopStatus: false,
|
||||
curAgentState: AgentState.RUNNING,
|
||||
t,
|
||||
});
|
||||
|
||||
expect(result).toBe(
|
||||
t(I18nKey.CONVERSATION$ERROR_STARTING_CONVERSATION),
|
||||
);
|
||||
});
|
||||
|
||||
it("returns READY translation when task is ready", () => {
|
||||
const result = getStatusText({
|
||||
isPausing: false,
|
||||
isTask: true,
|
||||
taskStatus: "READY",
|
||||
taskDetail: null,
|
||||
isStartingStatus: false,
|
||||
isStopStatus: false,
|
||||
curAgentState: AgentState.RUNNING,
|
||||
t,
|
||||
});
|
||||
|
||||
expect(result).toBe(t(I18nKey.CONVERSATION$READY));
|
||||
});
|
||||
|
||||
it("returns STARTING when starting status is true", () => {
|
||||
const result = getStatusText({
|
||||
isPausing: false,
|
||||
isTask: false,
|
||||
taskStatus: null,
|
||||
taskDetail: null,
|
||||
isStartingStatus: true,
|
||||
isStopStatus: false,
|
||||
curAgentState: AgentState.INIT,
|
||||
t,
|
||||
});
|
||||
|
||||
expect(result).toBe(t(I18nKey.COMMON$STARTING));
|
||||
});
|
||||
|
||||
it("returns SERVER_STOPPED when stop status is true", () => {
|
||||
const result = getStatusText({
|
||||
isPausing: false,
|
||||
isTask: false,
|
||||
taskStatus: null,
|
||||
taskDetail: null,
|
||||
isStartingStatus: false,
|
||||
isStopStatus: true,
|
||||
curAgentState: AgentState.STOPPED,
|
||||
t,
|
||||
});
|
||||
|
||||
expect(result).toBe(t(I18nKey.COMMON$SERVER_STOPPED));
|
||||
});
|
||||
|
||||
it("returns errorMessage when agent state is ERROR", () => {
|
||||
const result = getStatusText({
|
||||
isPausing: false,
|
||||
isTask: false,
|
||||
taskStatus: null,
|
||||
taskDetail: null,
|
||||
isStartingStatus: false,
|
||||
isStopStatus: false,
|
||||
curAgentState: AgentState.ERROR,
|
||||
errorMessage: "Something broke",
|
||||
t,
|
||||
});
|
||||
|
||||
expect(result).toBe("Something broke");
|
||||
});
|
||||
|
||||
it("returns default RUNNING status", () => {
|
||||
const result = getStatusText({
|
||||
isPausing: false,
|
||||
isTask: false,
|
||||
taskStatus: null,
|
||||
taskDetail: null,
|
||||
isStartingStatus: false,
|
||||
isStopStatus: false,
|
||||
curAgentState: AgentState.RUNNING,
|
||||
t,
|
||||
});
|
||||
|
||||
expect(result).toBe(t(I18nKey.COMMON$RUNNING));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -49,6 +49,8 @@ import {
|
||||
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
|
||||
import { useTaskPolling } from "#/hooks/query/use-task-polling";
|
||||
import { useConversationWebSocket } from "#/contexts/conversation-websocket-context";
|
||||
import ChatStatusIndicator from "./chat-status-indicator";
|
||||
import { getStatusColor, getStatusText } from "#/utils/utils";
|
||||
|
||||
function getEntryPoint(
|
||||
hasRepository: boolean | null,
|
||||
@@ -65,7 +67,7 @@ export function ChatInterface() {
|
||||
const { data: conversation } = useActiveConversation();
|
||||
const { errorMessage } = useErrorMessageStore();
|
||||
const { isLoadingMessages } = useWsClient();
|
||||
const { isTask } = useTaskPolling();
|
||||
const { isTask, taskStatus, taskDetail } = useTaskPolling();
|
||||
const conversationWebSocket = useConversationWebSocket();
|
||||
const { send } = useSendMessage();
|
||||
const storeEvents = useEventStore((state) => state.events);
|
||||
@@ -235,6 +237,31 @@ export function ChatInterface() {
|
||||
const v1UserEventsExist = hasV1UserEvent(v1FullEvents);
|
||||
const userEventsExist = v0UserEventsExist || v1UserEventsExist;
|
||||
|
||||
// Get server status indicator props
|
||||
const isStartingStatus =
|
||||
curAgentState === AgentState.LOADING || curAgentState === AgentState.INIT;
|
||||
const isStopStatus = curAgentState === AgentState.STOPPED;
|
||||
const isPausing = curAgentState === AgentState.PAUSED;
|
||||
const serverStatusColor = getStatusColor({
|
||||
isPausing,
|
||||
isTask,
|
||||
taskStatus,
|
||||
isStartingStatus,
|
||||
isStopStatus,
|
||||
curAgentState,
|
||||
});
|
||||
const serverStatusText = getStatusText({
|
||||
isPausing,
|
||||
isTask,
|
||||
taskStatus,
|
||||
taskDetail,
|
||||
isStartingStatus,
|
||||
isStopStatus,
|
||||
curAgentState,
|
||||
errorMessage,
|
||||
t,
|
||||
});
|
||||
|
||||
return (
|
||||
<ScrollProvider value={scrollProviderValue}>
|
||||
<div className="h-full flex flex-col justify-between pr-0 md:pr-4 relative">
|
||||
@@ -282,8 +309,14 @@ export function ChatInterface() {
|
||||
|
||||
<div className="flex flex-col gap-[6px]">
|
||||
<div className="flex justify-between relative">
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="flex items-end gap-1">
|
||||
<ConfirmationModeEnabled />
|
||||
{isStartingStatus && (
|
||||
<ChatStatusIndicator
|
||||
statusColor={serverStatusColor}
|
||||
status={serverStatusText}
|
||||
/>
|
||||
)}
|
||||
{totalEvents > 0 && !isV1Conversation && (
|
||||
<TrajectoryActions
|
||||
onPositiveFeedback={() =>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { cn } from "@heroui/react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import DebugStackframeDot from "#/icons/debug-stackframe-dot.svg?react";
|
||||
|
||||
interface ChatStatusIndicatorProps {
|
||||
status: string;
|
||||
statusColor: string;
|
||||
}
|
||||
|
||||
function ChatStatusIndicator({
|
||||
status,
|
||||
statusColor,
|
||||
}: ChatStatusIndicatorProps) {
|
||||
return (
|
||||
<div
|
||||
data-testid="chat-status-indicator"
|
||||
className={cn(
|
||||
"h-[31px] w-fit rounded-[100px] pt-[20px] pr-[16px] pb-[20px] pl-[5px] bg-[#25272D] flex items-center gap-2",
|
||||
)}
|
||||
>
|
||||
<AnimatePresence mode="wait">
|
||||
{/* Dot */}
|
||||
<motion.span
|
||||
key={`dot-${status}`}
|
||||
className="animate-[pulse_1.2s_ease-in-out_infinite]"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<DebugStackframeDot
|
||||
className="w-6 h-6 shrink-0"
|
||||
color={statusColor}
|
||||
/>
|
||||
</motion.span>
|
||||
|
||||
{/* Text */}
|
||||
<motion.span
|
||||
key={`text-${status}`}
|
||||
initial={{ opacity: 0, y: -2 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 2 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="font-normal text-[11px] leading-[20px] normal-case"
|
||||
>
|
||||
{status}
|
||||
</motion.span>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ChatStatusIndicator;
|
||||
@@ -1,11 +1,10 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import DebugStackframeDot from "#/icons/debug-stackframe-dot.svg?react";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
import { ConversationStatus } from "#/types/conversation-status";
|
||||
import { AgentState } from "#/types/agent-state";
|
||||
import { useAgentState } from "#/hooks/use-agent-state";
|
||||
import { useTaskPolling } from "#/hooks/query/use-task-polling";
|
||||
import { getStatusColor } from "#/utils/utils";
|
||||
import { getStatusColor, getStatusText } from "#/utils/utils";
|
||||
import { useErrorMessageStore } from "#/stores/error-message-store";
|
||||
|
||||
export interface ServerStatusProps {
|
||||
@@ -20,13 +19,12 @@ export function ServerStatus({
|
||||
isPausing = false,
|
||||
}: ServerStatusProps) {
|
||||
const { curAgentState } = useAgentState();
|
||||
const { t } = useTranslation();
|
||||
const { isTask, taskStatus, taskDetail } = useTaskPolling();
|
||||
const { t } = useTranslation();
|
||||
const { errorMessage } = useErrorMessageStore();
|
||||
|
||||
const isStartingStatus =
|
||||
curAgentState === AgentState.LOADING || curAgentState === AgentState.INIT;
|
||||
|
||||
const isStopStatus = conversationStatus === "STOPPED";
|
||||
|
||||
const statusColor = getStatusColor({
|
||||
@@ -38,45 +36,17 @@ export function ServerStatus({
|
||||
curAgentState,
|
||||
});
|
||||
|
||||
const getStatusText = (): string => {
|
||||
// Show pausing status
|
||||
if (isPausing) {
|
||||
return t(I18nKey.COMMON$STOPPING);
|
||||
}
|
||||
|
||||
// Show task status if we're polling a task
|
||||
if (isTask && taskStatus) {
|
||||
if (taskStatus === "ERROR") {
|
||||
return (
|
||||
taskDetail || t(I18nKey.CONVERSATION$ERROR_STARTING_CONVERSATION)
|
||||
);
|
||||
}
|
||||
if (taskStatus === "READY") {
|
||||
return t(I18nKey.CONVERSATION$READY);
|
||||
}
|
||||
// Format status text: "WAITING_FOR_SANDBOX" -> "Waiting for sandbox"
|
||||
return (
|
||||
taskDetail ||
|
||||
taskStatus
|
||||
.toLowerCase()
|
||||
.replace(/_/g, " ")
|
||||
.replace(/\b\w/g, (c) => c.toUpperCase())
|
||||
);
|
||||
}
|
||||
|
||||
if (isStartingStatus) {
|
||||
return t(I18nKey.COMMON$STARTING);
|
||||
}
|
||||
if (isStopStatus) {
|
||||
return t(I18nKey.COMMON$SERVER_STOPPED);
|
||||
}
|
||||
if (curAgentState === AgentState.ERROR) {
|
||||
return errorMessage || t(I18nKey.COMMON$ERROR);
|
||||
}
|
||||
return t(I18nKey.COMMON$RUNNING);
|
||||
};
|
||||
|
||||
const statusText = getStatusText();
|
||||
const statusText = getStatusText({
|
||||
isPausing,
|
||||
isTask,
|
||||
taskStatus,
|
||||
taskDetail,
|
||||
isStartingStatus,
|
||||
isStopStatus,
|
||||
curAgentState,
|
||||
errorMessage,
|
||||
t,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={className} data-testid="server-status">
|
||||
|
||||
@@ -929,6 +929,7 @@ export enum I18nKey {
|
||||
COMMON$RECENT_PROJECTS = "COMMON$RECENT_PROJECTS",
|
||||
COMMON$RUN = "COMMON$RUN",
|
||||
COMMON$RUNNING = "COMMON$RUNNING",
|
||||
COMMON$WAITING_FOR_SANDBOX = "COMMON$WAITING_FOR_SANDBOX",
|
||||
COMMON$SELECT_GIT_PROVIDER = "COMMON$SELECT_GIT_PROVIDER",
|
||||
COMMON$SERVER_STATUS = "COMMON$SERVER_STATUS",
|
||||
COMMON$SERVER_STOPPED = "COMMON$SERVER_STOPPED",
|
||||
|
||||
@@ -14863,6 +14863,22 @@
|
||||
"de": "Läuft",
|
||||
"uk": "Працює"
|
||||
},
|
||||
"COMMON$WAITING_FOR_SANDBOX": {
|
||||
"en": "Waiting for sandbox",
|
||||
"ja": "サンドボックスを待機中",
|
||||
"zh-CN": "等待沙盒",
|
||||
"zh-TW": "等待沙盒",
|
||||
"ko-KR": "샌드박스를 기다리는 중",
|
||||
"no": "Venter på sandkasse",
|
||||
"it": "In attesa del sandbox",
|
||||
"pt": "Aguardando sandbox",
|
||||
"es": "Esperando el sandbox",
|
||||
"ar": "في انتظار البيئة المعزولة",
|
||||
"fr": "En attente du bac à sable",
|
||||
"tr": "Sandbox bekleniyor",
|
||||
"de": "Warten auf Sandbox",
|
||||
"uk": "Очікування пісочниці"
|
||||
},
|
||||
"COMMON$SELECT_GIT_PROVIDER": {
|
||||
"en": "Select Git provider",
|
||||
"ja": "Gitプロバイダーを選択",
|
||||
|
||||
@@ -7,6 +7,7 @@ import { GitRepository } from "#/types/git";
|
||||
import { sanitizeQuery } from "#/utils/sanitize-query";
|
||||
import { PRODUCT_URL } from "#/utils/constants";
|
||||
import { AgentState } from "#/types/agent-state";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
@@ -746,3 +747,91 @@ export const getStatusColor = (options: {
|
||||
}
|
||||
return "#BCFF8C";
|
||||
};
|
||||
|
||||
interface GetStatusTextArgs {
|
||||
isPausing: boolean;
|
||||
isTask: boolean;
|
||||
taskStatus?: string | null;
|
||||
taskDetail?: string | null;
|
||||
isStartingStatus: boolean;
|
||||
isStopStatus: boolean;
|
||||
curAgentState: AgentState;
|
||||
errorMessage?: string | null;
|
||||
t: (t: string) => string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server status text based on agent and task state
|
||||
*
|
||||
* @param options Configuration object for status text calculation
|
||||
* @param options.isPausing Whether the agent is currently pausing
|
||||
* @param options.isTask Whether we're polling a task
|
||||
* @param options.taskStatus The task status string (e.g., "ERROR", "READY")
|
||||
* @param options.taskDetail Optional task-specific detail text
|
||||
* @param options.isStartingStatus Whether the conversation is in STARTING state
|
||||
* @param options.isStopStatus Whether the conversation is STOPPED
|
||||
* @param options.curAgentState The current agent state
|
||||
* @param options.errorMessage Optional agent error message
|
||||
* @returns Localized human-readable status text
|
||||
*
|
||||
* @example
|
||||
* getStatusText({
|
||||
* isPausing: false,
|
||||
* isTask: true,
|
||||
* taskStatus: "WAITING_FOR_SANDBOX",
|
||||
* taskDetail: null,
|
||||
* isStartingStatus: false,
|
||||
* isStopStatus: false,
|
||||
* curAgentState: AgentState.RUNNING
|
||||
* }) // Returns "Waiting For Sandbox"
|
||||
*/
|
||||
export function getStatusText({
|
||||
isPausing = false,
|
||||
isTask,
|
||||
taskStatus,
|
||||
taskDetail,
|
||||
isStartingStatus,
|
||||
isStopStatus,
|
||||
curAgentState,
|
||||
errorMessage,
|
||||
t,
|
||||
}: GetStatusTextArgs): string {
|
||||
// Show pausing status
|
||||
if (isPausing) {
|
||||
return t(I18nKey.COMMON$STOPPING);
|
||||
}
|
||||
|
||||
// Show task status if we're polling a task
|
||||
if (isTask && taskStatus) {
|
||||
if (taskStatus === "ERROR") {
|
||||
return taskDetail || t(I18nKey.CONVERSATION$ERROR_STARTING_CONVERSATION);
|
||||
}
|
||||
|
||||
if (taskStatus === "READY") {
|
||||
return t(I18nKey.CONVERSATION$READY);
|
||||
}
|
||||
|
||||
// Format status text: "WAITING_FOR_SANDBOX" -> "Waiting for sandbox"
|
||||
return (
|
||||
taskDetail ||
|
||||
taskStatus
|
||||
.toLowerCase()
|
||||
.replace(/_/g, " ")
|
||||
.replace(/\b\w/g, (c) => c.toUpperCase())
|
||||
);
|
||||
}
|
||||
|
||||
if (isStartingStatus) {
|
||||
return t(I18nKey.COMMON$STARTING);
|
||||
}
|
||||
|
||||
if (isStopStatus) {
|
||||
return t(I18nKey.COMMON$SERVER_STOPPED);
|
||||
}
|
||||
|
||||
if (curAgentState === AgentState.ERROR) {
|
||||
return errorMessage || t(I18nKey.COMMON$ERROR);
|
||||
}
|
||||
|
||||
return t(I18nKey.COMMON$RUNNING);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user