From ce8a8463cc18caaf189a2d2c5b1413259e184f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=BD=E5=B0=8F=E9=9B=A8?= <181683471+a137460387@users.noreply.github.com> Date: Fri, 6 Nov 2026 11:11:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E7=AD=BE=E5=88=B0?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E9=87=8C=E6=8F=92=E4=BB=B6=E5=AE=B6=E7=9A=84?= =?UTF-8?q?=E5=88=86=E7=BB=84=E6=A0=87=E9=A2=98=E5=9B=9E=E6=98=BE=E8=A3=B8?= =?UTF-8?q?=20provider=20id=EF=BC=88`quwork`=EF=BC=89=E8=80=8C=E4=B8=8D?= =?UTF-8?q?=E6=98=AF=E9=9D=A2=E6=9D=BF=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `auto_checkin::provider_label` 自己扫 `PROVIDERS` 静态表,而那张表只有内置枚举;插件家的 id 不在表里,于是 `unwrap_or(id)` 把 id 原样回显。结果是同一页上账号、模型、报表都显示「QuWork」,只有签到中心的分组标题是 `quwork`。 改动两处: - `core/auto_checkin.rs`:`provider_label` 不再自己扫表,改为委托 `providers::label_of`(该函数的文档本就写着它是「id → 给人看的名字」的唯一入口),签名从 `&str` 变为 `String`;三个调用点都在拼 JSON,无需其他改动。 - `core/providers/mod.rs`:`label_of` 的 runtime id 分支补一级回退 —— 先读**已安装包清单**的 `providers[].label`(`plugin_host::provider_label`,宿主没跑起来、握手未完成、用户停用时也读得到),再退回已握手执行体自报的名字,最后才回显 id。原先只查执行体,停用的插件家会掉回英文 id。 实测(网关 v3.4.2 + 一个申报 `quwork` 的独立插件包): - 签到中心分组标题:`quwork` → `QuWork` - 顺带修好两个原本同样掉回 id 的插件家:`astudio` → `AStudio`、`doubaowork` → `豆包工作` - 内置家标签无变化:`小浣熊`、`ZCode 国内版`、`WorkBuddy 国内版` 与改动前逐字一致 --- .../server/src/server/core/auto_checkin.rs | 18 +++++++++++------- .../server/src/server/core/providers/mod.rs | 18 ++++++++++++++---- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/desktop-tauri/src-tauri/server/src/server/core/auto_checkin.rs b/desktop-tauri/src-tauri/server/src/server/core/auto_checkin.rs index 736a73623..7f52997c4 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/auto_checkin.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/auto_checkin.rs @@ -260,7 +260,7 @@ pub fn providers_added_after(version: i64) -> Vec { .collect() } -/// 提供商的展示名(从注册表查,查不到就原样回显 id)。 +/// 提供商的展示名(签到语境的入口,直接委托 `providers::label_of`)。 /// /// 这是**签到语境**的展示名(签到中心的分组、自动签到的提供商勾选共用这一份)。 /// WorkBuddy 两个地区在注册表里就叫「WorkBuddy 国内版 / 国际版」(拆家后的 @@ -269,12 +269,16 @@ pub fn providers_added_after(version: i64) -> Vec { /// 不在标签里堆字。Qoder 拆家(2026-10)后注册名就是「Qoder 中国版 / /// 国际版」,不再需要这里的覆盖。其余几家不需要后缀:小浣熊没有版本区分, /// AutoClaw 两地的签到链路都存在且同形 —— 展示名已带「国内版 / 国际版」。 -pub fn provider_label(id: &str) -> &str { - crate::server::core::providers::PROVIDERS - .iter() - .find(|meta| meta.id == id) - .map(|meta| meta.label) - .unwrap_or(id) +/// +/// ── 为什么不再自己扫 `PROVIDERS` ──────────────────────────── +/// 插件架构下「有签到能力的家」不再只由内置枚举决定:签到的可签清单是 +/// `checkin_providers()`(常量表 + 运行期装入的插件家),而 `PROVIDERS` +/// 里没有插件家的条目。原先这里直接扫 `PROVIDERS`,于是插件家一律回显裸 +/// provider id —— 签到中心的分组标题就成了 `quwork` 这种用户看不懂的串, +/// 而同一页的账号、模型、报表早就通过 `label_of` 拿到了面板名。 +/// 改成委托 `label_of` 后,一处口径覆盖内置家、自定义家与插件家。 +pub fn provider_label(id: &str) -> String { + crate::server::core::providers::label_of(id) } /// 归一化配置里的提供商清单:只认 CHECKIN_PROVIDERS 里的 id(去重、保持顺序), diff --git a/desktop-tauri/src-tauri/server/src/server/core/providers/mod.rs b/desktop-tauri/src-tauri/server/src/server/core/providers/mod.rs index b189c5a50..c70174bfa 100644 --- a/desktop-tauri/src-tauri/server/src/server/core/providers/mod.rs +++ b/desktop-tauri/src-tauri/server/src/server/core/providers/mod.rs @@ -436,7 +436,13 @@ pub fn executable_provider_ids() -> Vec { /// ── 回退顺序 ────────────────────────────────────────────── /// 1. `custom-` 前缀 → 先查 `custom_providers::label_of`(用户给的名字优先), /// 查不到(已被删除 / 手改数据塞进来的陌生 id)回显原 id; -/// 2. 其余走注册表:登记的返回 `label`,未登记的原样回显。 +/// 2. 内置家走注册表:登记的返回 `label`; +/// 3. 插件家(`ProviderKind` 枚举里没有的 runtime id)→ 先读**已安装包清单**的 +/// `providers[].label`,再退回**已握手加载**的执行体自报的名字 → 都没有才回显原 id。 +/// +/// 第 3 步的两级顺序不是冗余:清单在包没跑起来时也读得到(宿主崩溃 / 用户停用 / +/// 网关刚启动握手未完成),执行体只在这家真的加载后才有。只查执行体会让「停用的 +/// 插件家」在界面上掉回一串英文 id —— 用户看不出那是什么。 /// /// 回显成 id 而不是「未知」的理由不变:调用点手上的 id 来自真实数据(账号 /// 记录、`owned_by`、日志),真出现未登记的 id 时,回显原文比一句笼统的 @@ -455,9 +461,13 @@ pub fn label_of(id: &str) -> String { match kind_from_id(id) { // 内置家优先读注册表:那是既有文案契约(插件接管后也不该改字)。 Some(kind) => meta(kind).label.to_string(), - // runtime id 不靠占位 kind 取名:插件登记优先,最后回显原 ID。 - None => crate::server::core::plugin_host::lookup(id) - .map(|adapter| adapter.label().to_string()) + // runtime id 不靠占位 kind 取名:清单优先(停用/未握手也读得到), + // 再退回已加载执行体,最后回显原 ID。 + None => crate::server::core::plugin_host::provider_label(id) + .or_else(|| { + crate::server::core::plugin_host::lookup(id) + .map(|adapter| adapter.label().to_string()) + }) .unwrap_or_else(|| id.to_string()), } }