DSH WorkBuddy Connect
corrinehu/dsh-workbuddy-connect将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness,在 DSH 对话窗口里零配置使用。
新增 deepseek-web provider,把 chat.deepseek.com 网页端模型接入 DSH:浏览器登录抓取、PoW 请求签名、SSE 流式传输与基于提示词的工具调用。
中文 · English
把 chat.deepseek.com 网页版接进 DSH:用浏览器登录态(不是 API Key)驱动 agent 的工具调用、思考流与图片理解。
DSH(DeepSeek Harness)通过 ctx.llm 的 provider 适配器接入模型。本项目实现了 deepseek-web 这个 provider —— 它不调用官方 API,而是复用你已登录的网页版:PoW 挑战、会话、SSE 流式、 文件上传,全部走网页端私有接口。
于是:在模型选择器里选 `DeepSeek 网页 · 快速模式`,就能用网页版免费额度跑 DSH 的 agent。
DSH agent loop ──▶ ctx.llm ──▶ [deepseek-web 适配器] ──▶ chat.deepseek.com
│ ├─ PoW(SHA3 WASM,**在浏览器页面里**求解)
│ ├─ chat_session(**按 DSH 会话复用,跨重启续上**)
│ ├─ chat/completion(SSE patch 流,链式只发增量)
│ └─ file/upload_file(图片输入)
└─ 提示词工具协议 ⇄ tool-call 块⚠️ 0.7.0 起:必须能启动 Edge / Chrome。
PoW 挑战改为在真实页面上下文里求解(原因见下方「为什么这样更不容易被限流」)。
找不到浏览器时会明确报错,不会退回 Node 侧求解 —— 这是刻意的:
Node 侧解 PoW 是被公开列为的封号触发条件,退回去等于这个改动没做。
已经用 DSH_NO_BROWSER_TRANSPORT=1 显式关掉浏览器传输的环境需要撤销该设置。被问得最多的两个问题:你们是操作 DOM,还是截获页面的请求?是不是个反代? 答案都是不是 —— 它自己构造请求、直接发给网页端私有接口。准确的说法是 「网页端私有接口的非官方客户端」。逐步拆开:
阶段 · 做什么 · 用什么 ① 登录捕获(只做一次) · 开一个独立 profile 的浏览器窗口让你登录,把页面自己发出的请求头读一份存下来:Authorization: Bearer、域 cookie、反爬头 x-hif-dliq / x-hif-leim、一批 x-client-* · Electron 的 webRequest.onBeforeSendHeaders ② 请求构造(每次调用) · 自己拼 POST /api/v0/chat/completion;PoW 自己解:先要 create_pow_challenge,再用 SHA3 WASM 算出答案塞进 x-ds-pow-response · 插件自己的 HTTP 客户端 ③ 发送 · 默认交给系统 Edge / Chrome 的网络栈发出(CDP 驱动真实页面),TLS / HTTP2 指纹与真实浏览器一致;也可切回 Node · 见下方「传输层」 ④ 解析与对接 · 自己解 response/fragments 的 SSE 帧、分思考与正文通道;工具调用走提示词协议(网页端没有原生 function calling) · 自研解析器
唯一沾到"截获"的只有第 ① 步,而且那一步是「读一份 + 清掉自己的痕迹」:同一个回调顺手把请求头里的 Electron 品牌(UA 与 UA-CH)删掉,否则网页端会判「使用环境异常」。它不改写业务请求、也不转发任何东西, 而且只在登录那一次生效 —— 登录完之后页面关掉,插件照样跑。
反代(反向代理)的关键是中间人:客户端以为自己在跟原服务器说话,实际请求被转发了一层。 这里没有中间人 —— 插件自己就是那个客户端,以网页端的身份直连 DeepSeek。 中间没有转发层,也不需要额外跑一个本地服务。
· DOM 自动化(如 cuckoo-code) · 请求 hook(浏览器扩展,如 deepseek-pp) · 本插件 请求由谁发出 · 页面 · 页面 · 插件自己 登录态来源 · 人在窗口里手动登 · 你日常浏览器里的登录态 · 开窗捕获一次、存在本机 网页改版会怎样 · 选择器一改就坏 · 只依赖接口路径 · 只依赖接口,完全不碰 DOM 浏览器要一直开着吗 · 是 · 是 · 否
前两条路线的共同点是「请求是浏览器发的」,只有本插件是发送方。代价是接口变了要跟着改; 换来的是不依赖 DOM、可以后台无人值守地跑。
网页端会拦自动化调用,而且公开的同类项目文档里已经列出了触发条件。0.7.0 按其中最可识别的那几条 做了调整:
原本的做法 · 问题 · 现在 在 Node 里 WebAssembly.instantiate 求PoW 挑战 · 被明确列为「自动解挑战」的封号触发条件 · 在真实页面里用官方自己的 wasm 求 每次调用临时建会话、用完即删 · 真人不会这样建删对话(实测曾一天建 182 个会话) · 按 DSH 会话复用,跨重启续上(resume-state.json) 每轮全量重发 · 请求体量与节奏都不像真人 · 链式投喂:只发增量,parent_message_id 挂在上一条回答下面 固定请求间隔 · 真人打字不是等距的 · 见设置页的请求间隔(可配随机区间)
代价(也是 0.7.0 的破坏性变更):必须有可用的 Edge / Chrome。 找不到浏览器时会明确报错—— 不会静默退回 Node 侧解PoW,因为那样等于这个改动没做, 只是给了「已经改好了」的错觉。
⚠️ 需要说清的边界:这些调整降低被识别为自动化的概率,不构成"不会被封"的保证。 逆向网页端本身违反服务条款,风险是"判罚多严"而不是"会不会被抓到"。 稳定性优先请用官方 API,或用已有的付费订阅走 OAuth。
设置页按用途分成 7 个标签(一次只显示一页)—— 账号(登录状态 / 当前账号 / 账号库 / 手动 Token)· 模型(可用模型 / 连通性测试)· 防风控(请求节流 / 会话清理及其三个区间 / 调用台账)· 传输层(指纹 + 一键测试)· 浏览器(内置浏览器:状态 / 启动 / 关闭 / 打开页签时自动启动)· 上下文(每轮全量 / 链式投喂)· 关于(版本与更新 / 数据位置 / 风险说明)。 操作反馈条常驻在标签栏之上,切到哪一页都看得见。
主区页签栏里多了一个 「网页版」(与 对话 / 轨迹 / LDW 并排)—— 点开就是 DSH 自带 Chromium 里的 chat.deepseek.com 本体,由插件保活并自动装回登录态(见「快速开始 → 4.」)。
设置页(真实截图,拍于拆页之前):当前账号 / 登录状态(适配器注册、凭证来源、PoW WASM、服务端校验)/ 三种登录方式(Microsoft Edge · 我的默认浏览器 · 从已登录窗口恢复)/ 手动粘贴 token。
DSH「使用统计」里看到的调用量 —— 免费网页通道,当日 1042.8 万 tokens / 164 次调用:
设置页示意图(标注各区块用途):登录状态 / 当前账号(退出当前账号 · 退出并登录其它账号) / 浏览器窗口登录 / 从已登录窗口恢复 / 手动 token / 连通性测试 / 模型列表。
能力 · 说明 🔐 网页登录(无 API Key) · Electron 独立分区窗口里正常登录,插件旁路捕获真实 Authorization、cookie、x-hif-* 指纹头与客户端版本头 🧩 PoW 求解 · create_pow_challenge + DeepSeek 自家 sha3_wasm_bg.*.wasm 的 wasm_solve,在浏览器页面上下文里执行(0.7.0 起,见下方「为什么这样更不容易被限流」);WASM 地址自动发现(哈希随部署变化),失败自动回退 🌊 流式 · 同时兼容 response/fragments(THINK/RESPONSE 片段)与直连 thinking_content/content 两套 SSE 格式,含 {o:"APPEND"} 与裸 {v} 续段;按逻辑流去重,快照重放不重复吐字 🛠 工具调用 · 网页端没有原生 function calling → 提示词 JSON 协议 + 流式过滤器(跨包标记、围栏、多调用、假阳性回退)→ 合成 tool-call 块并给出 finish: tool-calls;工具定义按 5.6 万字符预算整段下发,超预算时列出被省略的工具名并要求模型别猜参数 🛡 格式漂移双保险 · ① 指令层显式禁止 XML/DSML 标记并说明后果(实测模型会主动拒绝该格式);② 解析层同时容忍 JSON 与 XML/DSML 两族(\ · DSML\ · 前缀、dsml- 连字符、裸 `、CDATA) 🩹 **非法 JSON 宽容修复** · 模型常把 Windows 路径写成单反斜杠:\A 是非法转义,而 \r **合法**却会把 \resources 静默变成回车。多候选修复链逐字还原路径,解析不出才降级为正文(**绝不静默丢内容**) 🖼 **图片输入** · 走网页端文件上传通道(/api/v0/file/upload_file → ref_file_ids),同一张图在多处出现时自动去重(服务端拒绝重复 id)。实测:上传自造的「左红右蓝」PNG,模型答出「左=红色,右=蓝色」 🧹 **会话卫生** · 每次调用新建临时会话并在结束后删除 —— 实测调用前后网页端会话列表**完全一致**,不污染你的聊天记录 🎛 **设置面板** · 状态展示、**退出当前账号 / 退出并登录其它账号**(连带清除浏览器分区登录态)、浏览器登录、从已登录窗口恢复、手动粘贴 token、连通性测试(host HTTP API:/deepseek-web-login/api/*) 🖥 **内置浏览器(「网页版」页签)** · 主区页签里挂 DSH 自带 Chromium 加载的 chat.deepseek.com 本体;**登一次即可**——登录态(localStorage + cookie)落盘、重启自动装回;在里面登录会**自动同步进账号库并切号**;崩溃自动重挂(≤3 次);**不影响 DSH 启动**(等 UI 空闲再挂) 💓 **传输层保活心跳** · 盯"那个页面还活着吗、还登着吗",坏了就修(只做本地探测,**不给站点发定时 ping**);传输层浏览器 **10 分钟没人用自动退场**(transport.json` 可调)
登录与凭证捕获流程(点击展开)
# 方式 A:从 Release 的 tgz 装配(推荐,免构建;版本号以最新 Release 为准)
dsh plugin --profile desktop add ./dsh-deepseek-web-login-0.1.3.tgz
# 方式 B:git 装配(本机需可访问 github.com)
dsh plugin --profile desktop add github:cv-superding/dsh-deepseek-web-login
# 方式 C:从 npm 装(免 git、免构建,国内镜像也会同步)
# 先确认已发布:npm view dsh-deepseek-web-login version ← 查不到就先用方式 A/B
dsh plugin --profile desktop add dsh-deepseek-web-login⚠️ 在插件市场里点「更新」失败时(报 `update failed and restoration of the previous build could
not be verified`,括号里写着"当前宿主无法安装更新前的精确 GitHub 提交")—— 那句括号只是
"失败后无法自动回滚" 的说明,不是失败原因。本插件长期只提供 git 安装来源,所以更新要
clone GitHub、失败后市场也救不回来。绕过办法(挑一条,都不用等市场修好):
# 1) 按 tag 精确装(比装 HEAD 稳,不会被中间提交绊住)
dsh plugin --profile desktop add github:cv-superding/dsh-deepseek-web-login#v0.2.0
# 2) 用 Release 的 tgz(完全不走 git;先从 Releases 页下载对应 tgz)
dsh plugin --profile desktop add ./dsh-deepseek-web-login-0.2.0.tgz
# 3) 从 npm 装(免 git、免构建;先 `npm view dsh-deepseek-web-login version` 确认已发布)
dsh plugin --profile desktop add dsh-deepseek-web-login市场目录里的这个条目当前标记为 npm: null(未发布到 npm)⇒ 只能走 git。包侧已就绪(private已去掉、repository已补 —— 后者是目录识别 npm 包的硬条件),
发布之后目录每天重探一次(未发布的判定 1 天后过期),探到即自动切到 npm 路径
(版本比较 + tarball,不再依赖本机 git)。仍显示 git 时等一天再看,或直接用上面第 3 条。
--profile desktop是 DSH Desktop(Electron 应用)使用的 profile;若你跑的是 web profile,换成--profile web。
重启 DSH 后生效(本插件是 bundle 装配,重启即自动加载)。
设置 → DeepSeek 网页登录 → 浏览器窗口登录,在弹出的窗口里正常登录(手机号 / 邮箱 / 验证码均可)。 登录窗口报的是干净 Chrome UA(不含 Electron 字样,UA-CH 品牌也清过)—— 否则网页端会判定 「使用环境异常」直接拒绝服务;若仍被拦,用同一行的 用我的默认浏览器登录,按提示用 F12 取 token 粘贴。 捕获成功后窗口自动关闭,面板显示已登录。
💡 这个按钮每次都会先清掉上次的登录状态 —— 登录用的是独立 profile
(~/.dsh/web-login/browser-profile,不碰你日常 Edge 的 cookie 与历史),所以窗口一打开就是干净的登录页,不会带着上一个账号。
想省一次输入(凭证明明还有效、只是要重新捕获)就用账号行上的「重登」——
那条路默认不清,浏览器里若还留着登录态会立刻复用、一个密码都不用敲。
⚠️ 但如果这条账号已经被标记失效(红标「需要重新登录」),它就会先清掉再让你重新登录 ——
因为此时浏览器里那份登录态也已经不可用,复用只会把同一个坏凭证再抓一遍(会陷入点多少遍都失败的死循环)。
~/.dsh/web-login/deepseek-auth.json,不在仓库里;面板「当前账号 → 退出当前账号」一键清除(同时清掉浏览器分区里的登录态,保证真退出、可换号)模型选择器 → provider `DeepSeek 网页版(免费)` → DeepSeek 网页 · 快速模式, 然后照常用 agent(工具调用、思考流、贴图都可用)。
⚠️ 一个账号同时只开一个聊天窗口:多开并发会触发网页端临时封禁(1 天)——要开多个窗口就换账号,或把多余的窗口换到别的 provider。详见已知限制。
主区页签栏里(与 对话 / 轨迹 / LDW 并排)有一个 「网页版」 页签:里面是 DSH 自带的 Chromium 加载的 chat.deepseek.com 本体——真页面、真 JS、真指纹。它的作用不是"回显聊天"(发送仍走原有通路, 网页端的回答不会显示在这里),而是保持一个真人网页端会话活着,并把它的登录态交给插件使用。
怎么用(一次就够):
首次会看到转圈 + 「正在恢复内置浏览器…」,几秒后页面就上来了;
localStorage + cookie)存到本机(~/.dsh/web-login/guest-storage.json);token 与身份同步进账号库:新号会自动入库并切为当前账号(「账号」页能看到捕获时间 / 指纹头 / token 长度);
页面直接回到登录态;
「打开『网页版』页签时自动启动」开关)。
它崩了会怎样? 自动重挂(20 秒后,最多 3 次;你手动点过「关闭」就不再自动拉起)。 崩溃原因(crashed / destroyed / render-process-gone)会写进诊断文件,不再只有一句"探测不到"。
页面关着会丢东西吗? 不会丢存量:
东西 · 存在哪 · 页面关着时 页面指纹(UA 洗白 / webdriver=false / UA-CH 品牌) · 代码级补丁,每次挂载重新打 · 重开自动带上 登录态(localStorage + cookie 快照) · ~/.dsh/web-login/guest-storage.json · 重开自动装回 账号 / API token · 账号库(与页面无关) · 不受影响,照常发请求 页面自身的"活着"状态 · —— · 只有这一项抓不到(这正是"保活"的意义)
它为什么这么设计(都是实测踩出来的,写在这里省得你踩):
dsh-sidebar-browser-,没有 persist:)⇒登录态只能由插件落盘再装回;
useragent 只在挂载/导航前生效 —— 晚一步,页面就带着 Electron/ 出去,