diff --git a/tui-plugins/oc-session-all.js b/tui-plugins/oc-session-all.js index 26560ea..12c466e 100644 --- a/tui-plugins/oc-session-all.js +++ b/tui-plugins/oc-session-all.js @@ -470,28 +470,63 @@ function mmReadCatalog() { async function openModelManager(context) { try { - // 从 opencode.json 读「已连接 provider」(用户配了 API key 的),不是 catalog 全量 + // ── 收集「已连接 provider」,两个来源都读,合并去重 ────────────────── + // 来源 A:opencode.json 的 provider 字段(cc-switch 自定义加的,如 id=1) + // 来源 B:opencode.db catalog 里「当前 OC 真正启用的内置 provider」(如 Xiaomi) + // —— catalog 全量 232 个不是已连接,要按 OC 当前实际启用集合过滤 let connectedProviders = [] + const seen = new Set() + const addProvider = (name, models, source) => { + if (!name || seen.has(name)) return + seen.add(name) + connectedProviders.push({ name, models: models || [], source }) + } + + // 来源 A:config provider try { const cfgPath = join(homedir(), ".config", "opencode", "opencode.json") if (existsSync(cfgPath)) { const cfg = JSON.parse(readFileSync(cfgPath, "utf-8")) const prov = (cfg && cfg.provider) || {} - // 每个 provider 的 models 字典,合并成 {providerName: modelList} for (const pid of Object.keys(prov)) { const pv = prov[pid] || {} - // provider 名称优先取 name,其次 id const name = pv.name || pid const models = Object.keys((pv.models && pv.models) || {}) - connectedProviders.push({ id: pid, name, models }) + addProvider(name, models, "config") } } } catch (e) { log("[oc-session-all] /manage 读 config provider 失败: " + e.message) } + + // 来源 B:catalog 里「已连接内置 provider」。 + // 「已连接」= 该 provider 的 env 字段里的某个 API key 存在于 process.env + // (用户 /connect 时 OC 把 key 注入当前进程环境,运行时态,不落在文件里)。 + // 只列「能判定已连接」的 catalog provider,不会全量拉 232 个。 + const cat = await mmReadCatalog() + if (cat && cat.body) { + let body = {} + try { + body = JSON.parse(cat.body) + } catch (e) { + log("[oc-session-all] /manage catalog body parse 失败: " + e.message) + } + for (const cid of Object.keys(body)) { + const cv = body[cid] || {} + const models = Object.keys((cv && cv.models) || {}) + if (models.length === 0) continue + // 已连接判定:provider.env 数组里任一 key 在 process.env 里有值 + const envs = Array.isArray(cv.env) ? cv.env : [] + const isConnected = envs.some((k) => process.env && process.env[k]) + if (!isConnected) continue + const name = cv.name || cid + addProvider(name, models, "catalog") + } + } + if (connectedProviders.length === 0) { context.ui.toast.show({ - message: "没有已连接 provider(opencode.json 的 provider 字段为空),先 /connect 一个再 /manage", + message: "没有已连接 provider(config 和 catalog 都为空),先 /connect 一个再 /manage", variant: "warning", }) return @@ -504,7 +539,7 @@ async function openModelManager(context) { value: "__reset_all__", }, ...connectedProviders.map((p) => ({ - title: p.name + "(" + p.models.length + " 个模型)", + title: p.name + "(" + p.models.length + " 个模型 · " + p.source + ")", value: p.name, })), ]