diff --git a/packages/app/src/components/dialog-settings.tsx b/packages/app/src/components/dialog-settings.tsx index 9dd6efd68..5efee5a3c 100644 --- a/packages/app/src/components/dialog-settings.tsx +++ b/packages/app/src/components/dialog-settings.tsx @@ -6,12 +6,8 @@ import { useLanguage } from "@/context/language" import { usePlatform } from "@/context/platform" import { SettingsGeneral } from "./settings-general" import { SettingsKeybinds } from "./settings-keybinds" -import { SettingsPermissions } from "./settings-permissions" import { SettingsProviders } from "./settings-providers" import { SettingsModels } from "./settings-models" -import { SettingsAgents } from "./settings-agents" -import { SettingsCommands } from "./settings-commands" -import { SettingsMcp } from "./settings-mcp" export const DialogSettings: Component = () => { const language = useLanguage() @@ -45,6 +41,10 @@ export const DialogSettings: Component = () => { {language.t("settings.providers.title")} + + + {language.t("settings.models.title")} + @@ -64,9 +64,9 @@ export const DialogSettings: Component = () => { - {/* */} - {/* */} - {/* */} + + + {/* */} {/* */} {/* */} diff --git a/packages/app/src/components/settings-models.tsx b/packages/app/src/components/settings-models.tsx index 6a636879d..a3ba45f61 100644 --- a/packages/app/src/components/settings-models.tsx +++ b/packages/app/src/components/settings-models.tsx @@ -1,14 +1,135 @@ -import { Component } from "solid-js" +import { useFilteredList } from "@opencode-ai/ui/hooks" +import { ProviderIcon } from "@opencode-ai/ui/provider-icon" +import { Switch } from "@opencode-ai/ui/switch" +import { Icon } from "@opencode-ai/ui/icon" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { TextField } from "@opencode-ai/ui/text-field" +import type { IconName } from "@opencode-ai/ui/icons/provider" +import { type Component, For, Show } from "solid-js" import { useLanguage } from "@/context/language" +import { type ModelKey, useLocal } from "@/context/local" +import { popularProviders } from "@/hooks/use-providers" + +type ModelItem = ReturnType["model"]["list"]>[number] export const SettingsModels: Component = () => { + const local = useLocal() const language = useLanguage() + const list = useFilteredList({ + items: (_filter) => local.model.list(), + key: (x) => `${x.provider.id}:${x.id}`, + filterKeys: ["provider.name", "name", "id"], + sortBy: (a, b) => a.name.localeCompare(b.name), + groupBy: (x) => x.provider.id, + sortGroupsBy: (a, b) => { + const aIndex = popularProviders.indexOf(a.category) + const bIndex = popularProviders.indexOf(b.category) + const aPopular = aIndex >= 0 + const bPopular = bIndex >= 0 + + if (aPopular && !bPopular) return -1 + if (!aPopular && bPopular) return 1 + if (aPopular && bPopular) return aIndex - bIndex + + const aName = a.items[0].provider.name + const bName = b.items[0].provider.name + return aName.localeCompare(bName) + }, + }) + return ( -
-
-

{language.t("settings.models.title")}

-

{language.t("settings.models.description")}

+
+
+
+

{language.t("settings.models.title")}

+
+ + + + + +
+
+
+ +
+ + + {language.t("common.loading")} + {language.t("common.loading.ellipsis")} + +
+ } + > + 0} + fallback={ +
+ {language.t("dialog.model.empty")} + + "{list.filter()}" + +
+ } + > + + {(group) => ( +
+
+ + {group.items[0].provider.name} +
+
+ + {(item) => { + const key: ModelKey = { providerID: item.provider.id, modelID: item.id } + return ( +
+
+ {item.name} +
+
+ { + local.model.setVisibility(key, checked) + }} + hideLabel + > + {item.name} + +
+
+ ) + }} +
+
+
+ )} +
+
+
)