fix: fix ai extension assistant list fetch (#890)

* fix: fix ai extension assistant list fetch

* refactor: update

* refactor: update

* refactor: update
This commit is contained in:
ayangweb
2025-08-29 11:55:37 +08:00
committed by GitHub
parent efaaf73cd7
commit 4a5a4da399
12 changed files with 83 additions and 55 deletions

View File

@@ -15,7 +15,6 @@ import {
MultiSourceQueryResponse, MultiSourceQueryResponse,
} from "@/types/commands"; } from "@/types/commands";
import { useAppStore } from "@/stores/appStore"; import { useAppStore } from "@/stores/appStore";
import { useAuthStore } from "@/stores/authStore";
import { import {
getCurrentWindowService, getCurrentWindowService,
handleLogout, handleLogout,
@@ -39,16 +38,9 @@ async function invokeWithErrorHandler<T>(
command: string, command: string,
args?: Record<string, any> args?: Record<string, any>
): Promise<T> { ): Promise<T> {
const isCurrentLogin = useAuthStore.getState().isCurrentLogin;
const service = await getCurrentWindowService(); const service = await getCurrentWindowService();
// Not logged in if (!WHITELIST_SERVERS.includes(command) && !service?.profile) {
// console.log("isCurrentLogin", command, isCurrentLogin);
if (
!WHITELIST_SERVERS.includes(command) &&
(!isCurrentLogin || !service?.profile)
) {
console.error("This command requires authentication"); console.error("This command requires authentication");
throw new Error("This command requires authentication"); throw new Error("This command requires authentication");
} }

View File

@@ -2,6 +2,7 @@ import { useConnectStore } from "@/stores/connectStore";
import { SETTINGS_WINDOW_LABEL } from "@/constants"; import { SETTINGS_WINDOW_LABEL } from "@/constants";
import platformAdapter from "@/utils/platformAdapter"; import platformAdapter from "@/utils/platformAdapter";
import { useAuthStore } from "@/stores/authStore"; import { useAuthStore } from "@/stores/authStore";
import { useExtensionsStore } from "@/stores/extensionsStore";
export async function getCurrentWindowService() { export async function getCurrentWindowService() {
const currentService = useConnectStore.getState().currentService; const currentService = useConnectStore.getState().currentService;
@@ -13,23 +14,42 @@ export async function getCurrentWindowService() {
: currentService; : currentService;
} }
export async function setCurrentWindowService( export async function setCurrentWindowService(service: any, isAll?: boolean) {
service: any,
isAll?: boolean
) {
const { setCurrentService, setCloudSelectService } = const { setCurrentService, setCloudSelectService } =
useConnectStore.getState(); useConnectStore.getState();
// all refresh logout // all refresh logout
if (isAll) { if (isAll) {
setCloudSelectService(service); setCloudSelectService(service);
setCurrentService(service); return setCurrentService(service);
return;
} }
// current refresh // current refresh
const windowLabel = await platformAdapter.getCurrentWindowLabel(); const windowLabel = await platformAdapter.getCurrentWindowLabel();
return windowLabel === SETTINGS_WINDOW_LABEL
? setCloudSelectService(service) if (windowLabel === SETTINGS_WINDOW_LABEL) {
: setCurrentService(service); const { currentService } = useConnectStore.getState();
const {
aiOverviewServer,
setAiOverviewServer,
quickAiAccessServer,
setQuickAiAccessServer,
} = useExtensionsStore.getState();
if (currentService?.id === service.id) {
setCurrentService(service);
}
if (aiOverviewServer?.id === service.id) {
setAiOverviewServer(service);
}
if (quickAiAccessServer?.id === service.id) {
setQuickAiAccessServer(service);
}
return setCloudSelectService(service);
}
return setCurrentService(service);
} }
export async function handleLogout(serverId?: string) { export async function handleLogout(serverId?: string) {

View File

@@ -25,7 +25,7 @@ export const AssistantFetcher = ({
query?: string; query?: string;
}) => { }) => {
try { try {
if (unrequitable()) { if (await unrequitable()) {
return { return {
total: 0, total: 0,
list: [], list: [],

View File

@@ -54,7 +54,7 @@ const Splash = ({ assistantIDs = [], startPage }: SplashProps) => {
let response: any; let response: any;
if (isTauri) { if (isTauri) {
if (unrequitable()) { if (await unrequitable()) {
return setVisibleStartPage(false); return setVisibleStartPage(false);
} }
@@ -72,6 +72,8 @@ const Splash = ({ assistantIDs = [], startPage }: SplashProps) => {
setSettings(response); setSettings(response);
}; };
console.log("currentService", currentService);
useEffect(() => { useEffect(() => {
getSettings(); getSettings();
fetchData(); fetchData();

View File

@@ -67,7 +67,7 @@ export const MessageActions = ({
}; };
const handleSpeak = async () => { const handleSpeak = async () => {
if (isDefaultServer()) { if (await isDefaultServer()) {
return setSynthesizeItem({ id, content }); return setSynthesizeItem({ id, content });
} }

View File

@@ -1,6 +1,6 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useKeyPress, useSize } from "ahooks"; import { useAsyncEffect, useKeyPress, useSize } from "ahooks";
import clsx from "clsx"; import clsx from "clsx";
import AutoResizeTextarea from "./AutoResizeTextarea"; import AutoResizeTextarea from "./AutoResizeTextarea";
@@ -210,8 +210,8 @@ export default function ChatInput({
const extraIconRef = useRef<HTMLDivElement>(null); const extraIconRef = useRef<HTMLDivElement>(null);
const extraIconSize = useSize(extraIconRef); const extraIconSize = useSize(extraIconRef);
useEffect(() => { useAsyncEffect(async () => {
setVisibleAudioInput(isDefaultServer()); setVisibleAudioInput(await isDefaultServer());
}, [currentService]); }, [currentService]);
const renderSearchIcon = () => ( const renderSearchIcon = () => (

View File

@@ -1,4 +1,4 @@
import { FC, useMemo, useState, useCallback } from "react"; import { FC, useMemo, useState, useCallback, useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { isArray } from "lodash-es"; import { isArray } from "lodash-es";
import { useAsyncEffect, useMount } from "ahooks"; import { useAsyncEffect, useMount } from "ahooks";
@@ -37,6 +37,13 @@ const SharedAi: FC<SharedAiProps> = (props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [assistantSearchValue, setAssistantSearchValue] = useState(""); const [assistantSearchValue, setAssistantSearchValue] = useState("");
const [isLoadingAssistants, setIsLoadingAssistants] = useState(false); const [isLoadingAssistants, setIsLoadingAssistants] = useState(false);
const { setCloudSelectService } = useConnectStore();
useEffect(() => {
if (!server) return;
setCloudSelectService(server);
}, [server]);
const getEnabledServers = useCallback((servers: Server[]): Server[] => { const getEnabledServers = useCallback((servers: Server[]): Server[] => {
if (!isArray(servers)) return []; if (!isArray(servers)) return [];
@@ -56,7 +63,9 @@ const SharedAi: FC<SharedAiProps> = (props) => {
} }
if (server) { if (server) {
const matchServer = enabledServers.find((item) => item.id === server.id); const matchServer = enabledServers.find(
(item) => item.id === server.id
);
if (matchServer) { if (matchServer) {
setServer(matchServer); setServer(matchServer);
return; return;
@@ -65,7 +74,7 @@ const SharedAi: FC<SharedAiProps> = (props) => {
setServer(enabledServers[0]); setServer(enabledServers[0]);
} catch (error) { } catch (error) {
console.error('Failed to load servers:', error); console.error("Failed to load servers:", error);
addError(`Failed to load servers: ${String(error)}`); addError(`Failed to load servers: ${String(error)}`);
} }
}); });
@@ -86,7 +95,9 @@ const SharedAi: FC<SharedAiProps> = (props) => {
query: assistantSearchValue, query: assistantSearchValue,
}); });
const assistants: Assistant[] = data.list.map((item: any) => item._source); const assistants: Assistant[] = data.list.map(
(item: any) => item._source
);
setAssistantList(assistants); setAssistantList(assistants);
if (assistants.length === 0) { if (assistants.length === 0) {
@@ -104,7 +115,7 @@ const SharedAi: FC<SharedAiProps> = (props) => {
setAssistant(assistants[0]); setAssistant(assistants[0]);
} catch (error) { } catch (error) {
console.error('Failed to fetch assistants:', error); console.error("Failed to fetch assistants:", error);
addError(`Failed to fetch assistants: ${String(error)}`); addError(`Failed to fetch assistants: ${String(error)}`);
setAssistantList([]); setAssistantList([]);
setAssistant(undefined); setAssistant(undefined);
@@ -181,7 +192,9 @@ const SharedAi: FC<SharedAiProps> = (props) => {
searchable={searchable} searchable={searchable}
onChange={onChange} onChange={onChange}
onSearch={onSearch} onSearch={onSearch}
placeholder={isLoadingAssistants && searchable ? "Loading..." : undefined} placeholder={
isLoadingAssistants && searchable ? "Loading..." : undefined
}
/> />
</div> </div>
); );

View File

@@ -471,7 +471,7 @@ export function useChatActions(
const getChatHistory = useCallback(async () => { const getChatHistory = useCallback(async () => {
let response: any; let response: any;
if (isTauri) { if (isTauri) {
if (unrequitable()) { if (await unrequitable()) {
return setChats([]); return setChats([]);
} }

View File

@@ -117,6 +117,7 @@ export const useSyncStore = () => {
const setShowTooltip = useAppStore((state) => state.setShowTooltip); const setShowTooltip = useAppStore((state) => state.setShowTooltip);
const setEndpoint = useAppStore((state) => state.setEndpoint); const setEndpoint = useAppStore((state) => state.setEndpoint);
const setLanguage = useAppStore((state) => state.setLanguage); const setLanguage = useAppStore((state) => state.setLanguage);
const { setCurrentService } = useConnectStore();
useEffect(() => { useEffect(() => {
if (!resetFixedWindow) { if (!resetFixedWindow) {
@@ -180,8 +181,12 @@ export const useSyncStore = () => {
}), }),
platformAdapter.listenEvent("change-connect-store", ({ payload }) => { platformAdapter.listenEvent("change-connect-store", ({ payload }) => {
const { connectionTimeout, querySourceTimeout, allowSelfSignature } = const {
payload; connectionTimeout,
querySourceTimeout,
allowSelfSignature,
currentService,
} = payload;
if (isNumber(connectionTimeout)) { if (isNumber(connectionTimeout)) {
setConnectionTimeout(connectionTimeout); setConnectionTimeout(connectionTimeout);
} }
@@ -189,6 +194,7 @@ export const useSyncStore = () => {
setQueryTimeout(querySourceTimeout); setQueryTimeout(querySourceTimeout);
} }
setAllowSelfSignature(allowSelfSignature); setAllowSelfSignature(allowSelfSignature);
setCurrentService(currentService);
}), }),
platformAdapter.listenEvent("change-appearance-store", ({ payload }) => { platformAdapter.listenEvent("change-appearance-store", ({ payload }) => {

View File

@@ -66,7 +66,7 @@ export default function StandaloneChat({}: StandaloneChatProps) {
const getChatHistory = async () => { const getChatHistory = async () => {
try { try {
if (unrequitable()) { if (await unrequitable()) {
return setChats([]); return setChats([]);
} }
@@ -271,7 +271,11 @@ export default function StandaloneChat({}: StandaloneChatProps) {
const handleDelete = async (id: string) => { const handleDelete = async (id: string) => {
if (!currentService?.id) return; if (!currentService?.id) return;
await platformAdapter.commands("delete_session_chat", currentService.id, id); await platformAdapter.commands(
"delete_session_chat",
currentService.id,
id
);
}; };
return ( return (

View File

@@ -5,9 +5,8 @@ import { filesize as filesizeLib } from "filesize";
import platformAdapter from "./platformAdapter"; import platformAdapter from "./platformAdapter";
import { useAppStore } from "@/stores/appStore"; import { useAppStore } from "@/stores/appStore";
import { DEFAULT_COCO_SERVER_ID, HISTORY_PANEL_ID } from "@/constants"; import { DEFAULT_COCO_SERVER_ID, HISTORY_PANEL_ID } from "@/constants";
import { useConnectStore } from "@/stores/connectStore";
import { useAuthStore } from "@/stores/authStore";
import { useChatStore } from "@/stores/chatStore"; import { useChatStore } from "@/stores/chatStore";
import { getCurrentWindowService } from "@/commands/windowService";
// 1 // 1
export async function copyToClipboard(text: string) { export async function copyToClipboard(text: string) {
@@ -163,36 +162,28 @@ export const parseSearchQuery = (searchQuery: SearchQuery) => {
return result; return result;
}; };
export const unrequitable = () => { export const unrequitable = async () => {
const { isTauri } = useAppStore.getState(); const { isTauri } = useAppStore.getState();
const { currentService } = useConnectStore.getState(); const { id, available, enabled } = await getCurrentWindowService();
const { isCurrentLogin } = useAuthStore.getState();
const { id, available, enabled } = currentService ?? {};
const serviceAvailable = Boolean( const serviceAvailable = Boolean(id && enabled && available);
id && enabled && available && isCurrentLogin
);
return isTauri && !serviceAvailable; return isTauri && !serviceAvailable;
}; };
export const isDefaultServer = (checkAvailability = true) => { export const isDefaultServer = async (checkAvailability = true) => {
const { isTauri } = useAppStore.getState(); const { isTauri } = useAppStore.getState();
const { currentService } = useConnectStore.getState(); const { id, available, enabled } = await getCurrentWindowService();
const { isCurrentLogin } = useAuthStore.getState();
const { id, available, enabled } = currentService ?? {};
const isDefaultServer = currentService.id === DEFAULT_COCO_SERVER_ID; const isDefault = id === DEFAULT_COCO_SERVER_ID;
const serviceAvailable = Boolean( const serviceAvailable = Boolean(id && enabled && available);
id && enabled && available && isCurrentLogin
);
if (checkAvailability) { if (checkAvailability) {
return isTauri && isDefaultServer && serviceAvailable; return isTauri && isDefault && serviceAvailable;
} }
return isTauri && isDefaultServer; return isTauri && isDefault;
}; };
export const filesize = (value: number, spacer?: string) => { export const filesize = (value: number, spacer?: string) => {

View File

@@ -306,7 +306,7 @@ export const createTauriAdapter = (): TauriPlatformAdapter => {
error, error,
async searchMCPServers(serverId, queryParams) { async searchMCPServers(serverId, queryParams) {
if (unrequitable()) { if (await unrequitable()) {
return []; return [];
} }