language_models: Use /models/user for fetching OpenRouter models (#37534)
This PR switches the OpenRouter integration from fetching all models to fetching only the models specified in the user's account preferences. This will help improve the experience **The Problem** The previous implementation used the `/models` endpoint, which returned an exhaustive list of all models supported by OpenRouter. This resulted in a long and cluttered model selection dropdown in Zed, making it difficult for users to find the models they actually use. **The Solution** We now use the `/models/user` endpoint. This API call returns a curated list based on the models and providers the user has selected in their [OpenRouter dashboard](https://openrouter.ai/models). Ref: [OpenRouter API Docs for User-Filtered Models](https://openrouter.ai/docs/api-reference/list-models-filtered-by-user-provider-preferences) Release Notes: - language_models: Support OpenRouter user preferences for available models
This commit is contained in:
@@ -92,7 +92,7 @@ pub struct State {
|
||||
api_key_from_env: bool,
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
available_models: Vec<open_router::Model>,
|
||||
fetch_models_task: Option<Task<Result<()>>>,
|
||||
fetch_models_task: Option<Task<Result<(), LanguageModelCompletionError>>>,
|
||||
settings: OpenRouterSettings,
|
||||
_subscription: Subscription,
|
||||
}
|
||||
@@ -178,20 +178,35 @@ impl State {
|
||||
})
|
||||
}
|
||||
|
||||
fn fetch_models(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
|
||||
fn fetch_models(
|
||||
&mut self,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Task<Result<(), LanguageModelCompletionError>> {
|
||||
let settings = &AllLanguageModelSettings::get_global(cx).open_router;
|
||||
let http_client = self.http_client.clone();
|
||||
let api_url = settings.api_url.clone();
|
||||
|
||||
let Some(api_key) = self.api_key.clone() else {
|
||||
return Task::ready(Err(LanguageModelCompletionError::NoApiKey {
|
||||
provider: PROVIDER_NAME,
|
||||
}));
|
||||
};
|
||||
cx.spawn(async move |this, cx| {
|
||||
let models = list_models(http_client.as_ref(), &api_url)
|
||||
let models = list_models(http_client.as_ref(), &api_url, &api_key)
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("OpenRouter error: {:?}", e))?;
|
||||
.map_err(|e| {
|
||||
LanguageModelCompletionError::Other(anyhow::anyhow!(
|
||||
"OpenRouter error: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
this.available_models = models;
|
||||
cx.notify();
|
||||
})
|
||||
.map_err(|e| LanguageModelCompletionError::Other(e))?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -529,12 +529,16 @@ pub async fn stream_completion(
|
||||
pub async fn list_models(
|
||||
client: &dyn HttpClient,
|
||||
api_url: &str,
|
||||
api_key: &str,
|
||||
) -> Result<Vec<Model>, OpenRouterError> {
|
||||
let uri = format!("{api_url}/models");
|
||||
let uri = format!("{api_url}/models/user");
|
||||
let request_builder = HttpRequest::builder()
|
||||
.method(Method::GET)
|
||||
.uri(uri)
|
||||
.header("Accept", "application/json");
|
||||
.header("Accept", "application/json")
|
||||
.header("Authorization", format!("Bearer {}", api_key))
|
||||
.header("HTTP-Referer", "https://zed.dev")
|
||||
.header("X-Title", "Zed Editor");
|
||||
|
||||
let request = request_builder
|
||||
.body(AsyncBody::default())
|
||||
|
||||
Reference in New Issue
Block a user