refactor: remove allows_unlisted_models flag, always allow custom model entry (#7255)

Signed-off-by: clayarnoldg2m <carnold@g2m.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Clay
2026-02-23 09:23:00 +13:00
committed by GitHub
parent c8d4057dd1
commit aa05308803
16 changed files with 16 additions and 56 deletions
+10 -14
View File
@@ -466,13 +466,11 @@ fn select_model_from_list(
), ),
); );
if provider_meta.allows_unlisted_models { model_items.push((
model_items.push(( UNLISTED_MODEL_KEY.to_string(),
UNLISTED_MODEL_KEY.to_string(), "Enter a model not listed...".to_string(),
"Enter a model not listed...".to_string(), "",
"", ));
));
}
let selection = cliclack::select("Select a model:") let selection = cliclack::select("Select a model:")
.items(&model_items) .items(&model_items)
@@ -492,13 +490,11 @@ fn select_model_from_list(
let mut model_items: Vec<(String, String, &str)> = let mut model_items: Vec<(String, String, &str)> =
models.iter().map(|m| (m.clone(), m.clone(), "")).collect(); models.iter().map(|m| (m.clone(), m.clone(), "")).collect();
if provider_meta.allows_unlisted_models { model_items.push((
model_items.push(( UNLISTED_MODEL_KEY.to_string(),
UNLISTED_MODEL_KEY.to_string(), "Enter a model not listed...".to_string(),
"Enter a model not listed...".to_string(), "",
"", ));
));
}
let selection = cliclack::select("Select a model:") let selection = cliclack::select("Select a model:")
.items(&model_items) .items(&model_items)
-12
View File
@@ -175,9 +175,6 @@ pub struct ProviderMetadata {
pub model_doc_link: String, pub model_doc_link: String,
/// Required configuration keys /// Required configuration keys
pub config_keys: Vec<ConfigKey>, pub config_keys: Vec<ConfigKey>,
/// Whether this provider allows entering model names not in the fetched list
#[serde(default)]
pub allows_unlisted_models: bool,
} }
impl ProviderMetadata { impl ProviderMetadata {
@@ -210,7 +207,6 @@ impl ProviderMetadata {
.collect(), .collect(),
model_doc_link: model_doc_link.to_string(), model_doc_link: model_doc_link.to_string(),
config_keys, config_keys,
allows_unlisted_models: false,
} }
} }
@@ -231,7 +227,6 @@ impl ProviderMetadata {
known_models: models, known_models: models,
model_doc_link: model_doc_link.to_string(), model_doc_link: model_doc_link.to_string(),
config_keys, config_keys,
allows_unlisted_models: false,
} }
} }
@@ -244,15 +239,8 @@ impl ProviderMetadata {
known_models: vec![], known_models: vec![],
model_doc_link: "".to_string(), model_doc_link: "".to_string(),
config_keys: vec![], config_keys: vec![],
allows_unlisted_models: false,
} }
} }
/// Set allows_unlisted_models flag (builder pattern)
pub fn with_unlisted_models(mut self) -> Self {
self.allows_unlisted_models = true;
self
}
} }
/// Configuration key metadata for provider setup /// Configuration key metadata for provider setup
@@ -864,7 +864,6 @@ impl ProviderDef for ChatGptCodexProvider {
false, false,
)], )],
) )
.with_unlisted_models()
} }
fn from_env( fn from_env(
@@ -487,10 +487,6 @@ impl ProviderDef for ClaudeCodeProvider {
true, false, true, true, false, true,
)], )],
) )
// The model list only returns aliases the `claude` CLI uses, such as "default"
// and "haiku". There is no listing that includes full names like
// "claude-sonnet-4-5-20250929". However, they are permitted.
.with_unlisted_models()
} }
fn from_env( fn from_env(
-1
View File
@@ -605,7 +605,6 @@ impl ProviderDef for CodexProvider {
ConfigKey::from_value_type::<CodexSkipGitCheck>(false, false, true), ConfigKey::from_value_type::<CodexSkipGitCheck>(false, false, true),
], ],
) )
.with_unlisted_models()
} }
fn from_env( fn from_env(
@@ -294,7 +294,6 @@ impl ProviderDef for CursorAgentProvider {
true, false, true, true, false, true,
)], )],
) )
.with_unlisted_models()
} }
fn from_env( fn from_env(
@@ -541,7 +541,6 @@ impl ProviderDef for GcpVertexAIProvider {
), ),
], ],
) )
.with_unlisted_models()
} }
fn from_env( fn from_env(
@@ -742,6 +741,5 @@ mod tests {
assert!(!metadata.known_models.is_empty()); assert!(!metadata.known_models.is_empty());
assert_eq!(metadata.default_model, "gemini-2.5-flash"); assert_eq!(metadata.default_model, "gemini-2.5-flash");
assert_eq!(metadata.config_keys.len(), 6); assert_eq!(metadata.config_keys.len(), 6);
assert!(metadata.allows_unlisted_models);
} }
} }
-1
View File
@@ -169,7 +169,6 @@ impl ProviderDef for GeminiCliProvider {
true, false, true, true, false, true,
)], )],
) )
.with_unlisted_models()
} }
fn from_env( fn from_env(
-1
View File
@@ -168,7 +168,6 @@ impl ProviderDef for OpenRouterProvider {
), ),
], ],
) )
.with_unlisted_models()
} }
fn from_env( fn from_env(
@@ -127,7 +127,6 @@ impl ProviderRegistry {
known_models, known_models,
model_doc_link: base_metadata.model_doc_link, model_doc_link: base_metadata.model_doc_link,
config_keys, config_keys,
allows_unlisted_models: false,
}; };
self.entries.insert( self.entries.insert(
-1
View File
@@ -372,7 +372,6 @@ mod tests {
known_models: vec![], known_models: vec![],
model_doc_link: "".to_string(), model_doc_link: "".to_string(),
config_keys: vec![], config_keys: vec![],
allows_unlisted_models: false,
} }
} }
-1
View File
@@ -190,7 +190,6 @@ impl ProviderDef for MockCompactionProvider {
known_models: vec![], known_models: vec![],
model_doc_link: "".to_string(), model_doc_link: "".to_string(),
config_keys: vec![], config_keys: vec![],
allows_unlisted_models: false,
} }
} }
-4
View File
@@ -6154,10 +6154,6 @@
"config_keys" "config_keys"
], ],
"properties": { "properties": {
"allows_unlisted_models": {
"type": "boolean",
"description": "Whether this provider allows entering model names not in the fetched list"
},
"config_keys": { "config_keys": {
"type": "array", "type": "array",
"items": { "items": {
-4
View File
@@ -832,10 +832,6 @@ export type ProviderEngine = 'openai' | 'ollama' | 'anthropic';
* Metadata about a provider's configuration requirements and capabilities * Metadata about a provider's configuration requirements and capabilities
*/ */
export type ProviderMetadata = { export type ProviderMetadata = {
/**
* Whether this provider allows entering model names not in the fetched list
*/
allows_unlisted_models?: boolean;
/** /**
* Required configuration keys * Required configuration keys
*/ */
@@ -60,13 +60,11 @@ export const RecipeModelSelector = ({
provider: p.name, provider: p.name,
})); }));
if (p.metadata.allows_unlisted_models) { options.push({
options.push({ value: `__custom__:${p.name}`,
value: `__custom__:${p.name}`, label: 'Enter a model not listed...',
label: 'Enter a model not listed...', provider: p.name,
provider: p.name, });
});
}
if (options.length > 0) { if (options.length > 0) {
groupedOptions.push({ options }); groupedOptions.push({ options });
@@ -250,7 +250,7 @@ export const SwitchModelModal = ({
providerType: p.provider_type, providerType: p.provider_type,
})); }));
if (p.metadata.allows_unlisted_models && p.provider_type !== 'Custom') { if (p.provider_type !== 'Custom') {
options.push({ options.push({
value: 'custom', value: 'custom',
label: 'Enter a model not listed...', label: 'Enter a model not listed...',