+
{t('providerModelSelector.modelDeprecated')}
{selectedModel.deprecationReason && (
@@ -196,7 +229,6 @@ export function ProviderModelSelector({
)}
- {/* Model description */}
{selectedModel?.description && !selectedModel.broken && !selectedModel.deprecated && (
{selectedModel.description}
)}
@@ -226,27 +258,26 @@ export function ModelMappingSelector({
return (
-
+
({
+ value: model.id,
+ searchText: `${model.name} ${model.id}`,
+ triggerContent: {model.id},
+ itemContent: (
+
+
{model.name}
+ {model.tier === 'paid' &&
}
+
+ ),
+ }))}
+ />
);
}
@@ -272,10 +303,50 @@ export function FlexibleModelSelector({
disabled,
}: FlexibleModelSelectorProps) {
const { t } = useTranslation();
- // Combine catalog models (recommended) with all available models
- const catalogModelIds = new Set(catalog?.models.map((m) => m.id) || []);
+ const catalogModelIds = new Set(catalog?.models.map((model) => model.id) || []);
const isCodexProvider = catalog?.provider === 'codex';
- const selectedCodexEffort = isCodexProvider ? getCodexEffortDisplay(value) : null;
+
+ const recommendedOptions = (catalog?.models ?? []).map((model) => ({
+ value: model.id,
+ groupKey: 'recommended',
+ searchText: `${model.id} ${model.name}`,
+ keywords: [model.tier ?? '', catalog?.provider ?? ''],
+ triggerContent: (
+
+ {model.id}
+ {isCodexProvider && }
+
+ ),
+ itemContent: (
+
+
{model.id}
+ {model.tier === 'paid' &&
}
+ {isCodexProvider &&
}
+
+ ),
+ }));
+
+ const allModelOptions = allModels
+ .filter((model) => !catalogModelIds.has(model.id))
+ .map((model) => ({
+ value: model.id,
+ groupKey: 'all',
+ searchText: model.id,
+ keywords: [model.owned_by],
+ triggerContent: (
+
+ {model.id}
+ {isCodexProvider && }
+
+ ),
+ itemContent: (
+
+ {model.id}
+ {isCodexProvider && }
+
+ ),
+ }));
+ const hasAvailableModels = recommendedOptions.length + allModelOptions.length > 0;
return (
@@ -283,96 +354,36 @@ export function FlexibleModelSelector({
{description &&
{description}
}
-
+
+ ),
+ },
+ ]}
+ options={[...recommendedOptions, ...allModelOptions]}
+ />
);
}
diff --git a/ui/src/components/copilot/config-form/model-selector.tsx b/ui/src/components/copilot/config-form/model-selector.tsx
index 1f3a91f0..6d5448a9 100644
--- a/ui/src/components/copilot/config-form/model-selector.tsx
+++ b/ui/src/components/copilot/config-form/model-selector.tsx
@@ -4,16 +4,7 @@
*/
import { Badge } from '@/components/ui/badge';
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
- SelectGroup,
- SelectLabel,
-} from '@/components/ui/select';
-import { Check } from 'lucide-react';
+import { SearchableSelect } from '@/components/ui/searchable-select';
import type { FlexibleModelSelectorProps } from './types';
import { getPlanBadgeStyle, getMultiplierDisplay } from './utils';
import { useTranslation } from 'react-i18next';
@@ -27,8 +18,6 @@ export function FlexibleModelSelector({
disabled,
}: FlexibleModelSelectorProps) {
const { t } = useTranslation();
- // Find current model for display
- const currentModel = models.find((m) => m.id === value);
return (