From a2555f9c67b3769a8bae228a4dd1ccb2a441cbed Mon Sep 17 00:00:00 2001 From: ljunb Date: Tue, 16 Dec 2025 12:09:55 +0800 Subject: [PATCH 1/7] feat: integrate Gonka provider --- app/components/setting/add-model-modal.tsx | 82 ++++++------ app/components/setting/model-list.tsx | 22 +++- app/components/setting/provider-icon.tsx | 4 + app/icons/gonka.svg | 4 + app/locales/en-US/settings.json | 4 +- app/locales/zh-CN/settings.json | 4 +- app/services/model.ts | 141 ++++++++++++++++++++- app/store/agent.ts | 2 + 8 files changed, 223 insertions(+), 40 deletions(-) create mode 100644 app/icons/gonka.svg diff --git a/app/components/setting/add-model-modal.tsx b/app/components/setting/add-model-modal.tsx index de4b857e..04c255fc 100644 --- a/app/components/setting/add-model-modal.tsx +++ b/app/components/setting/add-model-modal.tsx @@ -28,11 +28,12 @@ import { import { fetch } from "@tauri-apps/api/http"; import { useAppConfig } from "@/app/store"; import { toast } from "@/app/utils/toast"; +import { getGonkaModels } from "@/app/services/model"; interface ModelInfo { provider: string; apiKey: string; - models: []; + models: string[]; customUrl: string; } @@ -57,7 +58,7 @@ export function AddModelModal({ const [isGettingModelLoading, setIsGettingModelLoading] = useState(false); const [isModelsError, setIsModelsError] = useState(false); const [isApiKeyError, setIsApiKeyError] = useState(false); - const [formData, setFormData, formDataRef] = useState({ + const [formData, setFormData, formDataRef] = useState({ provider: "", apiKey: "", models: [], @@ -65,24 +66,32 @@ export function AddModelModal({ }); const providerList = useAppConfig((state) => state.providerList); + useEffect(() => { - if (providerList && providerList.length) { - if (!isEdit) { + if (!open) return; + + if (isEdit && editInfo) { + const { apiKey, provider, models } = editInfo; + if (apiKey) { setFormData({ - provider: providerList[0].provider, - apiKey: "", - models: [], + provider: provider || "", + apiKey: apiKey, + models: models?.map((model) => model?.value) || [], customUrl: "", }); + getModels(); } + } else if (!isEdit && providerList && providerList.length) { + setFormData({ + provider: providerList[0].provider, + apiKey: "", + models: [], + customUrl: "", + }); + setModelList([]); } - }, [providerList]); + }, [open, isEdit, editInfo, providerList]); - useEffect(() => { - if (isEdit) { - initFormData(); - } - }, []); useEffect(() => { const { models } = formDataRef.current; if (models.length) { @@ -90,26 +99,6 @@ export function AddModelModal({ } }, [formDataRef.current]); - const initFormData = () => { - const { apiKey, provider, models } = editInfo || {}; - if (apiKey) { - // @ts-ignore - setFormData((prev) => { - const updatedFormData: ModelInfo = { - ...prev, - provider: provider || "", - apiKey: apiKey, - // @ts-ignore - models: models?.map((model) => model?.value), - customUrl: "", - }; - getModels(); - - return updatedFormData; - }); - } - }; - const handleConfirm = useCallback(() => { const { apiKey, models } = formDataRef.current; if (!apiKey || !models.length) { @@ -201,6 +190,21 @@ export function AddModelModal({ }; const getModels = async () => { + if (formDataRef.current.provider === "gonka") { + setIsGettingModelLoading(true); + setIsModelsError(false); + try { + const models = await getGonkaModels(); + setModelList(models); + } catch (error) { + toast.error("Failed to fetch gonka models: " + error); + console.error("Error fetching gonka models:", error); + } finally { + setIsGettingModelLoading(false); + } + return; + } + const apiKey = formDataRef.current.apiKey; if (!apiKey) return; const providerInfo = providerList.find( @@ -317,16 +321,22 @@ export function AddModelModal({
state.models); const localProviders = useAppConfig((state) => state.localProviders); @@ -50,7 +70,7 @@ export default function ModelList() { async function getProviderData() { const data = await getProviderList(); if (data && data.length) { - setProviderList(data); + setProviderList([...data, GonkaProvider]); } } getProviderData(); diff --git a/app/components/setting/provider-icon.tsx b/app/components/setting/provider-icon.tsx index 2f622cbc..5701f7c0 100644 --- a/app/components/setting/provider-icon.tsx +++ b/app/components/setting/provider-icon.tsx @@ -6,6 +6,7 @@ import AnthropicIconDark from "@/app/icons/anthropic-dark.svg"; import GoogleIcon from "@/app/icons/google.svg"; import AidenLightIcon from "@/app/icons/default-aiden.svg"; import AidenDarkIcon from "@/app/icons/logo-circle.svg"; +import GonkaIcon from "@/app/icons/gonka.svg"; import clsx from "clsx"; export function ProviderIcon({ @@ -31,6 +32,9 @@ export function ProviderIcon({ if (provider === "gemini") { return ; } + if (provider === "gonka") { + return ; + } return theme === Theme.Light ? ( diff --git a/app/icons/gonka.svg b/app/icons/gonka.svg new file mode 100644 index 00000000..939be550 --- /dev/null +++ b/app/icons/gonka.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/locales/en-US/settings.json b/app/locales/en-US/settings.json index 53b565a2..c252a371 100644 --- a/app/locales/en-US/settings.json +++ b/app/locales/en-US/settings.json @@ -72,7 +72,9 @@ "apiKeyErrorText": "Please enter API Key", "modelErrorText": "Please select models", "deleteSuccess": "Deleted successfully", - "enterApiKey": "Enter API Key" + "enterApiKey": "Enter API Key", + "privateKey": "Private Key", + "enterPrivateKey": "Enter private key" }, "mcp": { "inValidEmail": "Please enter a valid email address", diff --git a/app/locales/zh-CN/settings.json b/app/locales/zh-CN/settings.json index 511ba64c..2ef4b3a8 100644 --- a/app/locales/zh-CN/settings.json +++ b/app/locales/zh-CN/settings.json @@ -72,7 +72,9 @@ "apiKeyErrorText": "请输入 API Key", "modelErrorText": "请选择模型", "deleteSuccess": "删除成功", - "enterApiKey": "输入 API Key" + "enterApiKey": "输入 API Key", + "privateKey": "私钥", + "enterPrivateKey": "输入私钥" }, "mcp": { "inValidEmail": "请输入有效的邮箱地址", diff --git a/app/services/model.ts b/app/services/model.ts index e62d30aa..f81a8400 100644 --- a/app/services/model.ts +++ b/app/services/model.ts @@ -1,5 +1,6 @@ import { aidenFetch as fetch } from "@/app/utils/fetch"; -import { ModelOption, ProviderOption } from "../typing"; +import { ModelOption, ProviderOption, CustomModelOption } from "../typing"; +import { fetch as tauriFetch } from "@tauri-apps/api/http"; export const getModelList = async (): Promise => { const { data, status } = await fetch("/api/v1/models", { @@ -28,3 +29,141 @@ export const getProviderList = async (): Promise => { } return []; }; + +// Gonka API 响应类型定义 +interface GonkaParticipant { + index: string; + validator_key: string; + weight: number; + inference_url: string; + models: string[]; + seed?: any; + ml_nodes?: any[]; +} + +// Gonka 模型缓存 +interface GonkaModelCache { + models: CustomModelOption[]; + timestamp: number; +} + +let gonkaModelCache: GonkaModelCache | null = null; +const CACHE_DURATION = 5 * 60 * 1000; // 5分钟缓存 + +// 默认 Gonka 模型(作为后备) +const DEFAULT_GONKA_MODELS: CustomModelOption[] = [ + { + value: "Qwen/Qwen3-235B-A22B-Instruct-2507-FP8", + label: "Qwen3-235B-A22B-Instruct-2507-FP8", + }, +]; + +/** + * 获取 Gonka 模型列表 + * @param forceRefresh 是否强制刷新缓存 + * @returns CustomModelOption[] 模型列表 + */ +export const getGonkaModels = async ( + forceRefresh: boolean = false, +): Promise => { + if ( + !forceRefresh && + gonkaModelCache && + Date.now() - gonkaModelCache.timestamp < CACHE_DURATION + ) { + console.log("[Gonka] Using cached models"); + return gonkaModelCache.models; + } + + try { + console.log("[Gonka] Fetching models from API"); + const response = await tauriFetch( + "http://node2.gonka.ai:8000/v1/epochs/current/participants", + { + method: "GET", + }, + ); + + const { data, status } = response; + + if (status === 200 && data) { + let participants: GonkaParticipant[] = []; + + // data.active_participants.participants + if (typeof data === "object" && data !== null) { + const apiData = data as any; + + if ( + apiData.active_participants?.participants && + Array.isArray(apiData.active_participants.participants) + ) { + participants = apiData.active_participants.participants; + } else if (Array.isArray(apiData.participants)) { + participants = apiData.participants; + } else if (Array.isArray(apiData)) { + participants = apiData; + } else { + console.warn( + "[Gonka] Unexpected data structure, expected active_participants.participants", + ); + return DEFAULT_GONKA_MODELS; + } + } + + if (participants.length === 0) { + console.warn("[Gonka] No participants found in response"); + return DEFAULT_GONKA_MODELS; + } + + console.log(`[Gonka] Found ${participants.length} participants`); + + // 合并去重 + const allModels: string[] = []; + participants.forEach((participant) => { + if (participant.models && Array.isArray(participant.models)) { + allModels.push(...participant.models); + } + }); + + const uniqueModels = [...new Set(allModels)]; + const modelOptions = uniqueModels.map((model) => ({ + value: model, + label: model, + })); + + if (modelOptions.length > 0) { + // 更新缓存 + gonkaModelCache = { + models: modelOptions, + timestamp: Date.now(), + }; + console.log( + `[Gonka] Fetched ${modelOptions.length} models:`, + modelOptions, + ); + return modelOptions; + } + } + + console.warn( + `[Gonka] Failed to fetch models, status: ${status}, using default`, + ); + return DEFAULT_GONKA_MODELS; + } catch (error) { + console.error("[Gonka] Error fetching models:", error); + // 如果有缓存,即使过期也返回(降级策略) + if (gonkaModelCache) { + console.log("[Gonka] Using expired cache as fallback"); + return gonkaModelCache.models; + } + return DEFAULT_GONKA_MODELS; + } +}; + +/** + * 清除 Gonka 模型缓存 + */ +export const clearGonkaModelCache = (): void => { + gonkaModelCache = null; + console.log("[Gonka] Cache cleared"); +}; diff --git a/app/store/agent.ts b/app/store/agent.ts index b6048690..ae91fd62 100644 --- a/app/store/agent.ts +++ b/app/store/agent.ts @@ -152,6 +152,8 @@ export const useAgentStore = createPersistStore( const { renderAgents, updateAgent } = get(); const agents: Agent[] = renderAgents; agents.forEach((agent) => { + if (agent.model.provider === "gonka") return; + if (models.every((m) => m.model !== agent.model.name)) { console.log("[agent handle default model]", agent.model); const defaultModel = useAppConfig.getState().defaultModel; From 395ee3d57cea7d568e84011f911851c12bbee574 Mon Sep 17 00:00:00 2001 From: zhaoqing Date: Tue, 16 Dec 2025 14:22:26 +0800 Subject: [PATCH 2/7] fix: gonka icon --- app/icons/gonka.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/icons/gonka.svg b/app/icons/gonka.svg index 939be550..e00bac68 100644 --- a/app/icons/gonka.svg +++ b/app/icons/gonka.svg @@ -1,4 +1,4 @@ - + From 13259643fcf00da0ee44bf02ee2713b426862762 Mon Sep 17 00:00:00 2001 From: ljunb Date: Fri, 19 Dec 2025 15:43:35 +0800 Subject: [PATCH 3/7] fix: display blank when switch to custom model --- app/components/agent-tab.tsx | 4 +++- app/components/setting/add-model-modal.tsx | 7 ++++++- app/store/agent.ts | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/components/agent-tab.tsx b/app/components/agent-tab.tsx index 18c5c32f..14fcb233 100644 --- a/app/components/agent-tab.tsx +++ b/app/components/agent-tab.tsx @@ -299,7 +299,9 @@ export default function AgentTab() { onClick={() => setShowModel(!showModel)} className="min-h-[18px] text-xs text-[#101213] dark:text-[#E8ECEF] min-w-0 max-w-50 flex items-center" > - {getModelInfo(item.model.name)?.display} + {item.model.apiKey + ? item.model.name + : getModelInfo(item.model.name)?.display} {showModel ? ( ) : ( diff --git a/app/components/setting/add-model-modal.tsx b/app/components/setting/add-model-modal.tsx index 04c255fc..3c68b2bb 100644 --- a/app/components/setting/add-model-modal.tsx +++ b/app/components/setting/add-model-modal.tsx @@ -1,6 +1,6 @@ "use client"; -import { useCallback, useEffect } from "react"; +import { useCallback, useEffect, useMemo } from "react"; import useState from "react-usestateref"; import { Dialog, @@ -285,6 +285,10 @@ export function AddModelModal({ } }; + const disabledSaveButton = useMemo(() => { + return isApiKeyError || isModelsError || isGettingModelLoading; + }, [isApiKeyError, isModelsError, isGettingModelLoading]); + return ( {t("dialog.save")} diff --git a/app/store/agent.ts b/app/store/agent.ts index ae91fd62..778a6961 100644 --- a/app/store/agent.ts +++ b/app/store/agent.ts @@ -152,7 +152,8 @@ export const useAgentStore = createPersistStore( const { renderAgents, updateAgent } = get(); const agents: Agent[] = renderAgents; agents.forEach((agent) => { - if (agent.model.provider === "gonka") return; + // return directly if the agent is using a custom model + if (agent.model.apiKey) return; if (models.every((m) => m.model !== agent.model.name)) { console.log("[agent handle default model]", agent.model); From eeb6bc03f68bdd2b0264c5e381a9fe6a47d94f18 Mon Sep 17 00:00:00 2001 From: ljunb Date: Sun, 21 Dec 2025 11:58:59 +0800 Subject: [PATCH 4/7] fix: rendering blank when switching custom provider --- app/components/setting/add-model-modal.tsx | 28 +--- app/components/setting/model-list.tsx | 22 +--- app/components/setting/provider-icon.tsx | 4 - app/services/model.ts | 141 +-------------------- 4 files changed, 5 insertions(+), 190 deletions(-) diff --git a/app/components/setting/add-model-modal.tsx b/app/components/setting/add-model-modal.tsx index 3c68b2bb..6b87fbc2 100644 --- a/app/components/setting/add-model-modal.tsx +++ b/app/components/setting/add-model-modal.tsx @@ -28,7 +28,6 @@ import { import { fetch } from "@tauri-apps/api/http"; import { useAppConfig } from "@/app/store"; import { toast } from "@/app/utils/toast"; -import { getGonkaModels } from "@/app/services/model"; interface ModelInfo { provider: string; @@ -190,21 +189,6 @@ export function AddModelModal({ }; const getModels = async () => { - if (formDataRef.current.provider === "gonka") { - setIsGettingModelLoading(true); - setIsModelsError(false); - try { - const models = await getGonkaModels(); - setModelList(models); - } catch (error) { - toast.error("Failed to fetch gonka models: " + error); - console.error("Error fetching gonka models:", error); - } finally { - setIsGettingModelLoading(false); - } - return; - } - const apiKey = formDataRef.current.apiKey; if (!apiKey) return; const providerInfo = providerList.find( @@ -325,22 +309,16 @@ export function AddModelModal({
state.models); const localProviders = useAppConfig((state) => state.localProviders); @@ -70,7 +50,7 @@ export default function ModelList() { async function getProviderData() { const data = await getProviderList(); if (data && data.length) { - setProviderList([...data, GonkaProvider]); + setProviderList([...data]); } } getProviderData(); diff --git a/app/components/setting/provider-icon.tsx b/app/components/setting/provider-icon.tsx index 5701f7c0..2f622cbc 100644 --- a/app/components/setting/provider-icon.tsx +++ b/app/components/setting/provider-icon.tsx @@ -6,7 +6,6 @@ import AnthropicIconDark from "@/app/icons/anthropic-dark.svg"; import GoogleIcon from "@/app/icons/google.svg"; import AidenLightIcon from "@/app/icons/default-aiden.svg"; import AidenDarkIcon from "@/app/icons/logo-circle.svg"; -import GonkaIcon from "@/app/icons/gonka.svg"; import clsx from "clsx"; export function ProviderIcon({ @@ -32,9 +31,6 @@ export function ProviderIcon({ if (provider === "gemini") { return ; } - if (provider === "gonka") { - return ; - } return theme === Theme.Light ? ( diff --git a/app/services/model.ts b/app/services/model.ts index f81a8400..e62d30aa 100644 --- a/app/services/model.ts +++ b/app/services/model.ts @@ -1,6 +1,5 @@ import { aidenFetch as fetch } from "@/app/utils/fetch"; -import { ModelOption, ProviderOption, CustomModelOption } from "../typing"; -import { fetch as tauriFetch } from "@tauri-apps/api/http"; +import { ModelOption, ProviderOption } from "../typing"; export const getModelList = async (): Promise => { const { data, status } = await fetch("/api/v1/models", { @@ -29,141 +28,3 @@ export const getProviderList = async (): Promise => { } return []; }; - -// Gonka API 响应类型定义 -interface GonkaParticipant { - index: string; - validator_key: string; - weight: number; - inference_url: string; - models: string[]; - seed?: any; - ml_nodes?: any[]; -} - -// Gonka 模型缓存 -interface GonkaModelCache { - models: CustomModelOption[]; - timestamp: number; -} - -let gonkaModelCache: GonkaModelCache | null = null; -const CACHE_DURATION = 5 * 60 * 1000; // 5分钟缓存 - -// 默认 Gonka 模型(作为后备) -const DEFAULT_GONKA_MODELS: CustomModelOption[] = [ - { - value: "Qwen/Qwen3-235B-A22B-Instruct-2507-FP8", - label: "Qwen3-235B-A22B-Instruct-2507-FP8", - }, -]; - -/** - * 获取 Gonka 模型列表 - * @param forceRefresh 是否强制刷新缓存 - * @returns CustomModelOption[] 模型列表 - */ -export const getGonkaModels = async ( - forceRefresh: boolean = false, -): Promise => { - if ( - !forceRefresh && - gonkaModelCache && - Date.now() - gonkaModelCache.timestamp < CACHE_DURATION - ) { - console.log("[Gonka] Using cached models"); - return gonkaModelCache.models; - } - - try { - console.log("[Gonka] Fetching models from API"); - const response = await tauriFetch( - "http://node2.gonka.ai:8000/v1/epochs/current/participants", - { - method: "GET", - }, - ); - - const { data, status } = response; - - if (status === 200 && data) { - let participants: GonkaParticipant[] = []; - - // data.active_participants.participants - if (typeof data === "object" && data !== null) { - const apiData = data as any; - - if ( - apiData.active_participants?.participants && - Array.isArray(apiData.active_participants.participants) - ) { - participants = apiData.active_participants.participants; - } else if (Array.isArray(apiData.participants)) { - participants = apiData.participants; - } else if (Array.isArray(apiData)) { - participants = apiData; - } else { - console.warn( - "[Gonka] Unexpected data structure, expected active_participants.participants", - ); - return DEFAULT_GONKA_MODELS; - } - } - - if (participants.length === 0) { - console.warn("[Gonka] No participants found in response"); - return DEFAULT_GONKA_MODELS; - } - - console.log(`[Gonka] Found ${participants.length} participants`); - - // 合并去重 - const allModels: string[] = []; - participants.forEach((participant) => { - if (participant.models && Array.isArray(participant.models)) { - allModels.push(...participant.models); - } - }); - - const uniqueModels = [...new Set(allModels)]; - const modelOptions = uniqueModels.map((model) => ({ - value: model, - label: model, - })); - - if (modelOptions.length > 0) { - // 更新缓存 - gonkaModelCache = { - models: modelOptions, - timestamp: Date.now(), - }; - console.log( - `[Gonka] Fetched ${modelOptions.length} models:`, - modelOptions, - ); - return modelOptions; - } - } - - console.warn( - `[Gonka] Failed to fetch models, status: ${status}, using default`, - ); - return DEFAULT_GONKA_MODELS; - } catch (error) { - console.error("[Gonka] Error fetching models:", error); - // 如果有缓存,即使过期也返回(降级策略) - if (gonkaModelCache) { - console.log("[Gonka] Using expired cache as fallback"); - return gonkaModelCache.models; - } - return DEFAULT_GONKA_MODELS; - } -}; - -/** - * 清除 Gonka 模型缓存 - */ -export const clearGonkaModelCache = (): void => { - gonkaModelCache = null; - console.log("[Gonka] Cache cleared"); -}; From ec7230c587a65053a184d8b25b3b64e524c70ddc Mon Sep 17 00:00:00 2001 From: ljunb Date: Sun, 21 Dec 2025 12:06:53 +0800 Subject: [PATCH 5/7] chore: remove gonka files --- app/components/setting/model-list.tsx | 2 +- app/icons/gonka.svg | 4 ---- app/locales/en-US/settings.json | 4 +--- app/locales/zh-CN/settings.json | 4 +--- 4 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 app/icons/gonka.svg diff --git a/app/components/setting/model-list.tsx b/app/components/setting/model-list.tsx index 90191321..ec52e8bc 100644 --- a/app/components/setting/model-list.tsx +++ b/app/components/setting/model-list.tsx @@ -50,7 +50,7 @@ export default function ModelList() { async function getProviderData() { const data = await getProviderList(); if (data && data.length) { - setProviderList([...data]); + setProviderList(data); } } getProviderData(); diff --git a/app/icons/gonka.svg b/app/icons/gonka.svg deleted file mode 100644 index e00bac68..00000000 --- a/app/icons/gonka.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/app/locales/en-US/settings.json b/app/locales/en-US/settings.json index c252a371..53b565a2 100644 --- a/app/locales/en-US/settings.json +++ b/app/locales/en-US/settings.json @@ -72,9 +72,7 @@ "apiKeyErrorText": "Please enter API Key", "modelErrorText": "Please select models", "deleteSuccess": "Deleted successfully", - "enterApiKey": "Enter API Key", - "privateKey": "Private Key", - "enterPrivateKey": "Enter private key" + "enterApiKey": "Enter API Key" }, "mcp": { "inValidEmail": "Please enter a valid email address", diff --git a/app/locales/zh-CN/settings.json b/app/locales/zh-CN/settings.json index 2ef4b3a8..511ba64c 100644 --- a/app/locales/zh-CN/settings.json +++ b/app/locales/zh-CN/settings.json @@ -72,9 +72,7 @@ "apiKeyErrorText": "请输入 API Key", "modelErrorText": "请选择模型", "deleteSuccess": "删除成功", - "enterApiKey": "输入 API Key", - "privateKey": "私钥", - "enterPrivateKey": "输入私钥" + "enterApiKey": "输入 API Key" }, "mcp": { "inValidEmail": "请输入有效的邮箱地址", From 4056f311fb7220131d70c04d8a1b77f056cd3b5d Mon Sep 17 00:00:00 2001 From: ljunb Date: Sun, 21 Dec 2025 21:22:51 +0800 Subject: [PATCH 6/7] fix: model value mapping --- app/components/agent-list.tsx | 28 +++- app/components/agent-management.tsx | 28 +++- app/components/agent-tab.tsx | 20 ++- app/components/setting/add-model-modal.tsx | 165 ++++++--------------- app/store/index.ts | 1 + app/store/model.ts | 159 ++++++++++++++++++++ app/utils/model.ts | 28 ++++ 7 files changed, 297 insertions(+), 132 deletions(-) create mode 100644 app/store/model.ts diff --git a/app/components/agent-list.tsx b/app/components/agent-list.tsx index 0484622f..c82444ec 100644 --- a/app/components/agent-list.tsx +++ b/app/components/agent-list.tsx @@ -1,14 +1,15 @@ -import { useAgentStore } from "../store"; +import { useAgentStore, useModelStore } from "../store"; import Image from "next/image"; import { Theme } from "@/app/store"; import { useMemo, useCallback } from "react"; import { useTheme } from "../hooks/use-theme"; import { ProviderIcon } from "./setting/provider-icon"; import { useAppConfig } from "../store"; -import { Agent, AgentSource } from "../typing"; +import { Agent, AgentSource, ModelOption } from "../typing"; import { Switch } from "./shadcn/switch"; import { Button } from "./shadcn/button"; import { useTranslation } from "react-i18next"; +import { getModelDisplayText } from "../utils/model"; interface AgentItemProps { item: Agent; @@ -49,6 +50,25 @@ function AgentItem({ item, onEdit }: AgentItemProps) { return modelList.find((model) => model.model === item.model.name); }, [modelList, item.model.name]); + const formattedModelListMap = useModelStore( + (state) => state.formattedModelList, + ); + + const getDisplayText = useCallback( + (modelItem: ModelOption | UserModel): string => { + return getModelDisplayText( + { + model: modelItem.model, + provider: modelItem.provider, + display: modelItem.display, + apiKey: "apiKey" in modelItem ? modelItem.apiKey : undefined, + }, + formattedModelListMap, + ); + }, + [formattedModelListMap], + ); + const handleSwitch = async (checked: boolean) => { if (checked !== item.enabled) { updateAgent({ @@ -120,7 +140,9 @@ function AgentItem({ item, onEdit }: AgentItemProps) {
{renderProviderIcon()}
-

{currentModel?.display}

+

+ {currentModel ? getDisplayText(currentModel) : ""} +