把 CLIProxyAPI 的模型目录同步进模型选择器
30.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/19 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add TinyBOOOOM/dsh-cliproxyapi-pro该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · model
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 12 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 79 处,展示前 75 条)
- 发起网络请求lib/client.js:2438
const res = await fetch(url, { - 发起网络请求lib/client.js:2496
res = await fetch(url, { - 发起网络请求lib/client.js:2606
const doFetch = io.fetch ?? ((url, init) => fetch(url, init)); - 发起网络请求lib/client.js:3405
const res = await fetch(API.status, { cache: "no-store" }); - 发起网络请求lib/client.js:4696
const res = await fetch(API.mediaStatus, { cache: "no-store", signal }); - 写入剪贴板lib/client.js:4805
await navigator.clipboard.writeText(JSON.stringify(diag, null, 2)); - 发起网络请求lib/client.js:5424
const fetchImpl = io.fetch ?? ((...args) => fetch(...args)); - 写入剪贴板lib/client.js:6937
await navigator.clipboard.write([new ClipboardItem({ "image/png": png })]); - 写入剪贴板lib/client.js:6942
await navigator.clipboard.writeText(text); - 读取本地文件lib/host/state-store.js:23
if (!existsSync(filePath)) return {}; - 读取本地文件lib/host/state-store.js:24
const raw = JSON.parse(readFileSync(filePath, "utf8")); - 写入本地文件lib/host/state-store.js:34
mkdirSync(dir, { recursive: true }); - 写入本地文件lib/host/state-store.js:36
writeFileSync(tmp, JSON.stringify(state, null, 2), "utf8"); - 写入本地文件lib/host/state-store.js:37
renameSync(tmp, filePath); - 读取本地文件lib/host/apply/updates.js:22
const currentVersion = JSON.parse(readFileSync(new URL("../../../package.json", import.meta.url), "utf8")).version; - 读取本地文件lib/host/apply/controller.js:62
existsSync(join(updateDirectory, "media-sessions.json")) || existsSync(join(updateDirectory, "media-jobs.json")); - 读取本地文件lib/host/apply/controller.js:65
if ((loaded.error !== undefined || !existsSync(mediaSettingsPath)) && mediaUsedBefore()) { - 读取本地文件lib/host/apply/quota-service.js:16
read: () => (existsSync(quotaStatePath) ? JSON.parse(readFileSync(quotaStatePath, "utf8")) : undefined), - 读取本地文件lib/host/apply/quota-service.js:16
read: () => (existsSync(quotaStatePath) ? JSON.parse(readFileSync(quotaStatePath, "utf8")) : undefined), - 写入本地文件lib/host/apply/quota-service.js:18
mkdirSync(dirname(quotaStatePath), { recursive: true }); - 写入本地文件lib/host/apply/quota-service.js:20
writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\n`, "utf8"); - 写入本地文件lib/host/apply/quota-service.js:21
renameSync(tmp, quotaStatePath); - 读取本地文件lib/host/apply/media-service.js:137
.filter((r) => existsSync(r.file)) - 读取本地文件lib/host/apply/image-jobs.js:116
if (typeof cwd !== "string" || !isAbsolute(cwd) || !existsSync(cwd)) throw new MediaError("workspace-not-local"); - 读取本地文件lib/host/apply/video-command.js:59
if (typeof cwd !== "string" || !isAbsolute(cwd) || !existsSync(cwd)) throw new MediaError("workspace-not-local"); - 读取本地文件lib/host/apply/video-edit.js:17
return mediaSessions.get(sessionId).recent.find((r) => r.kind === "video" && (commandId === undefined || r.commandId === commandId) && existsSync(r.fi - 读取本地文件lib/host/apply/video-edit.js:35
info = statSync(path); - 读取本地文件lib/host/apply/video-edit.js:41
const data = new Uint8Array(readFileSync(path)); - 读取本地文件lib/host/apply/video-edit.js:54
if (typeof hostPath === "string" && existsSync(hostPath)) return readLocalVideo(hostPath, name); - 读取本地文件lib/host/apply/video-edit.js:88
if (typeof cwd !== "string" || !isAbsolute(cwd) || !existsSync(cwd)) throw new MediaError("workspace-not-local"); - 读取本地文件lib/host/apply/agent-tool.js:146
info = statSync(path); - 读取本地文件lib/host/apply/agent-tool.js:152
const data = new Uint8Array(readFileSync(path)); - 读取本地文件lib/host/apply/agent-tool.js:182
const data = new Uint8Array(readFileSync(path)); - 读取本地文件lib/host/apply/agent-tool.js:235
if (typeof cwd !== "string" || !isAbsolute(cwd) || !existsSync(cwd)) throw new Error(mediaFailureText(new MediaError("workspace-not-local"), t.kind)); - 读取本地文件lib/host/apply/agent-tool.js:275
const files = entry.recent.filter((r) => r.commandId === runId && existsSync(r.file)).map((r) => r.file); - 读取本地文件lib/host/apply/http-routes.js:156
.filter((r) => r.commandId === commandId && existsSync(r.file)) - 读取本地文件lib/host/apply/http-routes.js:178
size = video === undefined ? undefined : statSync(video.path).size; - 读取本地文件lib/host/apply/http-routes.js:219
if (record === undefined || type === undefined || !existsSync(record.file)) { - 读取本地文件lib/host/apply/http-routes.js:225
const bytes = readFileSync(record.file); - 读取本地文件lib/host/apply/http-routes.js:236
const size = statSync(record.file).size; - 读取本地文件lib/host/apply/http-routes.js:256
const stream = createReadStream(record.file, { start, end }); - 读取本地文件lib/media/settings.js:133
if (!existsSync(filePath)) return { settings: defaultMediaSettings() }; - 读取本地文件lib/media/settings.js:135
const raw = JSON.parse(readFileSync(filePath, "utf8")); - 写入本地文件lib/media/settings.js:145
mkdirSync(dirname(filePath), { recursive: true }); - 读取本地文件lib/media/settings.js:146
if (existsSync(filePath) && loadMediaSettings(filePath).error !== undefined) { - 写入本地文件lib/media/settings.js:147
renameSync(filePath, filePath.replace(/ json$/, `.corrupt-${Date.now().toString(36)}.json`)); - 写入本地文件lib/media/settings.js:150
writeFileSync(tmp, `${JSON.stringify(normalizeMediaSettings(settings), null, 2)}\n`, "utf8"); - 写入本地文件lib/media/settings.js:151
renameSync(tmp, filePath); - 读取本地文件lib/media/session-store.js:242
if (!existsSync(filePath)) return { data: normalizeMediaSessions({}) }; - 读取本地文件lib/media/session-store.js:244
const raw = JSON.parse(readFileSync(filePath, "utf8")); - 写入本地文件lib/media/session-store.js:266
mkdirSync(dirname(filePath), { recursive: true }); - 读取本地文件lib/media/session-store.js:267
if (damaged && existsSync(filePath)) { - 写入本地文件lib/media/session-store.js:268
renameSync(filePath, filePath.replace(/ json$/, `.corrupt-${Date.now().toString(36)}.json`)); - 写入本地文件lib/media/session-store.js:271
writeFileSync(tmp, `${JSON.stringify(next, null, 2)}\n`, "utf8"); - 写入本地文件lib/media/session-store.js:272
renameSync(tmp, filePath); - 写入本地文件lib/media/output-files.js:39
mkdirSync(dir, { recursive: true }); - 写入本地文件lib/media/output-files.js:47
writeFileSync(path, file.bytes, { flag: "wx" }); - 写入本地文件lib/media/video.js:248
mkdirSync(dir, { recursive: true }); - 删除本地文件lib/media/video.js:316
unlinkSync(path); - 读取本地文件lib/media/job-store.js:63
if (!existsSync(filePath)) return { data: normalizeMediaJobs({}, now()) }; - 读取本地文件lib/media/job-store.js:65
const raw = JSON.parse(readFileSync(filePath, "utf8")); - 写入本地文件lib/media/job-store.js:74
mkdirSync(dirname(filePath), { recursive: true }); - 读取本地文件lib/media/job-store.js:75
if (damaged && existsSync(filePath)) renameSync(filePath, filePath.replace(/ json$/, `.corrupt-${Date.now().toString(36)}.json`)); - 写入本地文件lib/media/job-store.js:75
if (damaged && existsSync(filePath)) renameSync(filePath, filePath.replace(/ json$/, `.corrupt-${Date.now().toString(36)}.json`)); - 写入本地文件lib/media/job-store.js:77
writeFileSync(tmp, `${JSON.stringify(next, null, 2)}\n`, "utf8"); - 写入本地文件lib/media/job-store.js:78
renameSync(tmp, filePath); - 读取本地文件lib/updater/settings.js:21
const raw = JSON.parse(readFileSync(file, "utf8")); - 写入本地文件lib/updater/settings.js:38
mkdirSync(dirname(file), { recursive: true }); - 写入本地文件lib/updater/settings.js:39
writeFileSync(temporary, `${JSON.stringify({ version: 1, ...normalizeUpdateSettings(settings) }, null, 2)}\n`, { mode: 0o600, flag: "wx" }); - 写入本地文件lib/updater/settings.js:40
renameSync(temporary, file); - 删除本地文件lib/updater/settings.js:42
try { unlinkSync(temporary); } catch {} - 写入本地文件lib/updater/store.js:15
mkdirSync(directory, { recursive: true }); - 写入本地文件lib/updater/store.js:16
writeFileSync(temporary, bytes, { flag: "wx", mode: 0o600 }); - 写入本地文件lib/updater/store.js:17
renameSync(temporary, path); - 删除本地文件lib/updater/store.js:19
try { unlinkSync(temporary); } catch {}
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DeepSeek Harness 的 CLIProxyAPI 服务商插件:支持多账号、模型发现并同步到 DSH 模型选择器、按模型覆盖配置。
README
由 DeepSeek 最新模型翻译生成dsh-cliproxyapi-pro (v1.4.0)
CLIProxyAPI 接入插件,适用于 DeepSeek Harness(DSH >=0.2.0-rc.1):自动发现 CPA 服务、同步模型目录与能力(上下文、视觉、推理档位)到 DSH 模型选择器,支持多个账号分别启用/停用、可视化勾选模型与单模型参数覆盖。
- 零运行时依赖,无需构建;仅使用 Node.js 内置模块与 DSH(Cordis)上下文服务。
- 密钥只存放在 DSH 凭证服务中,不会写入配置文件。
目录
- 功能
- 截图
- 安装
- 使用
- 设置面板
- 多账号
- Agent 工具 cliproxyapi
- 斜杠命令
- HTTP 接口
- 协议路由
- 存储与配置
- AI Agent 安装与配置指南
- 开发
- 许可证
功能
1. 自动发现:可填写远程/本地地址(自动剥离 /v1、/v1/chat/completions、/v1/messages 等后缀),留空则依次尝试已有路由地址、环境变量 CLIPROXYAPI_BASE_URL 与本地 127.0.0.1:8317。读取 /v1/models?client_version=pi 富元数据目录(兼容 OpenAI data[] 格式),并用 /v1/models 的 owned_by 判断模型家族。
展开完整文档(README 剩余 1 节)
dsh-cliproxyapi-pro (v1.4.0)
CLIProxyAPI 接入插件,适用于 DeepSeek Harness(DSH >=0.2.0-rc.1):自动发现 CPA 服务、同步模型目录与能力(上下文、视觉、推理档位)到 DSH 模型选择器,支持多个账号分别启用/停用、可视化勾选模型与单模型参数覆盖。
- 零运行时依赖,无需构建;仅使用 Node.js 内置模块与 DSH(Cordis)上下文服务。
- 密钥只存放在 DSH 凭证服务中,不会写入配置文件。
目录
- 功能
- 截图
- 安装
- 使用
- 设置面板
- 多账号
- Agent 工具 cliproxyapi
- 斜杠命令
- HTTP 接口
- 协议路由
- 存储与配置
- AI Agent 安装与配置指南
- 开发
- 许可证
功能
1. 自动发现:可填写远程/本地地址(自动剥离 /v1、/v1/chat/completions、/v1/messages 等后缀),留空则依次尝试已有路由地址、环境变量 CLIPROXYAPI_BASE_URL 与本地 127.0.0.1:8317。读取 /v1/models?client_version=pi 富元数据目录(兼容 OpenAI data[] 格式),并用 /v1/models 的 owned_by 判断模型家族。
2. 模型勾选筛选:搜索、家族标签、全部/已勾选/未勾选切换、批量勾选;只有勾选的模型会出现在对话框模型选择器中。勾选为空表示不过滤;另可用包含/排除关键词规则。从未保存过勾选的账号,首次探测成功后会按该服务自己的模型目录,为每个模型家族勾选最新的一个(最多 12 个);「恢复推荐精选」可恢复这组勾选。
3. 单模型参数覆盖:上下文窗口、最大输出、图片输入、思考等级(off…max)、请求协议,可一键恢复自动探测值。
4. 按模型家族走原生协议(默认):见协议路由。
5. 多账号:每个账号独立的服务地址、密钥、路由、协议、勾选与覆盖,可单独启用/停用。见多账号。
6. 自动刷新:所有账号按统一间隔(默认 300 秒)刷新;数据无变化时不写入任何设置。
截图
面板位于 设置 → 内置插件 → CLIProxyAPI 标签页,界面语言跟随 DSH 设置。
1. 账号栏与账号状态。 顶部账号栏列出所有账号:绿点表示已连接,灰点加「未启用」标记表示已停用。图中刚用「+ 添加账号」新增了第二个账号「CLI Proxy API 2」:它默认停用,拥有独立的路由 cli-proxy-2;由于还没填写服务地址,探测提示本地没有找到 CPA 服务。
账号栏:一个已连接账号和一个刚添加、未启用的账号
2. 模型显示筛选。 从 CPA 服务发现的全部 168 个模型,支持全部发现 / 已勾选 / 未勾选切换、家族标签(GPT、CLAUDE、GEMINI、GROK……)、搜索与批量操作。只有勾选的模型会同步到 DSH 模型选择器;每个模型显示将使用的协议(图中为 OpenAI Responses)、图片输入、推理档位与上下文长度,「编辑参数」可打开单模型参数覆盖。
模型筛选:家族标签、已勾选模型、协议与能力标记
3. 连接与认证配置。 每个账号独立的设置:「启用此账号」开关、服务地址、保存在该账号独立引用名(CLI_PROXY_API_KEY_2)下的 API Key、接口协议、账号名称、可折叠的高级设置,以及「保存设置并应用」与「删除此账号」。
未启用账号的连接设置,使用独立的密钥引用名
安装
在 DSH 对话中让 Agent 调用 plugin_manager 安装,target 任选其一:
| 来源 | target |
| GitHub 最新 main | git+https://github.com/TinyBOOOOM/dsh-cliproxyapi-pro.git#main |
| GitHub 某个版本标签 | git+https://github.com/TinyBOOOOM/dsh-cliproxyapi-pro.git#v1.4.0(见 Releases) |
| GitHub Release 的 .tgz | 下载 dsh-cliproxyapi-pro.tgz(始终是最新版本),填写它的绝对路径 |
| 本地目录(开发用,链接安装) | 克隆后的仓库目录绝对路径 |
| npm(发布后) | dsh-cliproxyapi-pro |
{ "action": "install_bundle", "target": "<上表中的 target>", "enabled": true }
- 安装目录时为链接安装(source: link:<目录>),修改代码后重载插件即生效。
- 已安装旧版本时可直接重新安装;替换已安装的包后需要重启 DSH 才能加载新代码。
- 安装结果中的 application 为 restart-required 时需重启 DSH。
安装后入口:
- 左侧栏 → 插件 → CLIProxyAPI
- 设置 → 内置插件 → CLIProxyAPI 标签页
使用
设置面板
面板顶部是账号栏:点击切换账号(圆点表示状态,未启用的账号带「未启用」标记),「+ 添加账号」新增账号。下方针对当前账号:
| 区块 | 内容 |
| 状态卡片 | 连接状态、当前节点、选择器中的模型数 / 发现总数;「立即探测刷新」「保存设置并应用」 |
| 模型显示筛选 | 勾选模型、编辑单模型参数;修改后点「保存模型勾选」 |
| 连接与认证 | 「启用此账号」开关、服务地址、API Key(可清除)、接口协议、账号名称 |
| 高级路由与规则过滤 | 包含/排除关键词、路由 ID、密钥引用名、自动刷新间隔(所有账号共用);「删除此账号」 |
多账号
- 每个账号写入自己的一组 llm-pi-ai 路由:首个账号为 cli-proxy / cli-proxy-responses / cli-proxy-messages,新增账号依次为 cli-proxy-2、cli-proxy-3……;密钥引用名依次为 CLI_PROXY_API_KEY、CLI_PROXY_API_KEY_2……。模型选择器中按账号名称分组。
- 路由 ID 不能重叠(例如另一个账号不能使用 cli-proxy-messages),保存时会拒绝。
- 停用账号:保留全部配置,但删除它的路由,模型从选择器中消失;其他账号不受影响。
- 新增账号默认停用。填写地址与密钥后可先「立即探测刷新」预览模型并勾选,再打开「启用此账号」保存。
- 填写了服务地址的账号只探测该地址,连不上就报错,不会回退到本地 :8317,避免多个账号指向同一服务。
- 删除账号会移除它的路由,但保留凭证服务中的密钥。
Agent 工具 cliproxyapi
| action | 作用 |
| status | 查看所有账号(或 account 指定的账号)状态与模型 |
| refresh | 立即探测并同步;不带 account 时刷新全部账号 |
| configure | 修改一个账号(默认第一个),保存后立即刷新 |
| add_account | 新增账号;给了 baseURL 时默认启用,否则停用 |
| remove_account | 删除 account 及其路由 |
参数(除 action 外均可选):
| 参数 | 说明 |
| account | 账号 id(如 default、account-2),也可用路由 ID 或账号名称 |
| enabled | 启用 / 停用该账号 |
| baseURL | CPA 地址,如 http://127.0.0.1:8317;空字符串表示自动发现 |
| apiKey | Bearer 密钥,保存到该账号的 apiKeyEnv 引用名下 |
| apiKeyEnv | 密钥引用名([A-Za-z_][A-Za-z0-9_]) |
| provider | llm-pi-ai 路由 ID,每个账号唯一 |
| displayName | 账号名称 / 模型选择器分组名 |
| protocolMode | auto(按家族原生协议,默认)或 fixed |
| protocol | fixed 时使用的协议:openai-completions / openai-responses / anthropic-messages |
| selectedModels | 显示在选择器中的模型 id 列表;[] 表示全部 |
| includePrefix / excludePrefix | 逗号分隔的模型 id 关键词 |
| modelOverrides | { [modelId]: { contextWindow?, maxTokens?, image?, reasoningLevels?, protocol? } },整体替换 |
示例:
{ "action": "configure", "baseURL": "http://127.0.0.1:8317", "apiKey": "sk-...", "selectedModels": ["gpt-6.1-sol", "claude-opus-5-5"] }
{ "action": "add_account", "displayName": "Backup CPA", "baseURL": "https://other-cpa:8317", "apiKey": "sk-...", "selectedModels": ["gpt-6-astra"] }
{ "action": "configure", "account": "account-2", "enabled": false }
{ "action": "remove_account", "account": "account-2" }
输出包含 accounts[](每个账号的 id、displayName、provider、enabled、state、endpoint、modelCount、totalDiscovered、error)与文字摘要 summary。state 取值:idle、probing、connected、disabled、error。
斜杠命令
- /cpa-status:显示所有账号的状态。
- /cpa-refresh:立即刷新所有账号(包括探测停用账号的模型列表)。
HTTP 接口
供设置面板使用,需要 DSH Web 会话认证;POST 仅接受本机/受信任主机的同源请求。
| 方法 | 路径 | 请求体 | 说明 |
| GET | /api/dsh-cliproxyapi/status | — | { ok, global, accounts[] } |
| POST | /api/dsh-cliproxyapi/refresh | { accountId? } | 刷新一个或全部账号 |
| POST | /api/dsh-cliproxyapi/save | { accountId?, …账号字段, apiKey?, clearApiKey?, refreshIntervalSeconds?, probeTimeoutMs? } | 保存账号(缺省为第一个);只有全局字段时只保存全局设置 |
| POST | /api/dsh-cliproxyapi/accounts/add | 账号字段(可选) | 新增账号,默认停用;返回 createdId |
| POST | /api/dsh-cliproxyapi/accounts/remove | { accountId } | 删除账号及其路由 |
协议路由
CLIProxyAPI 对每个模型同时提供 OpenAI Chat、OpenAI Responses、Anthropic Messages 三种入口,入口协议与上游不一致时会做转换。自动模式(protocolMode: "auto")让每个模型直接使用上游协议:
| 模型家族(依据 owned_by 与模型 id) | 协议 | 路由(以 cli-proxy 为例) |
| Claude(含 devin/claude-、Antigravity Claude) | Anthropic Messages /v1/messages | cli-proxy-messages |
| OpenAI / Codex / GPT、xAI Grok | OpenAI Responses /v1/responses | cli-proxy-responses |
| Gemini、DeepSeek、Kimi、GLM、SWE、gpt-oss 等 | OpenAI Chat /v1/chat/completions | cli-proxy |
- DSH 自定义路由不支持 Gemini 原生 generateContent,Gemini 走 OpenAI Chat。
- DSH 每条路由只有一种协议,模型按协议拆入三条路由;没有模型的路由会被移除。默认模型因此换路由时,agent-default-model 自动跟随。
- Claude 4.6+ / 5.x / Fable 使用自适应思考(effort),更早的 Claude 使用 token 预算。
- 可改为「统一使用」某一协议(fixed),或在单个模型的「编辑参数」中指定协议。
- 路由上你手动添加的其他字段(如 retryPolicy)会被保留。
存储与配置
- 状态文件:<Profile 目录>/.dsh-cliproxyapi/state.json
{
"version": 2,
"refreshIntervalSeconds": 300,
"probeTimeoutMs": 5000,
"accounts": [
{
"id": "default", "enabled": true, "provider": "cli-proxy", "displayName": "CLI Proxy API",
"baseURL": "https://cpa.example.com", "apiKeyEnv": "CLI_PROXY_API_KEY",
"protocol": "openai-completions", "protocolMode": "auto",
"includePrefix": "", "excludePrefix": "", "selectedModels": ["gpt-6.1-sol"], "modelOverrides": {}
}
]
}
文件每次读取时都会重新加载,手动修改后点「立即探测刷新」即可生效。v1 单账号文件会自动迁移为 id default 的账号(路由、密钥、勾选不变),原文件备份为 state.v1.json。
- 密钥:通过 DSH credentials 服务按引用名存取;未存储时回退读取同名环境变量。本地免密的 CPA 可以不填密钥。
- 环境变量:CLIPROXYAPI_BASE_URL 仅用于服务地址留空的账号的自动发现。
- Bundle 行配置:cordis.patch.yml 中插件行的 config 会在启动时叠加到状态文件上:含 accounts 时替换账号列表,否则平铺字段作用于第一个账号。通常保持 {},使用面板或工具配置即可。
AI Agent 安装与配置指南
给 DeepSeek Harness 中的 AI Agent:用户要求安装或配置本插件时按以下步骤执行。本包没有 npm 依赖,也没有构建脚本。
1. 安装:调用 plugin_manager,{"action": "install_bundle", "target": "<见安装一节>", "enabled": true}。查看结果中的 application 与 warnings;restart-required 表示需重启 DSH 后新代码才会运行。
2. 配置:使用 cliproxyapi 工具。
- 本地 http://127.0.0.1:8317 且无鉴权:无需配置,调用 {"action": "refresh"}。
- 远程地址或密钥:{"action": "configure", "baseURL": "...", "apiKey": "..."}(第一个账号),额外账号用 {"action": "add_account", ...};指定账号时传 "account": "<id>"。
- 用 selectedModels(取自 status 输出的精确 id)精简模型选择器。
3. 验证:{"action": "status"} 中每个启用的账号 state 为 connected 且 modelCount > 0。告诉用户模型已出现在 DSH 模型选择器中(以账号名称分组),可在 左侧栏 → 插件 → CLIProxyAPI 或 设置 → 内置插件 → CLIProxyAPI 管理账号。
不要把 API Key 回显给用户或写入任何文件。
开发
lib/index.js Host 插件(发现、同步、多账号控制器、工具、命令、HTTP 接口) lib/client.js Web 设置面板(ModuleLoader 格式,手写,无需构建) locale/*.json 插件管理器中显示的标题与描述 cordis.patch.yml Bundle patch,插入 dsh-cliproxyapi-pro 行 tests/ node:test 单元与集成测试 .github/workflows/ CI(测试)与发版(Release .tgz,可选 npm 发布) assets/screenshots/ README 截图(同时登记在 screenshots.json 中供插件市场展示) AGENTS.md 给编码 Agent 的开发约定、架构与不变量
git clone https://github.com/TinyBOOOOM/dsh-cliproxyapi-pro.git
cd dsh-cliproxyapi-pro
npm test # 运行测试
npm run check # 语法检查 + 测试
npm run pack:check # 查看打包文件列表
修改代码前请阅读 AGENTS.md;变更记录见 CHANGELOG.md。欢迎提交 Issue 与 Pull Request,修改说明文档时请同时更新中英文两份。
许可证
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
TinyBOOOOM/dsh-cliproxyapi-pro
把 CLIProxyAPI 的模型目录同步进模型选择器
相关插件 · 模型接入
API 中继安全审计toby-bridges/api-relay-audit
面向 AI API 中转与 LLM 代理的本地安全审计。
★ 897已汉化DSH
69.4
免费搜索插件DDDMUC/dsh-free-search
DeepSeek Harness 免费搜索插件 —— 无需 API key,零成本,多引擎可切换。 一个给…
★ 761已汉化DSH
68.7
免费联网搜索liustack/modsearch
在官方 App 里模型能联网,切到 API 就不能了。ModSearch 把联网补回来:网页搜索、X…
★ 863已汉化DSH
68.5
OpenCode 免费模型FishBottle7/opencode2dsh
在 DSHDeepSeek Harness里原生使用 OpenCode Zen 的免费匿名模型。
★ 379已汉化DSH
67.8
AI 模型网关tingly-dev/tingly-box
Tingly Box Web UI 演示
★ 373已汉化DSH
67.4
WorkBuddy 账号池XDTrees/dsh-xdpool
把你能白嫖的模型额度接进 DSH 同一个池:WorkBuddy 多账号自动容错、十三家扫码登录、76…
★ 359已汉化DSH
67.1