DSH WorkBuddy Connect
corrinehu/dsh-workbuddy-connect将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness,在 DSH 对话窗口里零配置使用。
将本机登录的 Trae 中国区模型接入 DSH,支持由 DSH 执行工具调用、账号切换,以及 Work/通用积分展示。
dsh-connect-trae
English · 安装 · 工作原理 · 模型覆盖范围 · 更新日志 · 问题反馈
一个独立的 DeepSeek Harness (DSH) bundle 插件。它把本机已登录的 Trae 账号(国内版、企业版与国际版均支持)接到 DSH 的模型选择器:模型负责生成结构化工具调用,bash / read / write / edit 等工具由 DSH 本地执行;同时提供用量概览(国内版 Work/通用积分、企业版租户额度、国际版订阅状态)、每日签到领取与模型管理界面。国内版、企业版与国际版是三个并行的供应商(`trae` / `trae-enterprise` / `trae-global`),可同时使用;插件设置卡片以 tab 区分三者,方便统一管理。
支持 macOS、Windows 与 Linux:CI 在 ubuntu-latest 与 windows-latest 上跑完整 typecheck / 测试 / 构建;Windows 侧的目录探测、应用版本头与锁行为均有针对性处理,详见 Windows 说明。
除每日签到领取外,插件的所有查询都是只读的、不消耗额度;签到领取也只在你点击按钮时才发生。
边界:本插件不与任何其它插件联动。 账号、凭据、模型目录、账号池与设置命名空间都只属于本插件;trae 失败不会借用别的插件的账号或额度,反之亦然。理由与具体含义见与其它插件的关系。trae provider(DeepSeek-V4-Flash、DeepSeek-V4-Pro 等),企业版注册为 trae-enterprise,国际版注册为 trae-global(Gemini / GPT / MiniMax 阵容),三边模型同时出现在 DSH 模型选择器里:不同会话可以各选一边,互不干扰。tob_online 租户,会被两个网关同时服务:消费池(扣个人积分)与租户池(扣企业额度)。同一模型、两种付费方,所以「谁付钱」由你显式选,插件不替你猜。trae 永不碰企业网关;trae-enterprise 不回落,被拒绝就如实报错,不会悄悄改用个人额度重跑。企业版默认关闭——纯个人账号用不了企业池,默认放开等于塞一条一用就失败的 provider。DeepSeek-V4.1-Flash 只有企业池列),所以勾选互不覆盖。dsh-connect-workbuddy)—— 上面那排地区是作用域(这张卡片讲的是哪个供应商),这一排是同一张卡片里的分栏:账号栏管「谁在服务、还剩多少、签到与账号池」,模型栏管「勾哪些模型、图片输入、上下文预算、保存」,诊断栏只读地列出面板名、供应商 id、服务账号、两种令牌到期时间、目录/已启用模型数、账号池与签到支持与否,以及本面板最近一次报错的原文。4.4.7 起诊断栏还多一行「损坏副本留存」:读不出来、因此被改名留存的账号副本会在这里被点名(连同它曾经保存了几个账号)——被顶掉的账号「去哪了」这个问题,从此不用再去 ~/.dsh 里翻文件名;未登录那一屏也会显示同一条通知,因为账号消失之后用户落地的正是那一屏。分栏的理由是提交语义不同:账号改动点一下即生效,模型改动是草稿、必须点「保存」——一列长页会把保存按钮放到离它要保存的东西三屏之外。切栏不重新拉取、不丢未保存的模型草稿、账号池日志也不重建;未登录时不出分栏,那一屏说明不会被看不见的 tab 藏起来。模型栏把所有模型一次性铺开,没有内层滚动条——不再是一个套在滚动页面里的小窗口,唯一滚动的就是卡片自己那一页。401 凭据被拒、额度耗尽、限流、上游 5xx);模型 id 写错、请求本身不合法不换号,因为那不是账号的问题,换号只会把同一个错误烧两遍、还冤枉一个没机会服务的账号。换号失败的真相会写进池的探针记录,下一次排序直接把它排到后面,而每一次结论都能在卡片上看到:可用 / 限流 / 额度耗尽 / 凭据被拒 / 套餐不覆盖 / 上游不提供 / 本次未测出,以及「什么时候可以重试」。关掉池就回到严格绑定,不会有任何残留 override。卡片里的「全部测速」会把每个成员按目标模型各测一次,结果边跑边显示(一行一个答案,不等整批跑完),并落盘成下次排序的依据。池是显式选择:默认关闭。它不会替你在没打开池的情况下换账号——「换账号等于换人计费」,所以这件事只能由你点头。池打开后卡片会明确写出当前是谁在付费(Host 报告的是「下一个真正发送请求的账号」,不是保存的那个绑定)。
GLM-5.2 · x0.79),倍率随目录刷新更新。activity_discount:折扣比例、原价、闲时时段与时区),插件按当前时钟判定后,在模型名旁边画一枚胶囊:5 折 / 闲时 5 折 / 限时 5 折,悬停写明原价、现价与时段。判定放在渲染时刻而不是解析时刻,所以夜间折扣不会在第二天早上继续挂着;上游说「此刻没打折」就不画,不从倍率反推,也不给没有结束时间的活动编「限时」。这是纯提示:不改请求、不改计费,国际区(订阅制)没有这项数据因此不显示。详见 docs/PROMO_BADGE.md。同一枚胶囊也画在 DSH 的模型选择器里(宿主 conversation.input.model.label 插槽),挑模型时就能看见——毕竟徽标画在设置卡片里时,你已经选完了。选择器里倍率只出现一次:名字里已有的目录倍率会被拆出来,有折扣时换成折后价(与卡片同一套时钟判定,同一份数据),打开选择器不会额外触发上游读。llm_utils_chat 获取待执行的结构化 tool_calls,交由 DSH 自带的本地工具执行,再将工具结果回传模型。userRegion 声明自动判定(host 后缀与 edition 标签兜底),无需手动指定。multimodal 时,插件直接按多模态对外声明,无需你在卡片上逐一手勾(issue #16)。判据是「你手动勾选的 ∪ Trae 标注多模态的」:Trae 明确标 false 或未标注的模型保持纯文本,你可以照旧手动为它们打开图片输入。卡片上被自动开启的那一行显示为已勾选且只读,并说明原因。详见下方「图片输入(识图)」。Trae / TRAE SOLO / 国际版),便于分辨凭据来自哪个安装。dsh-connect-workbuddy 互通,两边导出的文件可以互相导入。导入按账号去重(同一账号再导入即覆盖更新),认不出所属区域或因缺 Token 的记录会被跳过并计数——国内版与国际版是两条并行计费通道,跨区导入会导致跨区计费,所以这里只认同能正向识别的区域(企业版共用 CN 凭据池,不构成第三条导入通道)。导出文件里是有效 Token,请当作密码保管。(issue #37)ping、不带工具),逐个告诉你能不能真的应答:可用 / 需要更高档位(Trae 1005,你的套餐不覆盖)/ 上游不提供(4001,SOLO 通道没有这个模型)/ 被限流(4011,Trae 限了这条通道)/ 登录凭据被拒 / 本次未测出。最后一项是一等公民:超时、断连、代理、5xx 一律不算「不可用」——只有上游明确的拒绝才算负面结论。这是插件里唯一消耗额度的操作(签到改变的是账号状态,不消耗),只在你点击时运行,结果只留在当前会话里不写入设置。4011是限流不是「模型不可用」(issue #33 实测):它额度耗尽走的是另一个码4008,所以「额度还有很多却报 4011」两句话可以同时成立。被限流的模型等你一会儿再试即可,不要删。
签到 +150);该账号当天已领显示「已领取」并禁用,本机今日名额已被别的账号用掉时显示「本机已签」并禁用——如实区分「这个账号领了」和「这台设备领过了」,绝不把后者说成「已领取」。这是插件里唯一会改变账号状态的操作,由你主动点击触发;一次点击只针对该行账号、只发一次请求。Trae 的签到按「每台设备每天一次」计(换账号不会重置当天名额),所以逐账号签到始终是主路径。账号池里另有一个「全部签到」,它不是把同一件事盲目重复:一旦上游回 9095(本机今日已领),整批立刻停止并把剩余账号如实标成「本机已签」,产出的是真相而不是一排假失败。国际版没有签到活动,因此不显示该按钮。Pro / Free)。整块可点击,弹出浮层显示一张表格:本区域每个账号一行,国内版列通用积分、国际版列套餐,点行即可切换账号(写入与卡片相同的 accounts 字段、合并时不丢掉另一个区域的选择),并把手动刷新按钮放在浮层里。只在当前会话选中的模型属于本插件时出现——选其它供应商的模型时整块不渲染。这样两个连接器插件不会争同一个位置(侧边栏底部是共享的根级行,输入框工具栏是按会话、按供应商的)。读数显示在哪里可以选(学自同族 dsh-connect-workbuddy issue #62)。默认在输入框工具栏(即上面说的位置);如果那里被别的插件占了、读数不显示,改成输入框下方——那是「轮次 / 步数 / token」统计所在的那一行,读数是追加在官方统计之后,不会顶掉它们。位置按面板分别设置(三个面板各存各的),在卡片「设置」区紧挨「在输入框工具栏显示积分读数」那个勾选框。之所以要有第二个位置:输入框工具栏是共享的 list 插槽,外壳自己的控件和其他插件都注册在那里,而共享插槽无法保证每个占用者都可见——同族的报告者装了第三方插件后读数就整个消失了(本插件早年放在侧边栏底部时也被挤成过一个「Tr」的残片)。
DSH PiAiAdapter(每个 provider 一套)
-> 安全 loopback shim(每区域一个随机端口 + 进程内随机 secret)
-> TraeSoloBridge
-> 国内版 https://trae-api-cn.mchost.guru/api/agent/v3/llm_utils_chat
-> 企业版 https://console.enterprise.trae.cn/api/agent/v3/llm_utils_chat
-> 国际版 https://coresg-normal.trae.ai/api/agent/v3/llm_utils_chat
-> Trae SSE / pending function_call
-> OpenAI SSE tool_calls
-> DSH 本地执行工具并回传结果每个面板各持一套完整的运行时栈——凭据 store、模型 catalog、wire 映射、上游客户端、回环 shim、adapter——按凭证自带的区域声明隔离可见账号,所以多个区域的账号可以同时在线、同时被不同会话使用。
面板不是区域。 cn 与 ai 恰好与两个区域一一对应,但企业池共用 cn 凭据却计费到另一个账户、供另一份名录,它需要自己的开关、自己的账号绑定与自己的模型选择——那正是「面板」这个概念。把面板与区域分成两个概念,enterprise 就能用同一套设置管道处理,存储形状不变:它只是 regions 映射里的又一个槽位。
国内区因此并列发布两个 provider,路由在构建 provider 的客户端时固定,不存在「按调用猜一次」:shim 为每个 provider 提供一条 bearer 路由并按 bearer 分派,未知 token 直接 401,不会退回第一条路由。企业网关要求每次调用带 session_id,而消费网关会拒绝带它的请求体,所以只在该路由上加。
用量概览走 https://api.trae.cn/trae/api/v2/pay/* 与 /trae/api/v2/ug/* 只读接口(国际账号走其自有网关的订阅状态端点);每日签到领取是其中唯一的写操作,走 POST /trae/api/v2/ug/checkin_credits/claim,需要携带本机安装的设备号(x-device-id,与聊天通道同源)。该设备号也正是签到「每台设备每天一次」的判定依据,所以换账号不会重置当天名额。刷新得到的 token 按区域存放在 $DSH_HOME/.trae-auth.cn.json 与 $DSH_HOME/.trae-auth.ai.json(两个账号同时在线互不覆盖;旧的单文件 .trae-auth.json 作为迁移来源保留读取)。
详见docs/IMPLEMENTATION_PLAN.md、docs/SOLO_ROUTE_DECISION.md、docs/USAGE_API_RESEARCH.md。
本插件不与任何其它插件联动。 这是一条边界,不是一句口号:
$DSH_HOME/.trae-auth.*.json、.trae-auth.deleted.*.json、.trae-pool.*.json)与自己的设置命名空间,不读、不写、也不为任何别的插件供数。它确实会编辑 Trae 桌面应用自己的登录文件,但那是另一个应用,不是另一个插件。trae 失败就是失败,不会去「借」另一个连接器插件的账号、额度或通道,也不会把请求转交给别的插件重试。反方向同样成立:没有任何插件能通过本插件代发请求。modelSelection 投影),不靠插件间通信分配位置。两个连接器插件同时安装时,它们靠「各自只在自己的 provider 被选中时出现」共存——这是互不干扰,不是协作。为什么立这条边界。 插件之间一旦互相依赖,任何一个插件的升级、卸载或版本线变化,都会悄悄改变另一个插件的行为;而 DSH 的加载顺序、多版本并存与用户自定义 profile 让这种耦合无法可靠表达。立住这条边界,「出问题的是谁」永远可以定位到一个插件,而不是一串。
同一族插件之间互相学习(dsh-connect-workbuddy 的教训被写进本仓库的注释与测试),但不互相调用——学习是编译期的事,联动是运行时的事,这两件事必须分开。插件对外声明「这个模型是否接受图片」,DSH 据此决定附图是原样发出还是降级成文字描述。所以这条声明是硬开关,不是一个无关紧要的标记。
判据是两个来源的并集(issue #16):
来源 · 含义 Trae 目录自带的 multimodal 字段 · Trae 自己对「这模型读不读图」的回答。Trae IDE 本体的附图按钮就是纯粹由这个字段驱动的,没有用户开关 你在卡片上手动勾选的 imageModelIds · 显式选择。即便 Trae 后来不再标注该模型,你的勾选也不会被撤掉
要点:
false,都按纯文本处理——宁可不发,也不对一个能力不确定的模型谎报「支持图片」。false(或未标注)的模型依然有效,这是为那些「上游没标但实际可用」的情况留的口子。插件提供的是 Trae SOLO 通道的模型(DeepSeek-V4-Flash-Official、DeepSeek-V4-Pro-Official、GLM-5.3、GLM-5.2、Kimi-K3、MiniMax-M3、Qwen3.8-Max、Doubao-Seed-* 等),三个面板均走这条通道。企业池另有一份名录(例如 DeepSeek-V4.1-Flash 只有企业池列),所以两边勾选互不覆盖。
以下 2 个模型目前来自 TraeCode(Trae IDE)通道,尚未开放到 SOLO 通道:
模型 kimi-k2.8-preview qwen3.8-flash
它们会出现在模型列表里(Trae 的目录列出了它们),但插件侧暂时没有可调用它们的通道。选中后发送消息会得到一条明确的错误,例如:
Trae does not serve this model under the SOLO function the request used
(config_name rejected) · Trae code 4001 · upstream: We're sorry, the param is invalid…即「上游不提供该模型」被如实说明,而不是静默失败或像网络故障。官方把它们开放到 SOLO 通道后,插件会自动可用(判据就是能不能拿到调用 id),无需升级插件。
同一条报错的另一种成因(3.5.1 已修,issue #38):DeepSeek-V4 四行曾报同样的 4001,但成因相反 ——它们在上游名单里本来可以调用,只是 CN 区的 wire 把同一族列了三行且共享展示名,旧代码让最后一行
(元数据残缺的小写行deepseek-v4-flash)抢走了展示名键,桥接层据此把config_name改写成小写拼写,
上游拒收。判别方法:看这个模型在上游名单里有没有调用 id —— 有而报 4001,就是这一类。
3.5.1 起两张映射表都改为先到先得,不再发生改写,四行已实测恢复正常。
为什么现在会显示(2026-10-02 起的策略):此前这类「目录里有、但拿不到调用 id」的模型会被直接隐藏,理由是「放出来只会报错」。但可调用名单是按账号档位下发的——在免费账号上测不到,不等于付费账号用不了(issue #19 的报告人就是 Pro:他的账号能调用本机免费账号被门禁挡住的模型)。隐藏用户自己 Trae IDE 里有的模型,比让他看到一条明确的错误更糟,所以改为:全部呈现 + 如实报错。
deepseek-v4.1-flash曾在此列——docs/DS41_CALLABILITY.md(2026-09-15 取证)实测 8 个 SOLO function
全部返回 4001 param is invalid。上游后来把它开放到了 SOLO 通道:当前实时目录里它带wireFunction: solo_work_remote,可正常调用(已实测刷新确认)。文档此前未同步,现已从表中移除。glm-5.3-flash 同样曾在此列,4.4.0 起已移除:上游后来开放了它,当前实时 wire 名单里它带wireFunction: solo_work_remote(实测)。目录侧那一行一直都在——它此前被列出来的原因是Remote 目录列出了它而 wire 名单没有,于是既拿不到调用 id、也从未进入可调用名单;
4.4.0 修好了「wire 有而目录没有」与「目录问了但没问全」两处之后,它作为普通可调用模型出现。
注意区分:`GLM-5.3` 是支持的(走 SOLO 通道)。glm-5.3-flash 现在也支持了——它与 GLM-5.3 始终是两个不同的模型,但前者已开放到 SOLO 通道。如果你现在就要用这 3 个模型,请直接在 Trae IDE 本体中使用。
模型卡上的「最大输出」来自 Trae get_detail_param 的 model_detail_list[].max_tokens —— 上游是发布这个值的(CN 实测 80/80 config 都带)。4.0.1 起它随目录合并一路带到卡片、/models/refresh 与 DSH 模型注册;此前合并层漏传了这个字段,整区模型全部显示空白(issue #42,诊断见 docs/ISSUE42_DIAGNOSIS.md)。仍然空白的行是诚实的:目录里有、但 SOLO 名单里没有对应 config 的模型(上面那 3 个 TraeCode 通道行)拿不到任何候选值,宁可空白也不编一个上限。这个值是元数据,插件不把它写进请求体(输出上限由 Trae 服务端决定)。
上下文窗口在 Trae 公布的默认(dev)档与 Max 档之间选,4.4.8 起对宽窗模型多一个 500K 中间档,按面板逐模型存成 contextBudgets。500K 不是上游公布的窗口,是本地的半步:dev 常见 200K/256K/272K,Max 常见 1M,从默认直接跳到 Max 是 5 倍,而 1M 的计费并不是每个会话都用得上。所以它是有门槛的:只有当该模型的 Max ≥ 500K、且 500K 确实比 dev 宽、又确实比 Max 窄时才出现——applyContextBudgets 用同一条规则(contextBudgetOptions)校验,落盘值不是该模型可选窗口就一律退回 dev 档,绝不会把模型撑到它没有的窗口(比如某模型后来被上游把 Max 调到 256K,旧的 500K 会安静地失效而不是溢出)。
想整区一次切换:模型管理区有「整区切到 500K」(给本区所有 Max ≥ 500K 的行写入 500K,其余不动)、「整区切到 Max」(给每个带 Max 档的行写入其 maxContextWindow,没有 Max 档的行不动)和「全部恢复默认上下文」(清空本区预算)三个按钮,作用在草稿上、按「保存」生效,与逐行单选落盘的结果完全一致(issue #42 附带需求——CN 有 18 个 Max 模型,以前要点 18 次)。
推荐使用 DSH 插件命令安装 npm 已发布版本:
dsh plugin --profile desktop add dsh-connect-trae或直接通过 npm 安装:
npm install dsh-connect-trae安装、更新或卸载 bundle 后,需要重启对应的 DSH 进程。
要求 DSH 0.1.7-rc.1 及以上(2.3.0 起不再支持 0.1.7 之前的宿主;peer 依赖范围已按此收窄)。 peer 上界为 `<0.3.0-0`:0.1.7 与 0.2 两条线均受支持(含 0.2.1-rc.3,已实测)。
DSH 自己横跨 @earendil-works/pi-ai 的两代,而本插件解析到哪一代由你的安装环境决定, 未必是宿主那一代——插件声明它是 peer,这是对的,但两代对「上下文长什么样」的定义不同:
· 旧代(≤0.85) · 新代(0.86+) 形状 · { systemPrompt, tools, messages } · { messages: [ {role:'system', content, toolsAdded}, … ] } 系统提示 · 顶层 systemPrompt · 只挂在那条 system 消息上 工具声明 · 顶层 tools · 只挂在那条 system 消息的 toolsAdded 上
错配两个方向都会坏,所以 3.4.2 起插件会按自己解析到的那一代双向适配(issue #27):
role === 'system' 分支,会去迭代一个字符串并抛Cannot read properties of undefined (reading 'length')。这一步在请求构造之前,所以表现为 「任意模型都崩、耗时极短、usage 恒为 0」。
全部工具声明丢失(模型永远不会产生 toolCall)。这类故障更隐蔽,同样已修。
代际判据是本插件自己解析到的那份包(读它的 manifest 版本;读不到时看包布局), 不是宿主版本——因为嵌套的旧副本会盖过宿主的新副本,反之亦然。启动时日志里会有一行 dsh-connect-trae: pi-ai (),legacy 表示你这份安装解析到了 ≤0.85 的旧代。
分界线是 0.86:dist/utils/transcript.js、normalizeContext、估算器的 system 分支、 以及「不再读顶层字段」这四件事同时出现在 0.86.0。按 0.87 划分会把 0.86.x 误判成旧代而错误折返, 反而丢掉提示与工具。
0.2.0 线对本插件没有契约破坏——逐符号核对确认插件消费的 API 全部未变(完整的 0.2.0-rc.1 影响面核对)。但 0.1.7 起 DSH 有一道bundle 级 peer 门禁: peer 范围不满足的 bundle 会被整体跳过,只往 stderr 写一行,界面上表现为「插件凭空消失」。
宿主 0.2.1-rc.1 把 @earendil-works/pi-ai 从 ^0.85.1 抬到了 `^1.1.0`(0.2.1-rc.2 / 0.2.1-rc.3 均保持不变),这是 0.2 线里 唯一有实际行为影响的变化。三项结论: