diff --git a/apps/x/apps/renderer/src/components/chat-input-with-mentions.tsx b/apps/x/apps/renderer/src/components/chat-input-with-mentions.tsx index a4501039..34272d77 100644 --- a/apps/x/apps/renderer/src/components/chat-input-with-mentions.tsx +++ b/apps/x/apps/renderer/src/components/chat-input-with-mentions.tsx @@ -152,9 +152,19 @@ function ChatInputInner({ } } } + const defaultKey = parsed?.provider?.flavor && parsed?.model + ? `${parsed.provider.flavor}/${parsed.model}` + : '' + models.sort((a, b) => { + const aKey = `${a.flavor}/${a.model}` + const bKey = `${b.flavor}/${b.model}` + if (aKey === defaultKey) return -1 + if (bKey === defaultKey) return 1 + return 0 + }) setConfiguredModels(models) - if (parsed?.provider?.flavor && parsed?.model) { - setActiveModelKey(`${parsed.provider.flavor}/${parsed.model}`) + if (defaultKey) { + setActiveModelKey(defaultKey) } } catch { // No config yet diff --git a/apps/x/apps/renderer/src/components/settings-dialog.tsx b/apps/x/apps/renderer/src/components/settings-dialog.tsx index 2965308e..3c129e80 100644 --- a/apps/x/apps/renderer/src/components/settings-dialog.tsx +++ b/apps/x/apps/renderer/src/components/settings-dialog.tsx @@ -167,6 +167,7 @@ const defaultBaseURLs: Partial> = { function ModelSettings({ dialogOpen }: { dialogOpen: boolean }) { const [provider, setProvider] = useState("openai") + const [defaultProvider, setDefaultProvider] = useState(null) const [providerConfigs, setProviderConfigs] = useState>({ openai: { apiKey: "", baseURL: "", models: [""], knowledgeGraphModel: "" }, anthropic: { apiKey: "", baseURL: "", models: [""], knowledgeGraphModel: "" }, @@ -257,6 +258,7 @@ function ModelSettings({ dialogOpen }: { dialogOpen: boolean }) { if (parsed?.provider?.flavor && parsed?.model) { const flavor = parsed.provider.flavor as LlmProviderFlavor setProvider(flavor) + setDefaultProvider(flavor) setProviderConfigs(prev => { const next = { ...prev }; // Hydrate all saved providers from the providers map @@ -362,6 +364,7 @@ function ModelSettings({ dialogOpen }: { dialogOpen: boolean }) { const result = await window.ipc.invoke("models:test", providerConfig) if (result.success) { await window.ipc.invoke("models:saveConfig", providerConfig) + setDefaultProvider(provider) setTestState({ status: "success" }) toast.success("Model configuration saved") } else { @@ -374,24 +377,70 @@ function ModelSettings({ dialogOpen }: { dialogOpen: boolean }) { } }, [canTest, provider, activeConfig]) - const renderProviderCard = (p: { id: LlmProviderFlavor; name: string; description: string }) => ( - - ) + const handleSetDefault = useCallback(async (prov: LlmProviderFlavor) => { + const config = providerConfigs[prov] + const allModels = config.models.map(m => m.trim()).filter(Boolean) + if (!allModels[0]) return + try { + await window.ipc.invoke("models:saveConfig", { + provider: { + flavor: prov, + apiKey: config.apiKey.trim() || undefined, + baseURL: config.baseURL.trim() || undefined, + }, + model: allModels[0], + models: allModels, + knowledgeGraphModel: config.knowledgeGraphModel.trim() || undefined, + }) + setDefaultProvider(prov) + toast.success("Default provider updated") + } catch { + toast.error("Failed to set default provider") + } + }, [providerConfigs]) + + const renderProviderCard = (p: { id: LlmProviderFlavor; name: string; description: string }) => { + const isDefault = defaultProvider === p.id + const isSelected = provider === p.id + const hasModel = providerConfigs[p.id].models[0]?.trim().length > 0 + return ( + + ) + } if (configLoading) { return (