Spaces:
Build error
Build error
import React from "react"; | |
import { useTranslation } from "react-i18next"; | |
import { useSelector } from "react-redux"; | |
import { I18nKey } from "#/i18n/declaration"; | |
import { showErrorToast } from "#/utils/error-handler"; | |
import { RootState } from "#/store"; | |
import { AgentState } from "#/types/agent-state"; | |
import { | |
AGENT_STATUS_MAP, | |
IndicatorColor, | |
} from "../../agent-status-map.constant"; | |
import { | |
useWsClient, | |
WsClientProviderStatus, | |
} from "#/context/ws-client-provider"; | |
import { useNotification } from "#/hooks/useNotification"; | |
import { browserTab } from "#/utils/browser-tab"; | |
import { useActiveConversation } from "#/hooks/query/use-active-conversation"; | |
const notificationStates = [ | |
AgentState.AWAITING_USER_INPUT, | |
AgentState.FINISHED, | |
AgentState.AWAITING_USER_CONFIRMATION, | |
]; | |
export function AgentStatusBar() { | |
const { t, i18n } = useTranslation(); | |
const { curAgentState } = useSelector((state: RootState) => state.agent); | |
const { curStatusMessage } = useSelector((state: RootState) => state.status); | |
const { status } = useWsClient(); | |
const { notify } = useNotification(); | |
const { data: conversation } = useActiveConversation(); | |
const [statusMessage, setStatusMessage] = React.useState<string>(""); | |
const updateStatusMessage = () => { | |
let message = curStatusMessage.message || ""; | |
if (curStatusMessage?.id) { | |
const id = curStatusMessage.id.trim(); | |
if (i18n.exists(id)) { | |
message = t(curStatusMessage.id.trim()) || message; | |
} | |
} | |
if (curStatusMessage?.type === "error") { | |
showErrorToast({ | |
message, | |
source: "agent-status", | |
metadata: { ...curStatusMessage }, | |
}); | |
return; | |
} | |
if (message.trim()) { | |
setStatusMessage(message); | |
} else { | |
setStatusMessage(AGENT_STATUS_MAP[curAgentState].message); | |
} | |
}; | |
React.useEffect(() => { | |
updateStatusMessage(); | |
}, [curStatusMessage.id]); | |
// Handle window focus/blur | |
React.useEffect(() => { | |
if (typeof window === "undefined") return undefined; | |
const handleFocus = () => { | |
browserTab.stopNotification(); | |
}; | |
window.addEventListener("focus", handleFocus); | |
return () => { | |
window.removeEventListener("focus", handleFocus); | |
browserTab.stopNotification(); | |
}; | |
}, []); | |
const [indicatorColor, setIndicatorColor] = React.useState<string>( | |
AGENT_STATUS_MAP[curAgentState].indicator, | |
); | |
React.useEffect(() => { | |
if (conversation?.status === "STARTING") { | |
setStatusMessage(t(I18nKey.STATUS$STARTING_RUNTIME)); | |
setIndicatorColor(IndicatorColor.RED); | |
} else if (status === WsClientProviderStatus.DISCONNECTED) { | |
setStatusMessage(t(I18nKey.STATUS$WEBSOCKET_CLOSED)); | |
setIndicatorColor(IndicatorColor.RED); | |
} else { | |
setStatusMessage(AGENT_STATUS_MAP[curAgentState].message); | |
setIndicatorColor(AGENT_STATUS_MAP[curAgentState].indicator); | |
if (notificationStates.includes(curAgentState)) { | |
const message = t(AGENT_STATUS_MAP[curAgentState].message); | |
notify(t(AGENT_STATUS_MAP[curAgentState].message), { | |
body: t(`Agent state changed to ${curAgentState}`), | |
playSound: true, | |
}); | |
// Update browser tab if window exists and is not focused | |
if (typeof document !== "undefined" && !document.hasFocus()) { | |
browserTab.startNotification(message); | |
} | |
} | |
} | |
}, [curAgentState, status, notify, t, conversation?.status]); | |
return ( | |
<div className="flex flex-col items-center"> | |
<div className="flex items-center bg-base-secondary px-2 py-1 text-gray-400 rounded-[100px] text-sm gap-[6px]"> | |
<div | |
className={`w-2 h-2 rounded-full animate-pulse ${indicatorColor}`} | |
/> | |
<span className="text-sm text-stone-400">{t(statusMessage)}</span> | |
</div> | |
</div> | |
); | |
} | |