可以在 DSH 中使用 WorkBuddy 里面的模型
36.2/100
综合分
3
GitHub 星标
441
npm 周下载
—/5
用户评分
数据截至 2026/10/12 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-llm-workbuddynpm 源 · dsh-llm-workbuddy 的发布者账号已校验与本仓库一致
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · other
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 22 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-llm-workbuddy @ 0.1.27
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 20:00:20
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 33 处,展示前 27 条)
- 写入本地文件lib/index.js:596
mkdirSync(dirname(file), { recursive: true }); - 写入本地文件lib/index.js:608
appendFileSync(file, `${line}\n`); - 写入本地文件lib/index.js:644
renameSync(file, usageArchivePath()); - 删除本地文件lib/index.js:678
try { rmSync(lock, { force: true }); } catch { } - 读取本地文件lib/index.js:689
return statSync(file).size > USAGE_ROTATE_AFTER_BYTES; - 读取本地文件lib/index.js:702
if (Date.now() - statSync(lock).mtimeMs < USAGE_LOCK_STALE_MS) return false; - 删除本地文件lib/index.js:703
rmSync(lock, { force: true }); - 读取本地文件lib/index.js:765
lines = readFileSync(file, "utf8").split("\n").filter(Boolean); - 发起网络请求lib/index.js:1058
const response = await fetch(`${connection.baseURL}/models`, { signal: controller.signal }); - 发起网络请求lib/index.js:1165
const iterator = this.request(options, watchdog.signal, connection, () => watchdog.pulse())[Symbol.asyncIterator](); - 发起网络请求lib/index.js:1245
response = await fetch(`${connection.baseURL}/chat/completions`, { - 读取本地文件lib/index.js:1420
return JSON.parse(readFileSync(checkinStatePath(), "utf-8")); - 写入本地文件lib/index.js:1430
mkdirSync(dirname(file), { recursive: true }); - 写入本地文件lib/index.js:1431
writeFileSync(file, `${JSON.stringify(state, null, 2)}\n`); - 发起网络请求lib/index.js:1460
const response = await fetch(`${baseURL.replace(/ $/, "")}${path}`, { - 读取本地文件lib/index.js:1688
sessionFile = existsSync(legacySession) ? legacySession : defaultSessionFile(); - 读取本地文件lib/index.js:1775
const fromMtime = Math.round(statSync(sessionFile).mtimeMs) + expiresIn * 1000; - 发起网络请求lib/index.js:1946
const response = await fetch(`${baseURL.replace(/ v1 ?$/, "")}/health`, { - 发起网络请求lib/index.js:2033
const response = await fetch(endpoint, { - 执行外部命令固定命令lib/index.js:2219
const child = spawn("python3", args, { env: { ...process.env, PYTHONUNBUFFERED: "1" } }); - 发起网络请求lib/client.js:351
return fetch("/api/workbuddy/status") - 发起网络请求lib/client.js:368
fetch("/api/workbuddy/login" + (force ? "?force=1" : ""), { method: "POST" }) - 写入剪贴板lib/client.js:404
return navigator.clipboard.writeText(text); - 发起网络请求lib/client.js:499
fetch("/api/workbuddy/diagnose", { method: "POST" }) - 发起网络请求lib/client.js:609
fetch("/api/workbuddy/usage") - 发起网络请求lib/client.js:703
fetch("/api/workbuddy/checkin", { method: "POST" }) - 发起网络请求lib/client.js:726
fetch("/api/workbuddy/refresh-models", { method: "POST" })
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-llm@deepseek-ai/dsh-settings@deepseek-ai/dsh-timeout@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
最近更新
在 GitHub 查看全部 →v0.1.262026-10-12
· Changed
· 修复图片输入的一个 bug
· 具体修了什么
两处 bug 都会让只要历史里出现过图片的每一轮请求失败,并误报成
WorkBuddy proxy stream from failed:
1. 传给附件服务的 target 形状错了。 serializeMessages 传的是
{maxPixels, maxBytes},但 attachments.readImageRequest 要的是
ImageRequestTarget —— {width, height, maxBytes}。真实后端以
INVALID_ATTACHMENT_REF("Image request width must be a positive
integer.")拒绝,而 AttachmentError 不是 LlmError,于是被兜底重标成
TRANSPORT。代理其实一条请求都没收到,重试重发同一历史必然再失败。
现在按官方适配器(dsh-llm-pi-ai / dsh-llm-deepseek)的做法,用
requestImageDimensions 投影出目标尺寸。
2. tool 结果里的图片被丢掉了。 read_image 把图片字节放在 tool 结果内部,
而 serializeToolResult 把它 flatten 成纯文本,模型只会回"没有图片"。
现在保留文本并追加 image_url 部分。
· 验证
· 新增 test/image-serialize.test.mjs,用真实的 dsh-attachment-local
校验 target 形状;把修复回退后该测试确实失败(6 项挂 2 项),确认能捕获此 bug。
· 端到端:用真实的 app_home_qrcode.png 走真实附件服务 + 真实代理,
HTTP 200,模型正确描述出"二维码 / 中央有白色方块和星芒状图标"。
本 bug 自 0.1.9 引入(0.1.11 进一步确认了错误形状),此前 readImageRequest
从未被测试覆盖。桌面端安装的是同一份代码,升级到 0.1.26 即修复。
v0.1.202026-09-28
1.适配 DSH 新版本 0.1.7;
2.胶囊支持拖动移动,避免可能的遮挡;
3.当代理未启动,支持直接打开终端执行;
v0.1.182026-09-22
· 安装
dsh plugin --profile web add dsh-llm-workbuddy
· 或
npm i dsh-llm-workbuddy@0.1.18
本版含插件侧与本地代理侧两类修复,正文里用 [插件] / [本地代理] 标注了范围。
---
修复「任务跑着跑着就死、显示得像断联、之后再怎么重试也起不来」这一类问题。
根因是三条,都只在 WorkBuddy 这条链路上(原生 DeepSeek 不受影响)。
改动范围:[插件] 的随本包发布,装了就生效;[本地代理] 的在本机
.workbuddy-src(start-workbuddy.sh 用的那份源码)里,使用 PyPI 版
workbuddy2api 的用户不受影响。不过 [插件] 的错误帧解析对任何代理都有效,
所以"一次 429 就让整场任务死掉"这个问题对所有用户都修好了。
· Fixed
· [插件] 上游的 HTTP 错误被吞掉,任务当场死亡且不可重试(主因)。
代理在流式请求里先发 200 响应头、之后才知道上游状态,于是上游的
429 / 400 / 5xx 只能作为 data: {"error": …} 事件写进 SSE,而且写完直接
return,不补 [DONE]。适配器只看到"流结束了却没有 [DONE]",抛出
STREAM_CLOSED;而 STREAM_CLOSED 不在 harness 的重试策略里
(EMPTY_RESPONSE / RATE_LIMIT / SERVER / TIMEOUT / TRANSPORT)—— 一次限流
就让整个任务终结,且同样的请求下次还是被拒,用户看到的就是"卡死、无法继续"。
实测证据:09-16 上游 4 次 429 code 6004 您的使用量已超出频率限制(含重置时间)
↔ 会话记录里 5 次 STREAM_CLOSED;09-04 上游 6 次 400 code 11133。
现在:
1. 适配器把 error 帧翻成真正的 LlmError:配额类(6004 / "使用量已超出"
/ quota)→ QUOTA,429 → RATE_LIMIT,400 → INVALID_REQUEST /
CONTEXT_WINDOW_EXCEEDED,5xx → SERVER,并把上游原文(含"将在 … 重置")
带进错误信息;
2. 代理在所有结束路径(含错误、超时、内部异常)都补 data: [DONE],
并给错误帧带上 code / type / 可读原因;
3. "一个字节都没收到就断开"映射为可重试的 EMPTY_RESPONSE,已经有内容再断开
仍保持 STREAM_CLOSED(截断的回答不能当完整回答用)。
· [本地代理] 60 个工具被静默砍到 30 个(上下文自相矛盾)。DSH 一次发 60 个工具,代理
硬编码 MAX_TOOLS = 30 且按顺序截断;DSH 的工具表是字母序,前 30 个恰好
全是 ego_* 浏览器工具,被丢掉的正是 read / write / grep / glob /
todo_write / web_search / subagent / present …,而 system prompt 里
仍然写着这些工具。模型于是调用"没声明"的工具、或者干脆长时间只出推理不出
工具调用(实测一次卡住的 step:9727 字符推理、116 秒、无工具调用,最后被用户
中止)。实测上游接受 60 个工具(HTTP 200),所以默认上限提到 64,可用
--max-tools 调整,真发生截断时会把被丢掉的工具名写进日志(不再静默)。
· [插件] 探测抖动被当成掉登录(胶囊假红)。状态胶囊的判定是
status.authenticated && status.proxyUp,而 proxyUp 来自一次
2 秒硬超时、只试一次 的 /health 探测 —— 本机任何一次短暂卡顿都会让
胶囊直接显示 WorkBuddy · 未登录,哪怕会话文件完全有效。现改为:
每次探测 8 秒、失败重试 1 次、连续 2 次失败才报告 proxyUp: false
(连接被拒绝时立即判定,因为那确实说明代理没了);/status 与诊断面板
额外返回 lastProbeError / consecutiveProbeFailures / degraded。
· [插件] 胶囊只有两态,把"代理没响应"也说成"未登录"。现在三态:绿=已登录、
黄=代理未响应(登录态仍有效,不提示点登录,避免多占一次上游)、
红=未登录(只有会话真的无效时才出现)。
· [插件] 中止任务后
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。
README
由 DeepSeek 最新模型翻译生成dsh-llm-workbuddy
npm version
license
Changelog
在 DeepSeek Harness 中使用你的 WorkBuddy / CodeBuddy 账号模型的 LLM 适配器插件。
它把 workbuddy 这个 provider 路由指向本地运行的 workbuddy2api 代理(默认 http://127.0.0.1:8787/v1)。workbuddy2api 把 CodeBuddy/WorkBuddy 的私有协议转成标准 OpenAI chat-completions 格式,并用本地保存的登录态完成认证,因此本插件不需要任何 API Key。
装好并启动后提供两件事:
1. 模型能力:Web 界面的模型选择器(composer 模型菜单或 /model 命令)会多出一个 WorkBuddy 分组,模型(DeepSeek-V4、GLM-5.x、Kimi-K2.x、MiniMax-M3、 Hy3、Hunyuan…)随账号可用列表实时同步,点一下即可切换;支持推理的模型还会显示推理等级选择器(Low / Medium / High)。
2. Web 登录状态小组件:在 Web GUI 右下角常驻一个状态胶囊,实时显示登录/ 代理状态,未登录时一键在新标签页打开 WorkBuddy 登录页,登录完成后自动变绿。
展开完整文档(README 剩余 1 节)
dsh-llm-workbuddy
npm version
license
Changelog
在 DeepSeek Harness 中使用你的 WorkBuddy / CodeBuddy 账号模型的 LLM 适配器插件。
它把 workbuddy 这个 provider 路由指向本地运行的 workbuddy2api 代理(默认 http://127.0.0.1:8787/v1)。workbuddy2api 把 CodeBuddy/WorkBuddy 的私有协议转成标准 OpenAI chat-completions 格式,并用本地保存的登录态完成认证,因此本插件不需要任何 API Key。
装好并启动后提供两件事:
1. 模型能力:Web 界面的模型选择器(composer 模型菜单或 /model 命令)会多出一个 WorkBuddy 分组,模型(DeepSeek-V4、GLM-5.x、Kimi-K2.x、MiniMax-M3、 Hy3、Hunyuan…)随账号可用列表实时同步,点一下即可切换;支持推理的模型还会显示推理等级选择器(Low / Medium / High)。
2. Web 登录状态小组件:在 Web GUI 右下角常驻一个状态胶囊,实时显示登录/ 代理状态,未登录时一键在新标签页打开 WorkBuddy 登录页,登录完成后自动变绿。
无需再回到终端手动跑登录脚本。胶囊可以拖到页面任意位置(刷新后回到右下角)。
架构一览
┌──────────────────────────── DeepSeek Harness Web GUI ───────────────────────────┐
│ │
│ [ 模型选择器 (WorkBuddy 分组) ] [ WorkBuddy 状态胶囊 (默认右下角·可拖动) ] │
│ │ │ │
│ │ GET /v1/models (代理发现) │ GET /api/workbuddy/status │ │ ▼ │ POST /api/workbuddy/login │ │ lib/index.js (WorkBuddyAdapter) ▼ │ │ │ fetch lib/index.js │ │ ▼ POST /chat/completions (registerWorkbuddyRoutes) │ │ workbuddy2api 代理 (127.0.0.1:8787) ──health──▶ ├─ 读 .workbuddy/session.json│ │ │ ├─ 探测代理 /health │ │ ▼ └─ spawn login_workbuddy.py │ │ WorkBuddy / CodeBuddy 云端 │ │ │ ▼ │ │ login_workbuddy.py ──▶ 写回 │
│ (设备流) session │
└──────────────────────────────────────────────────────────────────────────────────┘
- 后端路由(lib/index.js 的 registerWorkbuddyRoutes)运行在 dsh web 的 HTTP 服务上,通过 Cordis 的 webServer 服务注册(用 ctx.get("webServer") 探测,webServer 不列入 inject),headless profile 下自动跳过。
- 前端胶囊(lib/client.js)是零依赖的原生浏览器 JS,由 DSH 的 dsh.client 双端机制注入(client-modules 的 /plugins/??…/client.js combo 路由下发)。
宿主每 500ms 轮询 bundle 元数据,文件一改就推送 rebuilt 帧,浏览器端 client-hmr 会热重载本插件并重新 apply()——所以改完 lib/client.js 不用重启 dsh web,页面上的胶囊会自己换新(靠 ctx.effect 的卸载函数清干净)。
- 登录脚本(login_workbuddy.py,仓库根)实现与官方 CodeBuddy 插件一致的 device flow(platform=CLI + codebuddy.cn 请求头)。
前置条件(重要)
1. 代理必须独立安装并运行:本插件不打包第三方代理 workbuddy2api。
请在你的机器上单独安装并启动它(见下方「安装代理」),它把 WorkBuddy/CodeBuddy 的私有协议转成标准 OpenAI chat-completions 格式。
2. 代理版本需 workbuddy2api >= 2.0.4(推荐直接从 PyPI 装,见下方「安装代理」):
- 2.0.3 及更早不可用:缺少 X-Product-Code / Genie-IDE 等请求头与企业认证头(_enterprise_headers / X-Domain),登录会在最后一步 401;
- 2.0.4 已包含该修复("修复登录账户轮询与企业认证 headers 传递"),登录成功;GitHub main 当前与 2.0.4 内容一致,两者皆可。
- 2.0.4 同时修掉了"回答卡在半句话 / 被静默截断"(commit "修复 DSML 流式缓冲器吞掉含 '、HTML、
a = 2.0.6。
- ⚠️ 从源码启动的要注意:git clone 后停在旧 commit(例如 57f6b03,它正是上述修复的父提交)再 uv run python -m codebuddy_proxy,拿到的仍是有 bug 的版本。用源码方式请 git pull 到 >= 2.0.4 的提交。
- 代理 /health 若返回 version / features,插件会据此判断并在胶囊上显示「代理过旧」 + 升级命令;上游 2.0.4~2.0.6 不返回这两个字段,此时插件无法远程判断,只能按本节的版本要求自行确认。
3. 登录使用插件内置的 login_workbuddy.py(本包自带,依赖系统 python3,纯标准库,Python 3.7+ 即可),不需要代理自带的 --login(VSCode platform 会 401)。
4. 插件装入 profile 后需要重启 dsh web 才能加载新的 bundle(包括本小部件)。
关于「🎁 签到」:该功能依赖代理提供 /v1/checkin-status 与 /v1/checkin 转发。截至 workbuddy2api 2.0.4,代理并未实现这两个端点(任何分支/PyPI 版本都没有)。插件会自动探测:探测到 404 时隐藏签到入口、并且不再每天自动尝试,因此不会产生无效的失败记录。若将来代理补齐了这两个端点,签到入口会自动重新出现,无需升级插件。
安装插件
在插件包目录(本仓库 dsh-llm-workbuddy/)执行:
dsh plugin --profile web add ./dsh-llm-workbuddy
从 npm 发布版安装(正式发布后,朋友或你自己在任何机器上):
dsh plugin add dsh-llm-workbuddy
直接从 GitHub 仓库安装(不需要等 npm 发布):
dsh plugin --profile web add github:zdk119746/dsh-llm-workbuddy
兼容性:插件声明的 DSH peer 范围是 @deepseek-ai/dsh-llm / dsh-settings / dsh-timeout 的
^0.1.1-rc.2 || ^0.1.5-rc.1 || ^0.2.0-rc.2,覆盖 *DSH 0.1.1-rc.2 ~ 0.1.7 以及
0.2.0-rc.2(含桌面端)。
DSH 从 0.2.0 起会在安装和启动时用 semver.satisfies 校验这组 peer,范围不匹配就以 incompatible-version 拒绝安装(GitHub / tarball 规格是装完再判,表现为 "pnpm 装好了又被回滚")。如果你在更早的插件版本(≤ 0.1.21)上看到 installation rejected: … is incompatible with dsh 0.2.0-rc.2,升级到 0.1.22 或更新即可;dsh plugin allow-version … --accept-risk 那条豁免是给真的不兼容的插件用的,本插件不需要。
⚠️ 刚发的新版本装不上?那是 pnpm 的发布冷却期,不是插件不兼容。
DSH 桌面端内置 pnpm 11,而 pnpm 11 默认开启供应链保护 minimumReleaseAge:发布时间不足 1 天(1440 分钟)的版本不会被解析。所以在你发完新版后的头 24 小时里,裸包名安装会被静默降级到"冷却期之外的最新版",然后 DSH 拿那个旧版本去校验 peer,报出 dsh-llm-workbuddy@0.1.20 与 DSH 0.2.0-rc.2 不兼容——报的版本号小于你刚发的版本,就是这个原因。
三种解法(任选其一):
1) 装的时候写死精确版本,立刻生效(推荐)
dsh plugin --profile desktop add dsh-llm-workbuddy@0.1.22
2) 或者等满 24 小时后再用裸包名
dsh plugin --profile desktop add dsh-llm-workbuddy
3) 或者关掉这个 profile 的冷却期(写入 profile 的 pnpm-workspace.yaml) minimumReleaseAge: 0
用第 1 种方式时 pnpm 会提示 Added 1 entry to minimumReleaseAgeExclude in pnpm-workspace.yaml,这是正常的——它把这次显式指定记成豁免,之后同 profile 里的裸包名安装也会用上这个版本。
CLI 会把依赖写进 profile 并把 dsh-llm-workbuddy 追加到 dsh.profile.bundles,同时在 package.json 的 dsh.client 声明里登记浏览器入口(见下文「Web 小部件工作原理」)。然后重启 dsh web / 桌面端。
本插件没有构建步骤:lib/client.js 是浏览器原生 JS 直接被 serve;登录脚本 login_workbuddy.py 已打进包内,用系统 python3 运行(纯标准库,无需 uv)。
唯一需要自己装的是第三方代理 workbuddy2api。
安装代理(先决条件,第三方)
插件只提供模型路由与登录;真正的协议转换由 workbuddy2api(第三方开源项目)完成。
它不在本插件包里,需要单独安装并启动在 127.0.0.1:8787。分两种情况:
全新机器 / 标准安装(任何能跑 Python 的机器)
别人或你自己在新机器上用 npm 版插件时,推荐直接用 PyPI 装(版本 >= 2.0.4):
1. 安装 uv(本机 Python 工具,若已装可跳过)
curl -LsSf https://astral.sh/uv/install.sh | sh
2. 安装代理(PyPI,需 >= 2.0.4;2.0.3 及更早缺登录所需请求头)
uv tool install -U workbuddy2api
3. 启动代理(监听 127.0.0.1:8787;先完成下方「登录」后再真正调用模型)
workbuddy2api --desensitize \
--session-file ~/.codebuddy-session.json \
--log-file ~/.codebuddy-proxy.jsonl
或者:从 GitHub 源码运行(等价,main 与 2.0.4 内容一致)
git clone https://github.com/hawklithm/workbuddy2api.git
cd workbuddy2api
uv run python -u -m codebuddy_proxy --desensitize \
--session-file ~/.codebuddy-session.json \
--log-file ~/.codebuddy-proxy.jsonl
之后任何时候想重启代理,重跑上面第 3 条命令即可(用 uv tool 安装时直接跑 workbuddy2api ...)。若提示 address already in use,先停掉旧代理: lsof -tiTCP:8787 -sTCP:LISTEN | xargs kill,再重跑。
本仓库本地开发(可选快捷方式)
仓库根目录提供 start-workbuddy.sh,它会用仓库固定的 main 分支源码 + 本地 .tools/uv 工具链 + 仓库内的 .workbuddy/session.json 启动代理。它不随 npm 包发布,仅面向本仓库开发时方便:
cd /path/to/dsh-workbuddy
./start-workbuddy.sh
验证代理是否真的能用
curl http://127.0.0.1:8787/health # {"status":"ok","authenticated":true,...}
curl http://127.0.0.1:8787/v1/models # 模型列表(含 glm-5.3-flash / glm-5.2 / deepseek-v4-pro ...)
⚠️ /health 只证明代理进程活着,不能证明模型能真正出字(代理进程指向旧路径/文件缺失时 /health 仍返回 authenticated: true,但所有模型请求 500)。
想确认"模型真能用",用右下角胶囊的 🔍 诊断 按钮,它会真实发一次模型请求。
登录态过期时 authenticated 变回 false,重跑登录即可,代理无需重启(会话按请求读取)。
登录:两种方式
方式 A(推荐):在 Web GUI 里点一下
1. 浏览器打开 dsh web(默认 http://127.0.0.1:3080)。
2. 看右下角的状态胶囊:
- 🟢 WorkBuddy · —— 已登录,无需操作。
- 🔴 WorkBuddy · 未登录 或带 代理未运行 提示 —— 点胶囊里的 「登录」 按钮。
3. 点击后,后端 POST /api/workbuddy/login 会 spawn 运行 login_workbuddy.py,解析它打印的设备流链接(authUrl)返回给前端;前端用 window.open 在新标签页打开该登录页。
4. 在新标签页用 WorkBuddy / CodeBuddy 账号(腾讯账号)完成扫码/授权。
5. 胶囊会自动从每 5 秒轮询加快到每 2 秒(最多 30 次),一旦会话的过期时间(见下方「登录态判定」)显示仍有效且含 accessToken,就切回绿态,显示账号昵称。
整个过程不需要离开浏览器、不需要回终端。
🔑 重新登录(强制重登):胶囊 ⚙️ → 🔑 重新登录 会带 ?force=1 调用登录接口,忽略本地会话判定直接重跑设备流。该入口始终可用:本地判定依赖从会话文件推导的过期时间,只是启发式(见下),token 被提前吊销时它仍会显示"有效",此时普通「登录」只会拿到 alreadyLoggedIn。不做条件显示是为了避免"判定错误 → 无法恢复"的耦合;判定不可靠时 title 会提示"当前建议执行"。
登录态判定(插件如何判断"是否已登录")
代理写入的 ~/.codebuddy-session.json 没有 expiresAt 字段,所以插件按以下优先级推导过期时间,而不是把"字段缺失"当作"永不过期":
| 优先级 | 来源 | 说明 |
| 1 | auth.expiresAt | 本插件自带 login_workbuddy.py 写入;秒/毫秒都会归一化 |
| 2 | refreshToken 的 JWT exp | 代理会自动 refresh accessToken,因此 refreshToken 的有效期才是会话真正的边界 |
| 3 | accessToken 的 JWT exp | 解码 JWT payload(不校验签名,只读声明) |
| 4 | auth.expiresIn + 会话文件 mtime | 兜底;只会低估有效期,不会高估 |
若以上都无法得出结果,接口会返回 expiryKnown: false 并给出 reloginRecommended: true(而不是假装有效);expiresAtSource 会说明用的是哪一来源,🔍 诊断面板里也会显示。
方式 B(传统):在终端手动跑
使用本包内置的登录脚本(纯标准库,依赖系统 python3):
python3 node_modules/dsh-llm-workbuddy/login_workbuddy.py --session-file ~/.codebuddy-session.json
浏览器打开打印的链接,用 WorkBuddy/CodeBuddy 账号登录完成后自动保存会话到 ~/.codebuddy-session.json
仓库根目录也有 ./login-workbuddy.sh 包装脚本(面向本地开发,走 .tools/uv);发布版插件直接用系统 python3 运行同款脚本即可。
两种方式写的是同一个会话文件,可混用:终端登录后 Web 胶囊会自动变绿, Web 登录后终端脚本也读得到同一份会话。
Web 小部件工作原理
后端路由(lib/index.js)
插件在 apply(ctx, config) 里用 ctx.get("webServer") 探测 HTTP 服务(不在 inject 里,headless profile 无 webServer 时返回 undefined、自动跳过),然后通过 webServer.register({ kind: 'exact', path, handler }) 注册两条精确路由,并用 ctx.effect 包裹以便热重载自动清理。HTTP 方法过滤在 handler 内自行判断(req.method),因为路由 API 本身不含方法字段:
| 方法 + 路径 | 行为 |
| GET /api/workbuddy/status | 读取会话文件(默认 ~/.codebuddy-session.json,或配置的 sessionFile),多源推导会话过期时间(expiresAt → refreshToken/accessToken 的 JWT exp → expiresIn+mtime)判断会话是否有效,并 fetch 代理 /health 判断 proxyUp;返回 { sessionFile, authenticated, expiresAt, expiresAtSource, expiryKnown, expired, tokenPresent, reloginRecommended, account, proxyUp, tokenValid, loginScriptAvailable, checkin: { supported, autoEnabled, handledToday, lastResult } };非 GET 返回 405 |
| POST /api/workbuddy/login | 已有有效会话且未指定 ?force=1 时直接返回 alreadyLoggedIn;否则用系统 python3 spawn 包内 login_workbuddy.py --session-file ,等它打印出设备流链接后返回 { authUrl, pending:true }(最长等 15 秒,超时/脚本早退返回 { error });设备流在后台继续,前端轮询 status 感知完成。?force=1 强制重跑登录(见「🔑 重新登录」);非 POST 返回 405 |
| POST /api/workbuddy/diagnose | 一键诊断:真实探测健康状态,返回 { ok, session, health, chat, loginScriptAvailable, restartCommand, terminalCommand }。与 /status 不同,它除了探 /health,还会真实发一次最小模型请求(chat.chatWorking),能戳穿"胶囊显示成功但模型全 500"的假象;session 里带 expiresAtSource / expiryKnown / reloginRecommended;ok:false 时附带两份重启命令——restartCommand(多行、带注释,给人看/复制)与 terminalCommand(单行、无注释、无续行,供面板的「▶ 在终端执行」直接敲进内置终端);两者由同一份定义生成,自动区分本地 monorepo 布局与标准安装;非 POST 返回 405 |
| GET /api/workbuddy/usage | 用量统计:读取本地 token 用量台账($DSH_HOME/llm-workbuddy/usage.jsonl),返回 { today, byModel, week, total }:today = 今日、week = 累计(本周)(本地时间周一 00:00 起算,含今日)、byModel = 本周按模型明细(与 week 同一窗口,逐行相加等于 week)、total = 全量累计(保留给兼容与台账自检用,面板不再显示);每项含 input/output tokens、请求次数,以及积分消耗 credit;非 GET 返回 405 |
| GET /api/workbuddy/checkin | 签到状态:返回 { supported, handledToday, lastResult, official };supported 为三态——true(代理有签到接口)/ false(探测到 404/405,代理未实现)/ null(尚未探测出结论)。探测结果缓存 30 分钟;非 GET/POST 返回 405 |
| POST /api/workbuddy/checkin | 立即签到:透传代理 /v1/checkin(幂等,官方对已签到返回业务拒绝)。代理未实现签到接口时返回 { ok:false, supported:false, message } 且不写入任何失败记录 |
| POST /api/workbuddy/refresh-models | 清空模型发现缓存并重读代理 /v1/models,同时发布 llm/adapters-updated 让模型选择器立即重载;返回 { ok, announced, count, models } |
会话文件与登录脚本路径的解析顺序:
1. 配置里显式指定的 sessionFile / loginScript;
2. 包内 login_workbuddy.py + ~/.codebuddy-session.json;
3. 旧仓库布局(向上两级 dsh-workbuddy/ 的 .workbuddy/session.json)自动兼容。
前端胶囊(lib/client.js)
- 作为经典 被 DSH 注入页面,IIFE 内直接操作 DOM,零依赖。
- 启动时在 document.body 末尾挂一个 position:fixed 的胶囊,默认停在右下角(CSS 的 right/bottom)。
- 可拖动:按住胶囊主体(按钮除外,按钮是点击目标)拖到任意位置,浮层会跟着胶囊走并自动夹在视口内;缩窗口也会被拉回来。移动不足 4px 仍按点击处理,不会把手抖变成拖动。位置刻意不持久化(不写 localStorage)——刷新页面即回到右下角,这是需求而不是遗漏。
- 每 5 秒 GET /api/workbuddy/status;点「登录」后加快到每 2 秒轮询、最多 30 次,直到 authenticated:true。
- 胶囊外面只显示一个 ⚙️ 设置 按钮(带 title「WorkBuddy 设置」)。点击展开菜单,内含 🔍 诊断 / 📊 用量 / 🎁 签到(按条件)/ 🔄 刷新模型 / 🔑 重新登录;点击页面空白或选中某项后菜单自动收起。
- 🎁 签到:仅当代理真的实现了签到接口时才出现(checkin.supported === true)。
workbuddy2api 至今没有 /v1/checkin-status / /v1/checkin,此时入口不显示,也不会每天自动尝试——避免“点了必然 404”和长期挂着的失败记录。
- 🔑 重新登录:始终显示,点击后带 ?force=1 强制重跑设备流,忽略本地会话判定(详见「登录态判定」)。
- 🔍 诊断:点它 POST /api/workbuddy/diagnose,弹出一个面板显示真实健康状态(登录、会话文件、代理进程、登录令牌、模型能否出字),发现问题时给出两份重启命令:
- 复制重启命令:把多行(含注释)的 restartCommand 放进剪贴板;
- ▶ 在终端执行(DSH >= 0.1.7 的内置终端):调 ctx.get("sidebarRight") /
ctx.get("webTerminals") 开一个右侧栏终端标签页,等它连上并拿到输入控制权
后,把单行的 terminalCommand 敲进去并回车。终端命令会先把 8787 上的旧代理停掉再重启;标准安装布局下不会顺手跑 uv tool install -U(升级是有意留给人手动做的一步)。界面里没有终端插件时按钮不退化成死路:提示原因并把命令复制到剪贴板。
- 📊 用量:点它 GET /api/workbuddy/usage,弹出一个面板显示今日 / 累计(本周) token 用量(累计(本周) = 本地时间周一 00:00 起算)、积分消耗(上游每次返回的 credit 累加)与
按模型明细(本周)(数据来自本地台账 $DSH_HOME/llm-workbuddy/usage.jsonl)。
注:代理不暴露余额/剩余积分接口,只能统计已消耗积分,无法显示账户剩余。
- 口径:面板只保留「今日」和「累计(本周)」两档(文案统一写成 累计(本周)); byModel 与 week 同一窗口,
所以按模型逐行相加正好等于累计(本周)。跨周后本周数字自然从 0 重新开始,
历史记录仍留在台账里(接口的 total 字段仍是全量累计)。
- 台账会轮转,但累计(本周)不会归零:live 文件超过约 1.5 MB(约 1.2 万次请求)时,它被原子改名成 usage.jsonl.1,下一次请求重新创建 live 文件;用量接口把归档 + live 一起读,所以本周数字是连续的(一周内跨轮转不会少算)。台账总占用因此稳定在约 3 MB。
- 多个 harness 共用一个台账:Web 版和桌面版都读同一个 $DSH_HOME,所以用量面板显示的是两边合计;每台机器只有一个代理、一个账号,这也是唯一有意义的统计口径。写入是 O_APPEND 单行原子追加,轮转走原子改名 + 跨进程锁,两个 harness 同时跑任务不会丢记录。
- 诊断 / 用量浮层右上角都有 ✕ 关闭按钮,也可点击浮层外区域或按 Esc 关闭;浮层默认贴在胶囊上方(上方放不下就放到下方)。
- 挂载/卸载都登记在 ctx.effect 上:客户端热重载会卸掉旧胶囊(含轮询定时器、全局监听、打开的浮层),不会叠出第二个。
- 状态映射(三态,避免把“探测失败”误报成“掉登录”):
- authenticated && proxyUp → 🟢 绿,显示 WorkBuddy ·
- authenticated && !proxyUp → 🟡 黄,显示「代理未响应」(登录态仍有效,
不提示点登录,避免白占一次上游)
- !authenticated → 🔴 红,显示「登录」按钮
关于 UI 挂载位置(临时做法说明)
当前状态胶囊用 position:fixed 直接注入 document.body。DSH 官方的 UI 组合机制是 slot 系统(@deepseek-ai/dsh-client-ui-slots,ctx.slots.register 注册 React 组件进声明的 slot)。按官方「组合优先、不要假设/覆盖其他插件内部实现」的原则,理想做法是注册进官方 slot,而非直接改产品外壳。
评估结论:当前 shell 声明的 slot 里没有专门的「右下角状态位」;最接近的 sidebar.footer.action、conversation.session.header.actions、 conversation.input.overlay 都是 React 组件位,迁移意味着要把本插件从「零依赖原生 JS」改造成 React + 构建流程,并依赖 shell 暴露 ctx.slots 服务。因此现阶段保留 DOM 注入(机制允许),待官方 shell 提供合适的状态胶囊 slot 后再迁移。以下是已知的迁移路径(供后续参考):
ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
name: "sidebar.footer.action",
id: "workbuddy-status",
locale: NS,
inject: () => ({ / 轮询句柄 / 登录回调 / })
}, WorkBuddyStatusPill / React 组件 /));
为什么不需要构建
DSH 的 dsh.client 机制只要求 package.json 里:
{
"dsh": { "client": { "platform": "web" } },
"exports": { "./client": "./lib/client.js" }
}
dsh web 会自动把 exports["./client"] 指向的文件 serve 到
/plugins//client.js 并注入引导清单,不要求打包器。
配置
插件入口配置(profile 的 cordis.patch.yml 或用户设置文档的 llm-workbuddy: 分节)。注意:状态小组件使用的代理地址取自这里的 baseURL(去掉 /v1 后探 /health)。
- id: llm-workbuddy
name: 'dsh-llm-workbuddy'
config:
baseURL: http://127.0.0.1:8787/v1 # workbuddy2api 端点(小组件据此探 /health) apiKey: '' # 代理一般不需要;如代理以 --api-key 启动则填写 maxTokens: 32000 # 单请求输出上限 defaultContextWindow: 200000 # 未在目录中标明容量的模型使用 discovery: true # 实时拉取代理的 /v1/models(30s 缓存)
models: [...] # 静态目录(代理不可达时的兜底)
每个条目可带 reasoningEffort: 'low'|'medium'|'high'(默认推理等级)以及 credits: 'x0.06 credits'(显示为模型名后的 ×0.06) loginScript: '' # 登录脚本绝对/相对路径;默认用包内 login_workbuddy.py sessionFile: ~/.codebuddy-session.json # 会话文件路径;默认同上
模型列表默认取插件内置目录;代理可达时改为实时拉取 /v1/models(支持
{"models": [...]} / {"data": [...]} 两种返回),未列出的模型 id 仍可原样
传递。内置目录不再是白名单:平台新上架的模型刷新后即出现在选择器里,无需等插件发版;只有已下架/不可用的模型 id(RETIRED_MODEL_IDS,上游返回 service info not found)会被隐藏。每个模型的推理等级(reasoningEffort)默认来自内置目录,代理可达时优先沿用目录值(代理 /v1/models 当前只上报 High,不区分模型)。
积分倍率:模型名后面会拼上平台声明的积分倍率,例如 Deepseek-V4-Flash ×0.06。倍率来自代理 /v1/models 的 credits 字段("x0.06 credits",平台写在 WorkBuddy 应用 product.json / models_config.json 里),实时值优先、内置目录兜底;平台没声明的模型(如个别新模型尚未写入 product.json)只显示模型名,不会猜一个数字。
刷新模型:⚙️ 设置 → 🔄 刷新模型 会清掉插件的 30s 发现缓存并重新拉取代理列表。注意代理自身的模型清单来自代理包内资源 .workbuddy-src/src/codebuddy_proxy/models_config.domestic.json——不在里面的模型刷新也不会出现,需先把条目补进这个文件。
补一个新模型(平台先上线、代理快照还没跟上时,如 glm-5.3-flash):
1. 把平台条目补进代理资源 src/codebuddy_proxy/models_config.domestic.json (字段照抄同族模型:id / name / credits / maxInputTokens / maxOutputTokens / reasoning / supportsToolCall / supportsImages / vendor);根目录的 models_config.json 是它的开发兼容副本,必须字节一致
(test_backend_profiles.py::test_root_model_config_matches_packaged_domestic_resource
守着这一点)。代理每次请求都重新读这个文件,改完直接生效,不用重启代理。
2. 插件内置目录 lib/index.js 的 DEFAULT_MODELS 也补一条同样的模型(代理不可达时兜底),并把 credits 一起写上——代理当前的 /v1/models 不透出 credits 字段,倍率显示靠这份目录。
3. 平台条目可以从 ~/.workbuddy/cache/acc-product-config-v3.json(WorkBuddy 应用的远程产品配置缓存,含平台声明的最新模型、倍率与窗口)里抄,别猜数字。
排错
| 现象 | 可能原因 / 解决 |
| 安装报“不兼容”,且报的版本号比最新发布版小(如刚发 0.1.22 却报 dsh-llm-workbuddy@0.1.20 不兼容) | DSH 内置的 pnpm 11 默认 minimumReleaseAge: 1440(1 天),发布时间不足 24 小时的版本不会被解析,于是被降级到冷却期外的最新版(那是真的不兼容)→ 装的时候写精确版本:dsh plugin --profile desktop add dsh-llm-workbuddy@0.1.22,或等满 24 小时,或在该 profile 的 pnpm-workspace.yaml 里设 minimumReleaseAge: 0 |
| 右下角没有胶囊(也没有黄色/红色胶囊) | 先刷新页面;宿主每 500ms 轮询 bundle,改动会经 /plugins/events 热重载。若刷新后仍没有,看浏览器控制台是否有 client-modules 报错,并确认插件在 profile 的 bundles 里 |
| 改了插件代码(lib/index.js / lib/client.js),界面/接口却还是旧的 | 先确认这个界面加载的是哪份插件:每个 harness 只从自己 profile 的 node_modules/dsh-llm-workbuddy 读,且进程启动时整体读入(宿主半 + 客户端 bundle)。web profile 是 link: 到本仓库的 → 改完源码重启 dsh web 生效;桌面 App(cwd = ~/.dsh/profiles/desktop)装的是 npm 上的版本,改本仓库不影响它,必须发版后 dsh plugin --profile desktop add dsh-llm-workbuddy@(新版 24 小时内还要把它加进该 profile 的 minimumReleaseAgeExclude,见上一行)并重启 App。查现场:lsof -nP -iTCP: -sTCP:LISTEN 看进程与其 cwd;grep '"version"' ~/.dsh/profiles//node_modules/dsh-llm-workbuddy/package.json 看装的是哪版;curl -s http://127.0.0.1:/api/workbuddy/usage 看接口字段是否符合预期 |
| 点「▶ 在终端执行」提示“当前界面没有内置终端” | 这个界面没装/没启用官方终端插件(@deepseek-ai/dsh-client-ui-sidebar-terminal + dsh-api-terminal-controller),或当前没选中任何会话。命令已自动复制到剪贴板,可手动粘贴执行 |
| 胶囊一直 …(加载中) | GET /api/workbuddy/status 失败 → 确认 dsh web 在跑、端口正确 |
| 胶囊红 + 代理未运行 | workbuddy2api 代理没起或挂了 → 按「安装代理」章节启动(新版胶囊对“代理未响应”显示黄色,不再报成“未登录”) |
| 另一个 workspace 在跑任务时胶囊显示「未登录」,结束任务后过一会儿又恢复 | 这是误报,不是掉登录。整台机器只有一个代理进程(127.0.0.1:8787)和一份会话(.workbuddy/session.json),所有 workspace 共用:一边在长任务里占用模型时,/health 探测可能短暂失败,旧版胶囊会直接把“探测失败”画成“未登录”。新版:探测 8 秒 + 重试 + 连续两次失败才算掉线,并且显示为黄色「代理未响应」;GET /api/workbuddy/status 会带 lastProbeError / consecutiveProbeFailures 说明真实原因。要并行跑两个 workspace 的 WorkBuddy 任务,需要第二份会话 + 第二个代理端口 + 第二个 profile(baseURL/sessionFile 是 profile 级配置,同一个 profile 里改不隔离) |
| 胶囊显示登录成功但模型用不了 | 典型的“代理进程活着但指向旧路径/文件缺失”假象(/health 仍显示 ok)。点胶囊 🔍 诊断,看 模型出字 是否失败;按面板给出的重启命令重启代理 |
| 点「登录」没反应 / 按钮灰 | loginScriptAvailable:false → 包内 login_workbuddy.py 缺失或系统无 python3;检查安装。若返回了 error(脚本 15 秒内没打印授权链接、或退出码非 0),页面会弹出具体原因 |
| 点「登录」弹出 alreadyLoggedIn,但 token 实际已失效 | 本地判定是启发式(会话文件可能没有 expiresAt)→ 用 ⚙️ → 🔑 重新登录 强制重跑登录 |
| 胶囊绿但所有模型 401 | accessToken/refreshToken 都已过期但判定未察觉 → ⚙️ → 🔑 重新登录;或先 🔍 诊断 看「令牌过期」一行 |
| 设置菜单里没有「🎁 签到」 | 正常现象:该代理未实现 /v1/checkin-status / /v1/checkin(workbuddy2api 至今未提供),插件探测到 404 后自动隐藏入口并停止每日自动尝试 |
| 设置菜单里的「🔑 重新登录」 | 该入口始终可用;判定结果不可靠时 title 会提示“当前建议执行” |
| 新标签页打开后登录完成,胶囊仍是红 | 会话文件(默认 ~/.codebuddy-session.json)未刷新或已过期 → 刷新页面或点「🔑 重新登录」 |
| 代理版本报错 / 登录最后一步 401 | 代理过旧(= 2.0.4 |
| 启动 dsh web 报 EPERM ... cordis.yml | .dsh 所在系统卷受保护(/System/Volumes/Data 带 protect)。解决:sudo chown -R $(whoami) /Users/jiyunyang/.dsh,或 export DSH_HOME=$HOME/dsh-home 后重新 dsh plugin --profile web add 并把插件链接进新 home |
| 模型请求 TRANSPORT 错误 | 代理未运行或端口不对(连接被拒绝) |
| 任务跑着跑着就死了 / 之后怎么重试都起不来 | 上游 429 / 400 / 5xx 以前被代理包成 200 + SSE error 帧 且不补 [DONE],客户端只看到 STREAM_CLOSED(不在 harness 重试策略里)→ 任务当场终结。新版会翻成 QUOTA / RATE_LIMIT / INVALID_REQUEST / SERVER 并带上游原文(如“您的使用量已超出频率限制,将在 … 重置”)。若报 QUOTA:等重置或换模型 |
| 报错 WorkBuddy SSE stream ended without [DONE] | 旧版代理的同一个问题。现在只在一个字节内容都没拿到时出现(EMPTY_RESPONSE,可重试);已经出过内容才断的流会报 STREAM_TRUNCATED(不自动重试,见下一行) |
| 报错 STREAM_TRUNCATED / 回答写到一半突然停 | 上游在已经流出内容之后把连接切了(代理日志 stream_error / ReadError)。旧行为是整轮静默重试:用户看到的回答会消失、从头重写一遍(实测一次已流出 178 字的生成被整轮丢弃)。现在改成不可重试的截断错误,保留已显示内容并明确告知“被截断”,由你决定继续还是重发 |
| 回答卡在半句话上不动 / 一直等,最后只能中止 | 代理 、List、HTML、a = 2.0.4 |
| 模型长时间只推理、不调用工具,像是卡住 | 检查代理日志里有没有 tools_truncated:旧版把 DSH 的 60 个工具按顺序砍到 30 个(read/write/grep/web_search 等全被丢掉,system prompt 里却还写着)。实测上游接受 60 个,默认上限已提到 64;也可用 --max-tools N 调整 |
| 中止任务后 WorkBuddy 要过一会儿才恢复 | 中止后上游请求可能仍在生成,账号一直被占着 → 适配器现在监听中止信号、立刻 abort 上游请求;代理也会记录 client_disconnected |
| 模型请求立刻返回 401 auth_error(以前是长时间无响应后所有模型一起卡) | 代理不再在请求路径里同步跑交互式登录(那会冻住整个事件循环);token 刷新失败就快速 401 → ⚙️ → 🔑 重新登录 后重试 |
限制
- 图片输入:声明支持图片的模型(inputModalities: ["text", "image"],如 deepseek-v4-pro、 glm-5.2、kimi-k2.x、hy3 等)可附带图片,适配器会通过 DSH 的附件服务把图片编码为 data:;base64, 以 OpenAI image_url 格式透传给代理。若附件服务不可用(headless 等无附件场景),图片输入会以 UNSUPPORTED_CONTENT 稳定报错。
- 推理等级(reasoning effort):支持推理的模型(如 DeepSeek-V4、GLM、Kimi、MiniMax、 Hy3 等)会显示推理等级下拉(Low / Medium / High),默认值取平台默认强度。reasoning_effort 会透传给代理;若某模型平台侧只接受平台默认、忽略该参数,则退化为平台默认强度,不影响出字。
- 代理未运行时,模型请求会以 TRANSPORT 错误快速失败(连接被拒绝);但状态小组件本身不依赖代理——代理挂了它仍能显示「代理未运行」并允许触发登录。
- 登录态有效期由 WorkBuddy 云端决定。插件会尽力从会话文件推导过期时间(见「登录态判定」),但推导不出时只能标记为“未知”而不是失败;真正的失效检测以一次真实模型请求(🔍 诊断的「模型出字」)为准,恢复手段是 🔑 重新登录,代理无需重启。
- 签到功能依赖代理实现 /v1/checkin-status 与 /v1/checkin;截至 workbuddy2api 2.0.4(含 GitHub main、dsh、codex 各分支)均未提供,因此默认不显示签到入口。代理侧补齐后无需升级插件,入口会自动出现。
多个 harness 同时用(Web 版 + 桌面版)
Web 版和桌面版是两个独立的 DSH 进程,各自有自己的 profile、端口、路由、 provider 注册和内存缓存,插件版本也可以不同(例如一边 link: 本地目录、一边装
npm 版)。所以两边同时开、同时跑任务不会互相干扰。
共享的只有三样,都在 $DSH_HOME 下或就在本机:
| 共享物 | 说明 |
| workbuddy2api 代理 | 一台机器只有一个进程、一份上游会话;两边都走它 |
| llm-workbuddy/usage.jsonl(+.1) | 用量台账,两边合并统计;写入是单行原子追加,轮转有跨进程锁(见「用量」) |
| llm-workbuddy/checkin.json | 每日签到去重标记,两边共用一个“今天已签”结论 |
并发本身没问题:代理是 FastAPI + httpx.AsyncClient 异步流式转发,没有并发上限,本来就是为多条流同时跑设计的。需要注意的只有这几点:
- 同一个账号、同一份额度:两个任务同时跑会一起消耗 credit / 并发额度,可能更早撞到上游限流。这是账号容量问题,不是插件或代理的 bug。
- 重启代理 / 重新登录会打断另一边:这是唯一的硬耦合。从任一侧点「重启代理」或「重新登录」,另一侧正在进行中的流会断。日常不点就没事。
- 超长任务跨过 token 过期时刻:代理在每次请求前会检查并刷新 access token(剩余不足 60 秒即刷新),但流已经开始之后若 token 失效,代理不会自动刷新重试,那一轮会报错。access token 有效期以周计,实际很少碰到;真碰到就重跑该轮。
- 想完全隔离(连用量/签到也不共享),只能给两个实例设不同的 DSH_HOME,代价是 profile、设置、会话记录、用量面板全部拆开,一般不值得。
文件索引
| 路径 | 作用 |
| lib/index.js | Cordis 插件主体:LLM 适配器 WorkBuddyAdapter + /api/workbuddy/ 路由(status / login / diagnose) |
| lib/client.js | 零依赖浏览器小部件(可拖动状态胶囊 + 登录流程 + 🔍 诊断(含在终端执行)/ 📊 用量),被 dsh.client 注入 |
| login_workbuddy.py | 设备流登录脚本(随包发布,被后端路由用系统 python3 spawn) |
| cordis.patch.yml | 本包的 Cordis bundle 挂载声明(id: llm-workbuddy) |
| package.json | 包元数据、dsh.client 浏览器入口声明、llm-workbuddy peer 依赖 |
第三方 workbuddy2api 代理不在包内,需单独安装(见「安装代理」章节)。
仓库根目录的 start-workbuddy.sh / login-workbuddy.sh / .workbuddy/ 是本地开发用的配套文件,不随 npm 包发布。
更新日志 / Changelog
每次发版的改动记录见 CHANGELOG.md。
发版流程(确保 GitHub 有更新说明)
1. 改完代码后,在 package.json 里 version 自增(语义化版本)。
2. 在 CHANGELOG.md 顶部补一段本次版本(## [x.y.z] - 日期)的 Added / Fixed / Changed。
3. 提交并打 tag:git commit -am "release: x.y.z" 然后 git tag vx.y.z。
4. git push origin main --tags,到 GitHub 用该 tag 创建 Release—— Release 的描述直接引用 CHANGELOG 对应段落,仓库页面就有了「改了啥」的说明。
注意:本机 dsh web 通过符号链接直接加载本地目录,因此本地改动能立刻重启生效, GitHub 上的版本只影响通过 dsh plugin add dsh-llm-workbuddy 安装的其他用户。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
zdk119746/dsh-llm-workbuddy
可以在 DSH 中使用 WorkBuddy 里面的模型
相关插件 · 其他
模型破甲清洗YuJunZhiXue/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,148已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,266已汉化DSH
70.7