3v324v23's picture
Зафиксирована рабочая версия TEN-Agent для HuggingFace Space
87337b1
"use client";
import * as React from "react";
import { LoadingButton } from "@/components/Button/LoadingButton";
import { setAgentConnected, setMobileActiveTab } from "@/store/reducers/global";
import {
useAppDispatch,
useAppSelector,
apiPing,
apiStartService,
apiStopService,
MOBILE_ACTIVE_TAB_MAP,
EMobileActiveTab,
isEditModeOn,
} from "@/common";
import { toast } from "sonner";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { cn } from "@/lib/utils";
import { RemotePropertyCfgSheet } from "@/components/Chat/ChatCfgPropertySelect";
import { RemoteGraphSelect } from "@/components/Chat/ChatCfgGraphSelect";
import { RemoteModuleCfgSheet } from "@/components/Chat/ChatCfgModuleSelect";
import { TrulienceCfgSheet } from "../Chat/ChatCfgTrulienceSetting";
let intervalId: NodeJS.Timeout | null = null;
export default function Action(props: { className?: string }) {
const { className } = props;
const dispatch = useAppDispatch();
const agentConnected = useAppSelector((state) => state.global.agentConnected);
const channel = useAppSelector((state) => state.global.options.channel);
const userId = useAppSelector((state) => state.global.options.userId);
const language = useAppSelector((state) => state.global.language);
const voiceType = useAppSelector((state) => state.global.voiceType);
const graphName = useAppSelector((state) => state.global.selectedGraphId);
const mobileActiveTab = useAppSelector(
(state) => state.global.mobileActiveTab
);
const [loading, setLoading] = React.useState(false);
React.useEffect(() => {
if (channel) {
checkAgentConnected();
}
}, [channel]);
const checkAgentConnected = async () => {
const res: any = await apiPing(channel);
if (res?.code == 0) {
dispatch(setAgentConnected(true));
}
};
const onClickConnect = async () => {
if (loading) {
return;
}
setLoading(true);
if (agentConnected) {
await apiStopService(channel);
dispatch(setAgentConnected(false));
toast.success("Agent disconnected");
stopPing();
} else {
const res = await apiStartService({
channel,
userId,
graphName,
language,
voiceType,
});
const { code, msg } = res || {};
if (code != 0) {
if (code == "10001") {
toast.error(
"The number of users experiencing the program simultaneously has exceeded the limit. Please try again later."
);
} else {
toast.error(`code:${code},msg:${msg}`);
}
setLoading(false);
throw new Error(msg);
}
dispatch(setAgentConnected(true));
toast.success("Agent connected");
startPing();
}
setLoading(false);
};
const startPing = () => {
if (intervalId) {
stopPing();
}
intervalId = setInterval(() => {
apiPing(channel);
}, 3000);
};
const stopPing = () => {
if (intervalId) {
clearInterval(intervalId);
intervalId = null;
}
};
const onChangeMobileActiveTab = (tab: string) => {
dispatch(setMobileActiveTab(tab as EMobileActiveTab));
};
return (
<>
{/* Action Bar */}
<div
className={cn(
"mx-2 mt-2 flex items-center justify-between rounded-t-lg bg-[#181a1d] p-2 md:m-2 md:rounded-lg",
className
)}
>
{/* -- Description Part */}
<div className="hidden md:block">
<span className="text-sm font-bold"></span>
<span className="ml-2 text-xs text-muted-foreground whitespace-nowrap">
</span>
</div>
<div className="flex w-full flex-col md:flex-row md:items-center justify-between md:justify-end">
{/* -- Tabs Section */}
<Tabs
defaultValue={mobileActiveTab}
className="md:hidden w-full md:flex-row"
onValueChange={onChangeMobileActiveTab}
>
<TabsList className="flex justify-center md:justify-start">
{Object.values(EMobileActiveTab).map((tab) => (
<TabsTrigger key={tab} value={tab} className="w-24 text-sm">
{MOBILE_ACTIVE_TAB_MAP[tab]}
</TabsTrigger>
))}
</TabsList>
</Tabs>
{/* -- Graph Select Part */}
<div className="flex flex-wrap items-center justify-between w-full md:w-auto gap-2 mt-2 md:mt-0">
<RemoteGraphSelect />
{isEditModeOn && (
<>
<TrulienceCfgSheet />
<RemoteModuleCfgSheet />
<RemotePropertyCfgSheet />
</>
)}
{/* -- Action Button */}
<div className="ml-auto flex items-center gap-2">
<LoadingButton
onClick={onClickConnect}
variant={!agentConnected ? "default" : "destructive"}
size="sm"
disabled={graphName === "" && !agentConnected}
className="w-fit min-w-24"
loading={loading}
svgProps={{ className: "h-4 w-4 text-muted-foreground" }}
>
{loading
? "Connecting"
: !agentConnected
? "Connect"
: "Disconnect"}
</LoadingButton>
</div>
</div>
</div>
</div>
</>
);
}