Distinguish between missing models and registries in error messages (#32678)

Consolidates configuration error handling by moving the error type and
logic from assistant_context_editor to language_model::registry.

The registry now provides a single method to check for configuration
errors, making the error handling more consistent across the agent panel
and context editor.

This also now checks if the issue is that we don't have any providers,
or if we just can't find the model.

Previously, an incorrect model name showed up as having no providers,
which is very confusing.

Release Notes:

- N/A
This commit is contained in:
Ben Brandt 2025-06-13 12:31:52 +02:00 committed by GitHub
parent fc7c106b2a
commit 9427833fdf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 218 additions and 207 deletions

View file

@ -39,7 +39,7 @@ use language::{
language_settings::{SoftWrap, all_language_settings},
};
use language_model::{
LanguageModelImage, LanguageModelProvider, LanguageModelProviderTosView, LanguageModelRegistry,
ConfigurationError, LanguageModelImage, LanguageModelProviderTosView, LanguageModelRegistry,
Role,
};
use multi_buffer::MultiBufferRow;
@ -1887,6 +1887,8 @@ impl ContextEditor {
// value to not show the nudge.
let nudge = Some(false);
let model_registry = LanguageModelRegistry::read_global(cx);
if nudge.map_or(false, |value| value) {
Some(
h_flex()
@ -1935,14 +1937,9 @@ impl ContextEditor {
)
.into_any_element(),
)
} else if let Some(configuration_error) = configuration_error(cx) {
let label = match configuration_error {
ConfigurationError::NoProvider => "No LLM provider selected.",
ConfigurationError::ProviderNotAuthenticated => "LLM provider is not configured.",
ConfigurationError::ProviderPendingTermsAcceptance(_) => {
"LLM provider requires accepting the Terms of Service."
}
};
} else if let Some(configuration_error) =
model_registry.configuration_error(model_registry.default_model(), cx)
{
Some(
h_flex()
.px_3()
@ -1959,7 +1956,7 @@ impl ContextEditor {
.size(IconSize::Small)
.color(Color::Warning),
)
.child(Label::new(label)),
.child(Label::new(configuration_error.to_string())),
)
.child(
Button::new("open-configuration", "Configure Providers")
@ -2034,14 +2031,19 @@ impl ContextEditor {
/// Will return false if the selected provided has a configuration error or
/// if the user has not accepted the terms of service for this provider.
fn sending_disabled(&self, cx: &mut Context<'_, ContextEditor>) -> bool {
let model = LanguageModelRegistry::read_global(cx).default_model();
let model_registry = LanguageModelRegistry::read_global(cx);
let Some(configuration_error) =
model_registry.configuration_error(model_registry.default_model(), cx)
else {
return false;
};
let has_configuration_error = configuration_error(cx).is_some();
let needs_to_accept_terms = self.show_accept_terms
&& model
.as_ref()
.map_or(false, |model| model.provider.must_accept_terms(cx));
has_configuration_error || needs_to_accept_terms
match configuration_error {
ConfigurationError::NoProvider
| ConfigurationError::ModelNotFound
| ConfigurationError::ProviderNotAuthenticated(_) => true,
ConfigurationError::ProviderPendingTermsAcceptance(_) => self.show_accept_terms,
}
}
fn render_inject_context_menu(&self, cx: &mut Context<Self>) -> impl IntoElement {
@ -3180,33 +3182,6 @@ fn size_for_image(data: &RenderImage, max_size: Size<Pixels>) -> Size<Pixels> {
}
}
pub enum ConfigurationError {
NoProvider,
ProviderNotAuthenticated,
ProviderPendingTermsAcceptance(Arc<dyn LanguageModelProvider>),
}
fn configuration_error(cx: &App) -> Option<ConfigurationError> {
let model = LanguageModelRegistry::read_global(cx).default_model();
let is_authenticated = model
.as_ref()
.map_or(false, |model| model.provider.is_authenticated(cx));
if model.is_some() && is_authenticated {
return None;
}
if model.is_none() {
return Some(ConfigurationError::NoProvider);
}
if !is_authenticated {
return Some(ConfigurationError::ProviderNotAuthenticated);
}
None
}
pub fn humanize_token_count(count: usize) -> String {
match count {
0..=999 => count.to_string(),