fix(agent/sync): make OpenRouter fetch optional, fallback to direct sync

When OpenRouter's public /api/v1/models endpoint fails (network error,
timeout, parse failure), the entire sync was aborted — meaning models
accessible from the user's AI endpoint were never synced.

Now: if OpenRouter fetch fails, fall back to sync_models_direct for all
available models instead of returning an error. Both sync_upstream_models
(API) and sync_once (background task) have this fix.
This commit is contained in:
ZhenYi 2026-04-26 15:49:34 +08:00
parent 31ed420186
commit 8a23a22c9b

View File

@ -726,15 +726,20 @@ impl AppService {
available_ids.len()
);
// Step 2: fetch OpenRouter metadata.
// Step 2: fetch OpenRouter metadata (optional — failure falls back to
// direct sync for all available models).
let http_client = reqwest::Client::new();
let or_resp: OpenRouterResponse = fetch_openrouter_models(&http_client)
.await
.map_err(AppError::InternalServerError)?;
let or_models: Vec<OpenRouterModel> = match fetch_openrouter_models(&http_client).await {
Ok(resp) => resp.data,
Err(msg) => {
tracing::warn!(error = %msg, "sync_upstream_models: OpenRouter fetch failed, falling back to direct sync");
let direct_result = sync_models_direct(&self.db, &available_ids).await;
return Ok(direct_result);
}
};
// Step 3: filter to only accessible models.
let filtered: Vec<&OpenRouterModel> = or_resp
.data
let filtered: Vec<&OpenRouterModel> = or_models
.iter()
.filter(|m| available_ids.contains(&m.id))
.filter(|m| m.id != "openrouter/auto")
@ -927,16 +932,16 @@ impl AppService {
};
let http_client = reqwest::Client::new();
let or_resp = match fetch_openrouter_models(&http_client).await {
Ok(r) => r,
let or_models: Vec<OpenRouterModel> = match fetch_openrouter_models(&http_client).await {
Ok(resp) => resp.data,
Err(msg) => {
tracing::warn!(error = %msg, "OpenRouter model sync");
tracing::warn!(error = %msg, "OpenRouter model sync: fetch failed, falling back to direct sync");
sync_models_direct(db, &available_ids).await;
return;
}
};
let filtered: Vec<&OpenRouterModel> = or_resp
.data
let filtered: Vec<&OpenRouterModel> = or_models
.iter()
.filter(|m| available_ids.contains(&m.id))
.filter(|m| m.id != "openrouter/auto")