diff --git a/src/features/ChatInput/ActionBar/Tools/KlavisServerItem.tsx b/src/features/ChatInput/ActionBar/Tools/KlavisServerItem.tsx index 5ab094f168..a5a8e41c5b 100644 --- a/src/features/ChatInput/ActionBar/Tools/KlavisServerItem.tsx +++ b/src/features/ChatInput/ActionBar/Tools/KlavisServerItem.tsx @@ -11,9 +11,9 @@ import { KlavisServerStatus } from '@/store/tool/slices/klavisStore'; import { useUserStore } from '@/store/user'; import { userProfileSelectors } from '@/store/user/selectors'; -// 轮询配置 -const POLL_INTERVAL_MS = 1000; // 每秒轮询一次 -const POLL_TIMEOUT_MS = 15_000; // 15 秒超时 +// Polling configuration +const POLL_INTERVAL_MS = 1000; // Poll once per second +const POLL_TIMEOUT_MS = 15_000; // 15-second timeout interface KlavisServerItemProps { /** @@ -53,7 +53,7 @@ const KlavisServerItem = memo( const activeAgentId = useAgentStore((s) => s.activeAgentId); const effectiveAgentId = agentId || activeAgentId || ''; - // 清理所有定时器 + // Clean up all timers const cleanup = useCallback(() => { if (windowCheckIntervalRef.current) { clearInterval(windowCheckIntervalRef.current); @@ -71,14 +71,14 @@ const KlavisServerItem = memo( setIsWaitingAuth(false); }, []); - // 组件卸载时清理 + // Clean up on component unmount useEffect(() => { return () => { cleanup(); }; }, [cleanup]); - // 当服务器状态变为 CONNECTED 时停止所有监听 + // Stop all listeners when server status becomes CONNECTED useEffect(() => { if (server?.status === KlavisServerStatus.CONNECTED && isWaitingAuth) { cleanup(); @@ -86,14 +86,14 @@ const KlavisServerItem = memo( }, [server?.status, isWaitingAuth, cleanup, t]); /** - * 启动降级轮询(当 window.closed 不可访问时) + * Start fallback polling (when window.closed is inaccessible) */ const startFallbackPolling = useCallback( (serverName: string) => { - // 已经在轮询了,不重复启动 + // Already polling, don't start again if (pollIntervalRef.current) return; - // 每秒轮询一次 + // Poll once per second pollIntervalRef.current = setInterval(async () => { try { await refreshKlavisServerTools(serverName); @@ -102,7 +102,7 @@ const KlavisServerItem = memo( } }, POLL_INTERVAL_MS); - // 15 秒后超时停止 + // Stop after 15-second timeout pollTimeoutRef.current = setTimeout(() => { if (pollIntervalRef.current) { clearInterval(pollIntervalRef.current); @@ -115,27 +115,27 @@ const KlavisServerItem = memo( ); /** - * 监听 OAuth 窗口关闭 + * Monitor OAuth window close */ const startWindowMonitor = useCallback( (oauthWindow: Window, serverName: string) => { - // 每 500ms 检查窗口状态 + // Check window state every 500ms windowCheckIntervalRef.current = setInterval(() => { try { - // 尝试访问 window.closed(可能被 COOP 阻止) + // Try to access window.closed (may be blocked by COOP) if (oauthWindow.closed) { - // 窗口已关闭,清理监听并检查认证状态 + // Window closed, clean up listeners and check auth status if (windowCheckIntervalRef.current) { clearInterval(windowCheckIntervalRef.current); windowCheckIntervalRef.current = null; } oauthWindowRef.current = null; - // 窗口关闭后开始轮询检查认证状态 + // Start polling to check auth status after window closes startFallbackPolling(serverName); } } catch { - // COOP 阻止了访问,降级到轮询方案 + // COOP blocked access, falling back to polling console.info('[Klavis] COOP blocked window.closed access, falling back to polling'); if (windowCheckIntervalRef.current) { clearInterval(windowCheckIntervalRef.current); @@ -149,28 +149,28 @@ const KlavisServerItem = memo( ); /** - * 打开 OAuth 窗口 + * Open OAuth window */ const openOAuthWindow = useCallback( (oauthUrl: string, serverName: string) => { - // 清理之前的状态 + // Clean up previous state cleanup(); setIsWaitingAuth(true); - // 打开 OAuth 窗口 + // Open OAuth window const oauthWindow = window.open(oauthUrl, '_blank', 'width=600,height=700'); if (oauthWindow) { oauthWindowRef.current = oauthWindow; startWindowMonitor(oauthWindow, serverName); } else { - // 窗口被阻止,直接用轮询 + // Window blocked, use polling directly startFallbackPolling(serverName); } }, [cleanup, startWindowMonitor, startFallbackPolling, t], ); - // Get plugin ID for this server (使用 identifier 作为 pluginId) + // Get plugin ID for this server (use identifier as pluginId) const pluginId = server ? server.identifier : ''; const plugins = useAgentStore(agentSelectors.getAgentConfigById(effectiveAgentId))?.plugins || []; @@ -209,15 +209,15 @@ const KlavisServerItem = memo( }); if (newServer) { - // 安装完成后自动启用插件(使用 identifier) + // Auto-enable plugin after installation (using identifier) const newPluginId = newServer.identifier; await togglePlugin(newPluginId); - // 如果已认证,直接刷新工具列表,跳过 OAuth + // If already authenticated, refresh tool list directly, skip OAuth if (newServer.isAuthenticated) { await refreshKlavisServerTools(newServer.identifier); } else if (newServer.oauthUrl) { - // 需要 OAuth,打开 OAuth 窗口并监听关闭 + // Need OAuth, open OAuth window and monitor close openOAuthWindow(newServer.oauthUrl, newServer.identifier); } } @@ -235,9 +235,9 @@ const KlavisServerItem = memo( setIsToggling(false); }; - // 渲染右侧控件 + // Render right-side controls const renderRightControl = () => { - // 正在连接中 + // Connecting in progress if (isConnecting) { return ( @@ -246,7 +246,7 @@ const KlavisServerItem = memo( ); } - // 未连接,显示 Connect 按钮 + // Not connected, show Connect button if (!server) { return ( ( ); } - // 根据状态显示不同控件 + // Show different controls based on status switch (server.status) { case KlavisServerStatus.CONNECTED: { - // 正在切换状态 + // Toggling state if (isToggling) { return ; } @@ -283,7 +283,7 @@ const KlavisServerItem = memo( ); } case KlavisServerStatus.PENDING_AUTH: { - // 正在等待认证 + // Waiting for authentication if (isWaitingAuth) { return ( @@ -299,7 +299,7 @@ const KlavisServerItem = memo( style={{ cursor: 'pointer', opacity: 0.65 }} onClick={(e) => { e.stopPropagation(); - // 点击重新打开 OAuth 窗口 + // Click to reopen OAuth window if (server.oauthUrl) { openOAuthWindow(server.oauthUrl, server.identifier); } @@ -331,7 +331,7 @@ const KlavisServerItem = memo( justify={'space-between'} onClick={(e) => { e.stopPropagation(); - // 如果已连接,点击整行切换状态 + // If connected, clicking the row toggles state if (server?.status === KlavisServerStatus.CONNECTED) { handleToggle(); } diff --git a/src/features/ChatInput/ActionBar/Tools/KlavisSkillIcon.tsx b/src/features/ChatInput/ActionBar/Tools/KlavisSkillIcon.tsx index 5e38a10109..9b98a33048 100644 --- a/src/features/ChatInput/ActionBar/Tools/KlavisSkillIcon.tsx +++ b/src/features/ChatInput/ActionBar/Tools/KlavisSkillIcon.tsx @@ -6,7 +6,7 @@ import { memo } from 'react'; export const SKILL_ICON_SIZE = 20; /** - * Klavis 服务器图标组件 + * Klavis server icon component */ const KlavisSkillIcon = memo & { size: number }>( ({ icon, label, size = SKILL_ICON_SIZE }) => { diff --git a/src/features/ChatInput/ActionBar/Tools/LobehubSkillIcon.tsx b/src/features/ChatInput/ActionBar/Tools/LobehubSkillIcon.tsx index 758bddb6ca..e7f447fcb1 100644 --- a/src/features/ChatInput/ActionBar/Tools/LobehubSkillIcon.tsx +++ b/src/features/ChatInput/ActionBar/Tools/LobehubSkillIcon.tsx @@ -6,7 +6,7 @@ import { memo } from 'react'; export const SKILL_ICON_SIZE = 20; /** - * LobeHub Skill Provider 图标组件 + * LobeHub Skill Provider icon component */ const LobehubSkillIcon = memo & { size: number }>( ({ icon, label, size = SKILL_ICON_SIZE }) => { diff --git a/src/features/ChatInput/ActionBar/Tools/LobehubSkillServerItem.tsx b/src/features/ChatInput/ActionBar/Tools/LobehubSkillServerItem.tsx index 321ce8e19b..6aa9b8292f 100644 --- a/src/features/ChatInput/ActionBar/Tools/LobehubSkillServerItem.tsx +++ b/src/features/ChatInput/ActionBar/Tools/LobehubSkillServerItem.tsx @@ -195,7 +195,7 @@ const LobehubSkillServerItem = memo(({ provider, la }, [provider, cleanup, checkStatus, togglePlugin, effectiveAgentId]); const handleConnect = async () => { - // 只有已连接状态才阻止重新连接 + // Only block reconnection when already connected if (server?.isConnected) return; setIsConnecting(true); diff --git a/src/features/ChatInput/ActionBar/Tools/useControls.tsx b/src/features/ChatInput/ActionBar/Tools/useControls.tsx index 80c6ab0d26..666b78fd8e 100644 --- a/src/features/ChatInput/ActionBar/Tools/useControls.tsx +++ b/src/features/ChatInput/ActionBar/Tools/useControls.tsx @@ -46,15 +46,15 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) const builtinList = useToolStore(builtinToolSelectors.metaList, isEqual); const plugins = useAgentStore((s) => agentByIdSelectors.getAgentPluginsById(agentId)(s)); - // Klavis 相关状态 + // Klavis-related state const allKlavisServers = useToolStore(klavisStoreSelectors.getServers, isEqual); const isKlavisEnabledInEnv = useServerConfigStore(serverConfigSelectors.enableKlavis); - // LobeHub Skill 相关状态 + // LobeHub Skill related state const allLobehubSkillServers = useToolStore(lobehubSkillStoreSelectors.getServers, isEqual); const isLobehubSkillEnabled = useServerConfigStore(serverConfigSelectors.enableLobehubSkill); - // Agent Skills 相关状态 + // Agent Skills related state const installedBuiltinSkills = useToolStore(builtinToolSelectors.installedBuiltinSkills, isEqual); const marketAgentSkills = useToolStore(agentSkillsSelectors.getMarketAgentSkills, isEqual); const userAgentSkills = useToolStore(agentSkillsSelectors.getUserAgentSkills, isEqual); @@ -79,24 +79,24 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) useFetchAgentSkills(true); useCheckPluginsIsInstalled(plugins); - // 使用 SWR 加载用户的 Klavis 集成(从数据库) + // Load user's Klavis integrations via SWR (from database) useFetchUserKlavisServers(isKlavisEnabledInEnv); - // 使用 SWR 加载用户的 LobeHub Skill 连接 + // Load user's LobeHub Skill connections via SWR useFetchLobehubSkillConnections(isLobehubSkillEnabled); - // 根据 identifier 获取已连接的服务器 + // Get connected server by identifier const getServerByName = (identifier: string) => { return allKlavisServers.find((server) => server.identifier === identifier); }; - // 获取所有 Klavis 服务器类型的 identifier 集合(用于过滤 builtinList) - // 这里使用 KLAVIS_SERVER_TYPES 而不是已连接的服务器,因为我们要过滤掉所有可能的 Klavis 类型 + // Get all Klavis server type identifier sets (used for filtering builtinList) + // Using KLAVIS_SERVER_TYPES instead of connected servers here, because we want to filter out all possible Klavis types const allKlavisTypeIdentifiers = useMemo( () => new Set(KLAVIS_SERVER_TYPES.map((type) => type.identifier)), [], ); - // 获取所有 skill 的 identifier 集合(用于过滤 builtinList) + // Get all skill identifier sets (used for filtering builtinList) const allSkillIdentifiers = useMemo(() => { const ids = new Set(); for (const s of installedBuiltinSkills) ids.add(s.identifier); @@ -105,7 +105,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) return ids; }, [installedBuiltinSkills, marketAgentSkills, userAgentSkills]); - // 过滤掉 builtinList 中的 klavis 工具和 skill(它们会单独显示) + // Filter out Klavis tools and skills from builtinList (they will be displayed separately) const filteredBuiltinList = useMemo(() => { let list = builtinList; if (isKlavisEnabledInEnv) { @@ -114,7 +114,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) return list.filter((item) => !allSkillIdentifiers.has(item.identifier)); }, [builtinList, allKlavisTypeIdentifiers, isKlavisEnabledInEnv, allSkillIdentifiers]); - // 获取推荐的 Klavis skill IDs + // Get recommended Klavis skill IDs const recommendedKlavisIds = useMemo( () => new Set( @@ -123,7 +123,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) [], ); - // 获取推荐的 Lobehub skill IDs + // Get recommended Lobehub skill IDs const recommendedLobehubIds = useMemo( () => new Set( @@ -132,19 +132,19 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) [], ); - // 获取已安装的 Klavis server IDs + // Get installed Klavis server IDs const installedKlavisIds = useMemo( () => new Set(allKlavisServers.map((s) => s.identifier)), [allKlavisServers], ); - // 获取已安装的 Lobehub skill IDs + // Get installed Lobehub skill IDs const installedLobehubIds = useMemo( () => new Set(allLobehubSkillServers.map((s) => s.identifier)), [allLobehubSkillServers], ); - // Klavis 服务器列表项 - 只展示已安装或推荐的 + // Klavis server list items - only show installed or recommended const klavisServerItems = useMemo( () => isKlavisEnabledInEnv @@ -168,7 +168,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) [isKlavisEnabledInEnv, allKlavisServers, installedKlavisIds, recommendedKlavisIds, agentId], ); - // LobeHub Skill Provider 列表项 - 只展示已安装或推荐的 + // LobeHub Skill Provider list items - only show installed or recommended const lobehubSkillItems = useMemo( () => isLobehubSkillEnabled @@ -183,7 +183,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) size={SKILL_ICON_SIZE} /> ), - key: provider.id, // 使用 provider.id 作为 key,与 pluginId 保持一致 + key: provider.id, // Use provider.id as key, consistent with pluginId label: ( filteredBuiltinList.map((item) => ({ @@ -231,7 +231,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) [filteredBuiltinList, checked, togglePlugin, setUpdating], ); - // Builtin Agent Skills 列表项(归入 LobeHub 分组) + // Builtin Agent Skills list items (grouped under LobeHub) const builtinAgentSkillItems = useMemo( () => installedBuiltinSkills.map((skill) => ({ @@ -260,7 +260,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) [installedBuiltinSkills, checked, togglePlugin, setUpdating], ); - // Market Agent Skills 列表项(归入 Community 分组) + // Market Agent Skills list items (grouped under Community) const marketAgentSkillItems = useMemo( () => marketAgentSkills.map((skill) => ({ @@ -284,7 +284,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) [marketAgentSkills, checked, togglePlugin, setUpdating], ); - // User Agent Skills 列表项(归入 Custom 分组) + // User Agent Skills list items (grouped under Custom) const userAgentSkillItems = useMemo( () => userAgentSkills.map((skill) => ({ @@ -308,8 +308,8 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) [userAgentSkills, checked, togglePlugin, setUpdating], ); - // Skills 列表项(包含 LobeHub Skill 和 Klavis) - // 已连接的排在前面 + // Skills list items (including LobeHub Skill and Klavis) + // Connected items listed first const skillItems = useMemo(() => { const allItems = [...lobehubSkillItems, ...klavisServerItems]; @@ -325,11 +325,11 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) }); }, [lobehubSkillItems, klavisServerItems, installedLobehubIds, installedKlavisIds]); - // 区分社区插件和自定义插件 + // Distinguish community plugins and custom plugins const communityPlugins = list.filter((item) => item.type !== 'customPlugin'); const customPlugins = list.filter((item) => item.type === 'customPlugin'); - // 生成插件列表项的函数 + // Function to map plugins to list items const mapPluginToItem = (item: (typeof list)[0]) => ({ icon: item?.avatar ? ( @@ -351,31 +351,31 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) ), }); - // 构建 LobeHub 分组的 children(包含 Builtin Agent Skills、内置工具和 LobeHub Skill/Klavis) + // Build LobeHub group children (including Builtin Agent Skills, builtin tools, and LobeHub Skill/Klavis) const lobehubGroupChildren: ItemType[] = [ // 1. Builtin Agent Skills ...builtinAgentSkillItems, - // 2. 内置工具 + // 2. Builtin tools ...builtinItems, - // 3. LobeHub Skill 和 Klavis(作为内置技能) + // 3. LobeHub Skill and Klavis (as builtin skills) ...skillItems, ]; - // 构建 Community 分组的 children(Market Agent Skills + 社区插件) + // Build Community group children (Market Agent Skills + community plugins) const communityGroupChildren: ItemType[] = [ ...marketAgentSkillItems, ...communityPlugins.map(mapPluginToItem), ]; - // 构建 Custom 分组的 children(User Agent Skills + 自定义插件) + // Build Custom group children (User Agent Skills + custom plugins) const customGroupChildren: ItemType[] = [ ...userAgentSkillItems, ...customPlugins.map(mapPluginToItem), ]; - // 市场 tab 的 items + // Items for the market tab const marketItems: ItemType[] = [ - // LobeHub 分组 + // LobeHub group ...(lobehubGroupChildren.length > 0 ? [ { @@ -386,7 +386,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) }, ] : []), - // Community 分组 + // Community group ...(communityGroupChildren.length > 0 ? [ { @@ -397,7 +397,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) }, ] : []), - // Custom 分组(只有在有自定义插件时才显示) + // Custom group (only shown when there are custom plugins) ...(customGroupChildren.length > 0 ? [ { @@ -410,11 +410,11 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) : []), ]; - // 已安装 tab 的 items - 只显示已安装的插件 + // Items for the installed tab - only show installed plugins const installedPluginItems: ItemType[] = useMemo(() => { const installedItems: ItemType[] = []; - // 已安装的 builtin 工具 + // Installed builtin tools const enabledBuiltinItems = filteredBuiltinList .filter((item) => checked.includes(item.identifier)) .map((item) => ({ @@ -441,20 +441,20 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) ), })); - // 已连接的 Klavis 服务器 + // Connected Klavis servers const connectedKlavisItems = klavisServerItems.filter((item) => checked.includes(item.key as string), ); - // 已连接的 LobeHub Skill Providers + // Connected LobeHub Skill Providers const connectedLobehubSkillItems = lobehubSkillItems.filter((item) => checked.includes(item.key as string), ); - // 合并已启用的 LobeHub Skill 和 Klavis(作为内置技能) + // Merge enabled LobeHub Skill and Klavis (as builtin skills) const enabledSkillItems = [...connectedLobehubSkillItems, ...connectedKlavisItems]; - // 已启用的 Builtin Agent Skills + // Enabled Builtin Agent Skills const enabledBuiltinAgentSkillItems = installedBuiltinSkills .filter((skill) => checked.includes(skill.identifier)) .map((skill) => ({ @@ -481,17 +481,17 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) ), })); - // 构建内置工具分组的 children(包含 Builtin Agent Skills、内置工具和 LobeHub Skill/Klavis) + // Build builtin tools group children (including Builtin Agent Skills, builtin tools, and LobeHub Skill/Klavis) const allBuiltinItems: ItemType[] = [ // 1. Builtin Agent Skills ...enabledBuiltinAgentSkillItems, - // 2. 内置工具 + // 2. Builtin tools ...enabledBuiltinItems, - // 3. divider (如果有内置工具且有 skill items) + // 3. divider (if there are builtin tools and skill items) ...(enabledBuiltinItems.length > 0 && enabledSkillItems.length > 0 ? [{ key: 'installed-divider-builtin-skill', type: 'divider' as const }] : []), - // 4. LobeHub Skill 和 Klavis + // 4. LobeHub Skill and Klavis ...enabledSkillItems, ]; @@ -504,7 +504,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) }); } - // 已启用的社区插件 + // Enabled community plugins const enabledCommunityPlugins = communityPlugins .filter((item) => checked.includes(item.identifier)) .map((item) => ({ @@ -528,7 +528,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) ), })); - // 已启用的自定义插件 + // Enabled custom plugins const enabledCustomPlugins = customPlugins .filter((item) => checked.includes(item.identifier)) .map((item) => ({ @@ -552,7 +552,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) ), })); - // 已启用的 Market Agent Skills + // Enabled Market Agent Skills const enabledMarketAgentSkillItems = marketAgentSkills .filter((skill) => checked.includes(skill.identifier)) .map((skill) => ({ @@ -574,7 +574,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) ), })); - // Community 分组(Market Agent Skills + 社区插件) + // Community group (Market Agent Skills + community plugins) const allCommunityItems = [...enabledMarketAgentSkillItems, ...enabledCommunityPlugins]; if (allCommunityItems.length > 0) { installedItems.push({ @@ -585,7 +585,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) }); } - // 已启用的 User Agent Skills + // Enabled User Agent Skills const enabledUserAgentSkillItems = userAgentSkills .filter((skill) => checked.includes(skill.identifier)) .map((skill) => ({ @@ -607,7 +607,7 @@ export const useControls = ({ setUpdating }: { setUpdating: (updating: boolean) ), })); - // Custom 分组(User Agent Skills + 自定义插件) + // Custom group (User Agent Skills + custom plugins) const allCustomItems = [...enabledUserAgentSkillItems, ...enabledCustomPlugins]; if (allCustomItems.length > 0) { installedItems.push({