云计算百科
云计算领域专业知识百科平台

DSH 接入 Command Code Go 插件:模型、联网搜索与多账户轮换一次到位


📝 本文首发于 栏轩·阁

欢迎访问阅读原文,获取更好的阅读体验。


概述

DeepSeek Harness(下称 DSH)的模型接入是插件化的:装一条 provider 插件,模型就直接出现在选择器里,流式输出、工具调用、权限控制全都还是 DSH 自己的。Command Code 在这里面是性价比很突出的一个选择,$1 一个月的 Go 套餐给 10 美元额度,开源模型加上几个 premium 例外,叠上平台折扣还能再翻一倍多。

麻烦的是社区里同名的 Command Code 插件不止一个,功能差得挺远。有的只做聊天,有的走标准 Provider API——而 Go 套餐恰恰没有 Provider API 权限,装上去直接不能用。我最后选的是 Mars-Sea 维护的那个,包名 @mars-sea/dsh-commandcode-provider,理由很直接:它是目前唯一把联网搜索一起带进来的,另外还带多账户轮换、用量面板和终端界面支持。

这篇先把功能讲清楚,再拆它背后的机制。

它比同类多做了什么

最核心的是一个插件覆盖所有套餐。Command Code 有两套服务端通道,标准 Provider API 只对 GOAT 及以上开放,Go 套餐去调会返回 upgrade_required,额度只在官方 CLI 走的私有网关 /alpha/generate 上放行。这个插件两套都实现了:有 Provider API 权限的账号走标准端点,Go 套餐自动走 CLI 网关,而且切换是靠服务端拒绝来驱动的,你不用配任何开关。

联网搜索是另一个不太常见的加分项,这点值得单独说:DSH 自带的 web_search 工具其实需要一个单独的 DeepSeek API key 才能工作,而 DSH 的 web 能力本身就是可插拔的接缝(seam)。这个插件在 ctx.web 上注册了一个 commandcode 搜索后端,直接调 Command Code 的 /alpha/web-search,复用聊天的同一把 key 和同一个 base URL——也就是说一份订阅同时管住了聊天和搜索,不需要再配第二个 key。

多账户轮换也做了。有多个 Command Code 订阅的话,一个账号把用量窗口打满,请求会自动切到下一个,而且这个过程对模型是透明的(后面原理篇会讲为什么)。除此之外还有按模型路由到指定账户、手动 pin 当前账户。

用量面板做得比较全:不只是余额,而是账号名、请求数与成功率、花费、token 进出、月度/购买/免费三类 credits,以及 5 小时和每周两个滚动窗口的进度条加重置时间——数据来自官方 CLI 用的那几个账号接口,全部在服务端生成,浏览器从头到尾不碰你的 key。

它同时支持终端。Web 和 dsh-TUI 都能用,终端里有自己的 /settings → Command Code 页面来填 key、挑模型、切账户。

安装

前置条件和 DSH 插件一致,Node 22 以上。安装就一条命令:

dsh plugin –profile web add @mars-sea/dsh-commandcode-provider@0.10.6

装完重启 dsh。

这里有个很容易踩的坑:pnpm 11 的 minimumReleaseAge 默认 1440 分钟,也就是发布不足一天的版本会被跳过,@latest 会静默解析到上一个版本,而安装命令照样以成功退出。所以如果你要装的是刚发布的新版,必须写精确版本号,并且把它加进 profile 的 pnpm-workspace.yaml:

minimumReleaseAgeExclude:
'@mars-sea/dsh-commandcode-provider@0.10.6'

装完别只看命令退没退出,核对一下实际落地的版本:

dsh plugin –profile web list

版本对应关系也确认一下。插件在 package.json 里声明了逐版本的兼容清单(dsh.compatibility.dshReleases),目前标记为 compatible 的是 0.1.2-rc.1、0.1.3-alpha.1、0.1.3-alpha.2、0.1.5-alpha.1、0.1.5-rc.1、0.1.5-rc.2。另外它有个硬性的引擎要求:dsh 必须导出 ToolCallId,也就是 0.1.2-alpha.3 或更高。在更老的 0.1.0-rc.6 / 0.1.1-rc.2 上,插件的模块导入会直接失败,终端界面根本起不来。

还有一条容易被忽略的:每个 profile 有自己独立的插件列表。上面那条命令装的是 Web,如果你还想在终端里用,得单独再装一次到 dsh-tui profile。

模型选择器里能看到什么

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

装上之后,模型选择器里的 Command Code 分组不再是干巴巴一串模型名。每个条目都是一行紧凑标注,形如 Go · 50% off · Image · 1M,从前往后依次是:最低套餐档位(Go / GOAT / Pro / Provider)、当前有效的折扣或 FREE 徽章、是否支持图片输入、上下文长度。

这套标注解决的是一个很实际的问题:以前你只有在第一次请求被服务端用 MODEL_NOT_IN_PLAN 拒掉之后,才知道某个模型不在自己的套餐里。现在一眼就能看出"这个模型我需要升到哪一档才能用"。

排序也是按这个逻辑来的:免费模型排最前(它们不消耗 credits,而且任何账号都能用,最适合当默认选项),然后是 Go、GOAT、Pro、Provider/Max,同一档内按字母序。Go 套餐用户真正能用的模型会集中在列表顶部,不用在扁平的字母序里翻找。

折扣标注是带过期时间的,官方把某个 deal 下线之后,即使你用的还是旧版插件,那个徽章也不会继续显示。这一点做得挺克制——不少同类插件会把过期的优惠一直挂在那里。

另外还有几个配套开关:默认会隐藏超出你套餐的模型(可以关掉恢复完整目录),以及一个模型白名单,勾选之后选择器只列出你常驻的那几个。

联网搜索

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

搜索这块的开箱体验很好:设置 → Command Code 页面里有个「用 Command Code 承载联网搜索」的开关(配置项叫 webSearch),默认就是开的。打开它之后,模型发起的 web_search 就由 Command Code 承载,用的是聊天那把 key。

有几个细节值得记一下:

它的开关不是"抢过来就完事"。当你打开它时,插件会记住它顶掉的那个后端;等你把它关掉,或者直接卸载插件,选择权会交还给原来的后端。所以如果你同时还装了别的搜索插件(比如 modsearch),不会被它弄死,两个可以来回切。这一点在 0.10.2 修过一次——早期版本关掉开关会强制回退到 DSH 自带的 DeepSeek 搜索,把兄弟插件的路堵死了。

如果你想让配置更"钉死"一点,可以不走运行时开关,直接在配置里写 searchProvider: commandcode,或者设环境变量 $DSH_WEB_SEARCH_PROVIDER=commandcode。这样即使插件的运行时选中不可用,选择依然生效。

工具参数上,numResults 会被收敛到 Command Code 自己的取值范围(1 到 10,默认 5),返回结果映射成 DSH 的 WebSearchSource 结构(url、title、snippet),所以在前端看到的搜索卡片和原来一模一样。

一个前提:这套只在你的 profile 挂了 web 能力(@deepseek-ai/dsh-web 和 @deepseek-ai/dsh-tool-web)时才生效。没挂的话,插件就只是个纯聊天插件,搜索后端不会注册。

多账户轮换

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你有多个 Command Code 账号,这块很实用。设置页有个「多账户轮换」卡片,可以添加账户、填备注名和 key;顶层那把 key 永远是第一顺位的 default 账户,其余的按列表顺序排下去。

轮换是被动的,这一点设计得很聪明:稳态下它不产生任何额外的 API 调用。只有当某次请求真的被拒绝时才会标记——429 记成"耗尽",401 记成"失效"——然后适配器在 stream() 内部拿下一个账户的 key 把同一个请求重试一遍。因为请求体和账号无关,切换对模型完全不可见,你不会在会话里看到任何中断迹象。

等到所有账户都被标记了,它才会去探测每个 key 的真实五小时窗口(打 /alpha/billing/credits),把窗口其实已经重置的账户复活;如果确实都满了,抛出的错误里会直接告诉你最早的窗口重置时间,而不是让你自己猜。

除了自动轮换,还有两个手动控制:一个「当前使用账户」下拉框,可以 pin 住优先账户(它耗尽了会自动回落到其他账户,窗口重置后自动恢复);一个「按模型切换账户」的规则列表,可以多选模型固定到某个账户,规则按列表顺序匹配、第一条命中生效。后者的典型用法是把便宜的 Go 档模型留在 Go 账号上,把 GOAT 专属的模型路由到 GOAT 账号。

有个细节做得比较讲究:轮换状态是按 API key 存的,不是按槽位。所以如果两个槽位填了同一把 key,它们共享同一个标记,不会出现"同一个凭证被反复尝试"的情况。

用量面板

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

插件注册了一个 /commandcode 斜杠命令,在终端里输入就能看到分账户的用量报告:

/commandcode

输出包括账号名、请求总数和成功率、花费、token 进出、月度/购买/免费 credits,以及 5 小时和每周两个窗口的进度条与重置时间。多账户时会分账户各显示一段,并用 ✅ 当前使用 / ⏳ 限额冷却中 这样的标记区分状态。

设置页里也有一张同样的「账户用量」卡片。多账户时它不是把卡片堆成一列,而是做成带状态点的轮播,页面不会随着账户数量增长。这两处数据都由服务端生成,浏览器不持有 API key。

文案是中英双语的,跟 shell 的语言走:插件配置里显式写了 lang: 'en' | 'zh' 优先,否则读 LC_ALL / LANG,再否则默认 zh。

配置项

大部分东西在设置页点点就行,需要写配置文件的话,选项都挂在 llm-commandcode 这个命名空间下(改完即刻生效,不用重启):

llm-commandcode:
apiKeyEnv: COMMANDCODE_API_KEY # 凭据引用
apiBase: https://api.commandcode.ai
workingDir: /path/to/project # 可选
modelsCachePath: ~/.commandcode/modelscache.json
requestTimeoutMs: 60000 # 默认 60s
streamIdleTimeoutMs: 300000 # 默认 300s

配置项默认值作用
apiKeyEnv COMMANDCODE_API_KEY 凭据引用,也就是 key 存哪
apiBase https://api.commandcode.ai API 地址
workingDir 进程工作目录 发送给网关的项目路径
modelsCachePath ~/.commandcode/models-cache.json 模型目录的离线缓存
requestTimeoutMs 60000 等第一个字节的上限
streamIdleTimeoutMs 300000 流中途无事件的空闲上限
activeAccount pin 住的当前账户
accounts [] 额外账户列表(label + apiKeyEnv)
modelAccountRules [] 按模型路由到账户的规则
visibleModels 模型白名单,不填则全显示
webSearch true 是否用 Command Code 承载联网搜索
lang 跟随 LC_ALL/LANG 命令与错误文案的语言

原理篇

双传输是怎么自动切换的

这是整个插件里最值得看的设计。Command Code 有两套服务端通道:标准 Provider API(/provider/v1/chat/completions 和 Anthropic 风格的 /messages)和官方 CLI 走的私有网关 /alpha/generate。前者只对 GOAT 及以上开放。

插件对两套都实现了,但不是靠一个用户开关来选——它靠服务端的拒绝来驱动。有权限的账号走标准端点;一旦 Provider API 回一个 upgrade_required,它就自动回退到 CLI 网关。所以 Go 套餐用户什么都不用配,插件自己知道该走哪条路。协议本身是按模型 id 固定的:claude-* 走 Anthropic Messages,其余走 Chat Completions。

两条路的差异主要在推理块怎么处理。CLI 网关那条路,历史推理要按内容顺序重放到 assistant 消息里;Provider API 那条路则用 reasoning_content 字段回传。为什么要这么麻烦——因为 DeepSeek 的思考模式在有工具调用时,如果 assistant 那一轮的工具调用没有带回顾推理,服务端会直接拒绝整个请求。

模型目录和快照同步

模型列表不写死在代码里。启动时从 GET /provider/v1/models 拉实时目录(这个端点是公开的,没有 key 也能浏览),缓存在本地,离线时用最后一次的缓存继续跑。

但那个公开端点只给 id、name、上下文长度这几项,不告诉你每个模型属于哪个套餐、支持哪些推理档位。这两项信息插件是从官方 command-code CLI 打包进去的模型表里读出来的,而且用一个 COMMAND_CODE_CLI_VERSION 常量跟着官方 CLI 走(当前是 1.53.1)。每次上游发新版,插件作者就重新核对一遍:请求体、端点、推理档位映射、套餐表、折扣、峰谷时段,全部对齐。

顺带说,上下架也是这么跟的。官方 CLI 退休某个免费促销(比如之前的 MiniMax 免费版),插件会把对应条目移掉,而不是让它在旧的过期时间上继续挂着。

搜索走的是哪条路

前面说搜索复用聊天的 key,具体是打到 Command Code 的 /alpha/web-search。这个端点和 CLI 网关 /alpha/generate 属于同一族,也就是官方 CLI 自己内置的那个 web_search 走的同一条路。所以它和 DeepSeek 原生的搜索后端是两回事——结果直接来自 Command Code。

key 是怎么找到的

按优先级依次尝试:组合配置里写的字面 apiKey、凭据服务里的引用(默认 COMMANDCODE_API_KEY)、启动环境变量、以及最后的兜底——官方 CLI 写的 ~/.commandcode/auth.json。所以你如果已经用 cmd login 登录过,插件直接就能用,不用重新配。

不想装 CLI 也行:设置页有个「登录 Command Code」按钮,走的是和 cmd login 同一套浏览器授权流程,批准之后 key 直接写进 DSH 的凭据服务,全程不经过浏览器。写进配置文件的字面 key 也被声明成了 secret 角色,会被 harness 从返回给浏览器的设置描述符里剥掉。

用量数据从哪来

/commandcode 和设置页那张卡片的数据,来自官方 CLI 使用的几个账号接口:/alpha/whoami、/alpha/billing/credits、/alpha/billing/subscriptions、/alpha/usage/summary。它们是非公开接口,所以插件的用量面板本质上和 CLI 看到的是同一份数据。

这类信息的获取是并行发的,而且每个端点独立降级——某个接口挂了不影响其他部分显示,只是那一块空着。

几个已知的坑

图片会话切模型会被拒。DSH 有一个刻意的保护:如果当前会话里已经带了图片,你把它切到一个纯文本模型,会被直接拒绝。这个 guard 在 dsh-host-apiproxy 里,插件侧改不了,它只能把错误文案改得好懂一点。要切就选带 Image 标记的模型,或者先把图片移出会话。

不支持 stop 序列。携带 stop 参数的请求会报错,这个在文档里明确写了。

长思考模型超时这件事,默认值已经调过了。streamIdleTimeoutMs 默认 300 秒,比早期版本的 120 秒宽松得多——因为前沿推理模型在 xhigh/max 档位下可以合法地沉默几分钟,原来的 120 秒会把"在思考"误判成"连接死了",然后触发重试,用户看到的现象就是"卡住,然后重连"。同理,requestTimeoutMs 只管等第一个字节,响应头一到就不再计时,避免长推理的 SSE 流被连接预算掐断。这两个值都能在设置页里调。

重试是持久的。瞬态失败(限流、5xx、超时、传输中断、空响应)最多重试 1000 次,等待从 500 毫秒起指数退避、封顶 15 分钟、带 ±10% 抖动;而永久性失败(无效 key、不支持的内容、套餐拒绝)第一次就失败,不会无意义地耗着。遇到 429 会尊重服务端的 Retry-After。最实用的一个后果是:当所有账户的用量窗口都耗尽时,会话会睡过窗口然后原地恢复,而不是两次快速尝试之后直接死掉。

卸载不会带走你的凭据。dsh plugin remove 之后,DSH 凭据库里的 key 和 ~/.commandcode/auth.json 都还在,重装就能接着用。

总结

这个插件的定位很清楚:把 Command Code 接入 DSH 这件事做全。模型目录、推理档位、图片输入这些是基础,真正拉开差距的是联网搜索(复用同一把 key,不用再配第二个)和被动式多账户轮换(稳态零额外请求,切换对模型透明),再外加一个数据相当完整的用量面板和终端支持。

选型上我建议看两点。一是它是不是只走 Provider API——如果是,Go 套餐直接排除。二是它的兼容性声明里有没有你的 DSH 核心版本,这类 provider 插件对内核对得很紧,版本对不上就是启动失败,而不是功能缺失。

最后提醒一句:这仍然是社区插件,走的是未公开接口,Command Code 一侧调整协议就可能失效。它移植自 pi-commandcode-provider(MIT),作者更新很勤(八天里发了七个版本),出问题去仓库开 issue 的响应速度应该还行。

赞(0)
未经允许不得转载:网硕互联帮助中心 » DSH 接入 Command Code Go 插件:模型、联网搜索与多账户轮换一次到位
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!