diff --git a/app/i18n/en/warp.ftl b/app/i18n/en/warp.ftl index ef4741c7ae..186bc5e36b 100644 --- a/app/i18n/en/warp.ftl +++ b/app/i18n/en/warp.ftl @@ -1516,6 +1516,7 @@ settings-agent-providers-quick-add-title = Quick add settings-agent-providers-refresh-catalog = Refresh catalog settings-agent-providers-loading-catalog = Loading models.dev catalog… (the first load may take a few seconds) settings-agent-providers-catalog-empty = models.dev catalog is empty. Click [Refresh catalog] to retry. +settings-agent-providers-catalog-load-failed = Failed to load models.dev catalog. Click [Refresh catalog] to retry. settings-agent-providers-no-match = No match for "{ $query }" settings-agent-providers-collapse = Collapse ▲ settings-agent-providers-expand-remaining = Expand remaining { $count } ▼ diff --git a/app/i18n/ja/warp.ftl b/app/i18n/ja/warp.ftl index fc27cd05d5..d9d64601de 100644 --- a/app/i18n/ja/warp.ftl +++ b/app/i18n/ja/warp.ftl @@ -1451,6 +1451,7 @@ settings-agent-providers-quick-add-title = クイック追加 settings-agent-providers-refresh-catalog = カタログを更新 settings-agent-providers-loading-catalog = models.dev カタログを読み込み中… (初回読み込みは数秒かかる場合があります) settings-agent-providers-catalog-empty = models.dev カタログが空です。[カタログを更新] をクリックして再試行してください。 +settings-agent-providers-catalog-load-failed = models.dev カタログの取得に失敗しました。[カタログを更新] をクリックして再試行してください。 settings-agent-providers-no-match = 「{ $query }」に一致する項目はありません settings-agent-providers-collapse = 折りたたむ ▲ settings-agent-providers-expand-remaining = 残り { $count } 件を展開 ▼ diff --git a/app/i18n/zh-CN/warp.ftl b/app/i18n/zh-CN/warp.ftl index 06e9fdcaf6..faf0024072 100644 --- a/app/i18n/zh-CN/warp.ftl +++ b/app/i18n/zh-CN/warp.ftl @@ -1491,6 +1491,7 @@ settings-agent-providers-quick-add-title = 快速添加 settings-agent-providers-refresh-catalog = 刷新目录 settings-agent-providers-loading-catalog = 正在拉取 models.dev 目录…(第一次可能需要几秒) settings-agent-providers-catalog-empty = models.dev 目录为空,点 [刷新目录] 重试。 +settings-agent-providers-catalog-load-failed = models.dev 目录拉取失败,点 [刷新目录] 重试。 settings-agent-providers-no-match = 无匹配「{ $query }」 settings-agent-providers-collapse = 收起 ▲ settings-agent-providers-expand-remaining = 展开剩余 { $count } 个 ▼ diff --git a/app/src/ai/agent_providers/models_dev.rs b/app/src/ai/agent_providers/models_dev.rs index 2371b9ca67..26be1086ab 100644 --- a/app/src/ai/agent_providers/models_dev.rs +++ b/app/src/ai/agent_providers/models_dev.rs @@ -269,6 +269,20 @@ pub fn toggle_chips_expanded() { CHIPS_EXPANDED.fetch_xor(true, Ordering::Relaxed); } +// ── 最近一次网络拉取失败标志 ───────────────────────────────────────────────── + +static FETCH_FAILED: AtomicBool = AtomicBool::new(false); + +/// 最近一次网络拉取是否失败(cached() == None 时有意义)。 +pub fn last_fetch_failed() -> bool { + FETCH_FAILED.load(Ordering::Relaxed) +} + +/// 由调用方在 spawn 回调中设置(失败 true,成功不需要重置,因为 cached() 此时为 Some)。 +pub fn set_fetch_failed(failed: bool) { + FETCH_FAILED.store(failed, Ordering::Relaxed); +} + // ── 快速添加 chip 行的搜索过滤 ────────────────────────────────────────────── fn search_state() -> &'static RwLock { diff --git a/app/src/settings_view/agent_providers_widget.rs b/app/src/settings_view/agent_providers_widget.rs index 10778a0ee1..23c0d14193 100644 --- a/app/src/settings_view/agent_providers_widget.rs +++ b/app/src/settings_view/agent_providers_widget.rs @@ -1462,10 +1462,15 @@ impl AgentProvidersWidget { match models_dev::cached() { None => { + let catalog_text = if models_dev::last_fetch_failed() { + crate::t!("settings-agent-providers-catalog-load-failed") + } else { + crate::t!("settings-agent-providers-loading-catalog") + }; body.add_child( Container::new( Text::new( - crate::t!("settings-agent-providers-loading-catalog"), + catalog_text, appearance.ui_font_family(), appearance.ui_font_size(), ) diff --git a/app/src/settings_view/ai_page.rs b/app/src/settings_view/ai_page.rs index 9081c7e7c7..0d3b896514 100644 --- a/app/src/settings_view/ai_page.rs +++ b/app/src/settings_view/ai_page.rs @@ -3401,8 +3401,15 @@ impl TypedActionView for AISettingsPageView { ctx.spawn( async move { models_dev::fetch_and_cache(client).await }, |view, result, ctx| match result { - Ok(()) => view.rebuild_current_page(ctx), - Err(e) => log::warn!("[models.dev] 拉取失败: {e}"), + Ok(()) => { + models_dev::set_fetch_failed(false); + view.rebuild_current_page(ctx); + } + Err(e) => { + log::warn!("[models.dev] 拉取失败: {e}"); + models_dev::set_fetch_failed(true); + ctx.notify(); + } }, ); } else { @@ -3415,8 +3422,15 @@ impl TypedActionView for AISettingsPageView { ctx.spawn( async move { models_dev::fetch_and_cache(client).await }, |view, result, ctx| match result { - Ok(()) => view.rebuild_current_page(ctx), - Err(e) => log::warn!("[models.dev] 刷新失败: {e}"), + Ok(()) => { + models_dev::set_fetch_failed(false); + view.rebuild_current_page(ctx); + } + Err(e) => { + log::warn!("[models.dev] 刷新失败: {e}"); + models_dev::set_fetch_failed(true); + ctx.notify(); + } }, ); }