Browse Source

fix: model dialog issue when searching for models in fav/recents list, also ensure that deprecated models dont appear in list (#7429)

Aiden Cline 1 month ago
parent
commit
07dc1f8ecc

+ 68 - 66
packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx

@@ -33,76 +33,82 @@ export function DialogModel(props: { providerID?: string }) {
 
   const options = createMemo(() => {
     const q = query()
-    const favorites = showExtra() ? local.model.favorite() : []
+    const needle = q.trim()
+    const showSections = showExtra() && needle.length === 0
+    const favorites = connected() ? local.model.favorite() : []
     const recents = local.model.recent()
 
-    const recentList = showExtra()
+    const recentList = showSections
       ? recents.filter(
           (item) => !favorites.some((fav) => fav.providerID === item.providerID && fav.modelID === item.modelID),
         )
       : []
 
-    const favoriteOptions = favorites.flatMap((item) => {
-      const provider = sync.data.provider.find((x) => x.id === item.providerID)
-      if (!provider) return []
-      const model = provider.models[item.modelID]
-      if (!model) return []
-      return [
-        {
-          key: item,
-          value: {
-            providerID: provider.id,
-            modelID: model.id,
-          },
-          title: model.name ?? item.modelID,
-          description: provider.name,
-          category: "Favorites",
-          disabled: provider.id === "opencode" && model.id.includes("-nano"),
-          footer: model.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined,
-          onSelect: () => {
-            dialog.clear()
-            local.model.set(
-              {
+    const favoriteOptions = showSections
+      ? favorites.flatMap((item) => {
+          const provider = sync.data.provider.find((x) => x.id === item.providerID)
+          if (!provider) return []
+          const model = provider.models[item.modelID]
+          if (!model) return []
+          return [
+            {
+              key: item,
+              value: {
                 providerID: provider.id,
                 modelID: model.id,
               },
-              { recent: true },
-            )
-          },
-        },
-      ]
-    })
+              title: model.name ?? item.modelID,
+              description: provider.name,
+              category: "Favorites",
+              disabled: provider.id === "opencode" && model.id.includes("-nano"),
+              footer: model.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined,
+              onSelect: () => {
+                dialog.clear()
+                local.model.set(
+                  {
+                    providerID: provider.id,
+                    modelID: model.id,
+                  },
+                  { recent: true },
+                )
+              },
+            },
+          ]
+        })
+      : []
 
-    const recentOptions = recentList.flatMap((item) => {
-      const provider = sync.data.provider.find((x) => x.id === item.providerID)
-      if (!provider) return []
-      const model = provider.models[item.modelID]
-      if (!model) return []
-      return [
-        {
-          key: item,
-          value: {
-            providerID: provider.id,
-            modelID: model.id,
-          },
-          title: model.name ?? item.modelID,
-          description: provider.name,
-          category: "Recent",
-          disabled: provider.id === "opencode" && model.id.includes("-nano"),
-          footer: model.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined,
-          onSelect: () => {
-            dialog.clear()
-            local.model.set(
-              {
+    const recentOptions = showSections
+      ? recentList.flatMap((item) => {
+          const provider = sync.data.provider.find((x) => x.id === item.providerID)
+          if (!provider) return []
+          const model = provider.models[item.modelID]
+          if (!model) return []
+          return [
+            {
+              key: item,
+              value: {
                 providerID: provider.id,
                 modelID: model.id,
               },
-              { recent: true },
-            )
-          },
-        },
-      ]
-    })
+              title: model.name ?? item.modelID,
+              description: provider.name,
+              category: "Recent",
+              disabled: provider.id === "opencode" && model.id.includes("-nano"),
+              footer: model.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined,
+              onSelect: () => {
+                dialog.clear()
+                local.model.set(
+                  {
+                    providerID: provider.id,
+                    modelID: model.id,
+                  },
+                  { recent: true },
+                )
+              },
+            },
+          ]
+        })
+      : []
 
     const providerOptions = pipe(
       sync.data.provider,
@@ -145,6 +151,7 @@ export function DialogModel(props: { providerID?: string }) {
             }
           }),
           filter((x) => {
+            if (!showSections) return true
             const value = x.value
             const inFavorites = favorites.some(
               (item) => item.providerID === value.providerID && item.modelID === value.modelID,
@@ -177,16 +184,11 @@ export function DialogModel(props: { providerID?: string }) {
         )
       : []
 
-    // Apply fuzzy filtering to each section separately, maintaining section order
-    if (q) {
-      const filteredFavorites = fuzzysort.go(q, favoriteOptions, { keys: ["title"] }).map((x) => x.obj)
-      const filteredRecents = fuzzysort
-        .go(q, recentOptions, { keys: ["title"] })
-        .map((x) => x.obj)
-        .slice(0, 5)
-      const filteredProviders = fuzzysort.go(q, providerOptions, { keys: ["title", "category"] }).map((x) => x.obj)
-      const filteredPopular = fuzzysort.go(q, popularProviders, { keys: ["title"] }).map((x) => x.obj)
-      return [...filteredFavorites, ...filteredRecents, ...filteredProviders, ...filteredPopular]
+    // Search shows a single merged list (favorites inline)
+    if (needle) {
+      const filteredProviders = fuzzysort.go(needle, providerOptions, { keys: ["title", "category"] }).map((x) => x.obj)
+      const filteredPopular = fuzzysort.go(needle, popularProviders, { keys: ["title"] }).map((x) => x.obj)
+      return [...filteredProviders, ...filteredPopular]
     }
 
     return [...favoriteOptions, ...recentOptions, ...providerOptions, ...popularProviders]

+ 1 - 0
packages/opencode/src/provider/provider.ts

@@ -852,6 +852,7 @@ export namespace Provider {
         if (modelID === "gpt-5-chat-latest" || (providerID === "openrouter" && modelID === "openai/gpt-5-chat"))
           delete provider.models[modelID]
         if (model.status === "alpha" && !Flag.OPENCODE_ENABLE_EXPERIMENTAL_MODELS) delete provider.models[modelID]
+        if (model.status === "deprecated") delete provider.models[modelID]
         if (
           (configProvider?.blacklist && configProvider.blacklist.includes(modelID)) ||
           (configProvider?.whitelist && !configProvider.whitelist.includes(modelID))