用手机浏览器接入桌面会话,随时查看与回复
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/9 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add paayton/dsh-link该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 8 处,展示前 8 条)
- 发起网络请求src/client/client.js:101
const res = await fetch(url, { credentials: "same-origin", cache: "no-store", ...opts }); - 写入剪贴板src/client/client.js:114
await navigator.clipboard.writeText(text); - 读取本地文件src/host/routes.ts:545
const info = await stat(abs); - 读取本地文件src/host/routes.ts:547
const body = await readFile(abs); - 写入剪贴板src/public/app.js:165
navigator.clipboard.writeText(text), - 发起网络请求src/public/app.js:228
const res = await fetch(url, { - 发起网络请求src/public/app.js:1059
const res = await fetch(`${API.attachment}?sessionId=${encodeURIComponent(sessionId)}&attachmentId=${encodeURIComponent(attachmentId)}`, - 发起网络请求src/public/app.js:2455
const res = await fetch(file, { cache: "no-cache" });
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-api-session-controller@deepseek-ai/dsh-credentials@deepseek-ai/dsh-session给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 手机浏览器接入桌面会话
- 查看与回复会话
- 支持图片上传
DeepSeek Harness 移动端 H5 桥接插件:手机浏览器经内网 / Tailscale 用连接密钥接入桌面版正在运行的会话(流式回复、Markdown、工具卡、图片上传)。
README
由 DeepSeek 最新模型翻译生成dsh-link
DeepSeek Harness 移动端 H5 桥接插件:在桌面版设置页新增「Link」栏,让手机浏览器打开一个极简 H5,与 Mac 桌面版正在运行的会话交互(工作区边栏 + 基础聊天 + 流式回复)。
状态:可用,H5 已按「桌面版体验」重做 ✅
- host 段、客户端设置栏、H5 SPA 全部完成,零第三方运行时依赖、零构建步骤。
- H5 客户端已升级为桌面级对话视图:Markdown 正文、思考块、工具调用卡片(可展开看参数/输出)、流式增量、更早历史分页、会话边栏(头像/状态、筛选/折叠/侧滑手势、设置面板)、发送即插话、深浅色主题、PWA 可加到主屏。
- 图片上传:手机相册/拍照 → 本地按长边 1568px 压缩 → /m/api/upload 换 fileUploads 收据 → 随 prompt 一起发;历史消息与工具结果里的图片通过 /m/api/attachment 拉回显示。
- 149 项本地测试全过(WebSocket 协议 10 + host 集成 33 + 客户端冒烟 6 + Markdown 19 + 事件归约 20 + H5 UI 61)。
展开完整文档(README 剩余 1 节)
dsh-link
DeepSeek Harness 移动端 H5 桥接插件:在桌面版设置页新增「Link」栏,让手机浏览器打开一个极简 H5,与 Mac 桌面版正在运行的会话交互(工作区边栏 + 基础聊天 + 流式回复)。
状态:可用,H5 已按「桌面版体验」重做 ✅
- host 段、客户端设置栏、H5 SPA 全部完成,零第三方运行时依赖、零构建步骤。
- H5 客户端已升级为桌面级对话视图:Markdown 正文、思考块、工具调用卡片(可展开看参数/输出)、流式增量、更早历史分页、会话边栏(头像/状态、筛选/折叠/侧滑手势、设置面板)、发送即插话、深浅色主题、PWA 可加到主屏。
- 图片上传:手机相册/拍照 → 本地按长边 1568px 压缩 → /m/api/upload 换 fileUploads 收据 → 随 prompt 一起发;历史消息与工具结果里的图片通过 /m/api/attachment 拉回显示。
- 149 项本地测试全过(WebSocket 协议 10 + host 集成 33 + 客户端冒烟 6 + Markdown 19 + 事件归约 20 + H5 UI 61)。
- 已装入 desktop profile,并在手机视口(390×844)对真实会话做过全链路自测:登录 → 会话列表 → 历史(含工具卡)→ 实时流式 → 分页 → 发送/停止/断线重连。
- host 段用 TypeScript 编写,对着 DSH 官方类型(@deepseek-ai/@0.2.0-rc.2)做 tsc 检查,编译产物在 dist/;H5 段保持零构建(运行时直读 + 内容指纹自升级)。
形态
双段 Cordis 插件(纯函数 apply/inject/name,对齐官方 @deepseek-ai/dsh-client-connection 写法):
- host 段(src/host/,进程内全权限):挂 HTTP 路由 + WebSocket,直连 sessionController / workspaceRegistry / credentials / connection。
- 客户端段(src/client/client.js,React):设置页「Link」栏,展示网络状态、连接密钥、手机地址与操作指引。手写 window.__ModuleLoader__.load 产物格式,require("react"),无需打包。
- H5(src/public/):静态单页,fetch + WebSocket,移动优先、深浅色自适应、安全区与软键盘适配。
app.js(界面/连接)只负责渲染,事件归约在 transcript.js(纯函数)、Markdown 在 md.js(纯函数),两者都能在 Node 里直接单测。
关键架构决定(与最初设计的偏差,均有源码依据)
1. 自建 LAN 监听,不复用桌面版主 webServer。
核实发现:桌面版 webServer 只绑 127.0.0.1:19387,且 DSH 官方主动禁止把主服务绑到 0.0.0.0(原因:会把 RCE 暴露到网络)。因此手机无法直接访问主服务上的路由。
本插件另起一个受「连接密钥」保护的独立监听(默认 127.0.0.1:19388,可配置为 0.0.0.0 供手机接入),只提供静态 H5 + 只读/聊天 API,不暴露密钥生成等控制面。
2. 受众隔离的三类路由:
| 前缀 | 受众 | 鉴权 | 暴露位置 |
| /m(静态 H5) | 手机浏览器 | 公开(无敏感数据) | 回环 + LAN |
| /m/api/(数据 + WS) | 手机 H5 | 连接密钥(LAN 侧强制) | 回环 + LAN |
| /m/link/(控制面) | 桌面设置页 | cookie(connection.admit) | 仅回环 |
3. 初始历史取自 follow 的 snapshot 帧(用真实 cursor、不激活 agent),而非 page(throughSeq:-1)(后者经核实会返回空页)。
更早的历史用 /m/api/messages?beforeSeq=<最老 seq> 分页(host 内部按 turn 对齐切页)。
4. 零依赖 WebSocket 服务端(src/host/ws-mini.ts):link: 安装下 ws 包不可解析,故自带极简 RFC 6455 实现(文本帧 / 分片 / ping-pong / close / 长度上限)。
5. 进程内调用 Remote 门面必须自己传 signal:sessionController / fileUploads 这些门面方法的签名都以 signal 结尾(prompt(request, signal)、upload(agent, request, signal)),方法体第一行就是
signal.throwIfAborted();走 RPC 时网关会按描述符自动补上,进程内直调不会,漏传就得到一个
莫名其妙的 Cannot read properties of undefined (reading 'throwIfAborted')。
需要传 signal 的:prompt / page / follow / list / search / projections / fileUploads.upload|resolve|bindPrompt;不需要的:create / cancel / rename / fork / attachment / updateQueue。
单测里 mock 也照真实签名断言(少传就 FAIL),避免再退化。
6. 图片走 DSH 自己的上传契约:ctx.fileUploads.upload(sessionId, {data: base64, name}) → receiptId, prompt 的 content 里追加 {type:"file", receiptId}(附件由 host 侧 ctx.attachments 解析落地)。
fileUploads 用可选注入(ctx.inject(["fileUploads"], …)),profile 没提供时插件照常工作,只是 /m/api/upload 返回 503。
7. H5 只发一次 follow:follow 与 ensureStream 互相调用过会在连接建立前刷出上万条 follow, host 随之反复重放快照基线并把流式内容冲掉。现在队列去重 + followedOnSocket 记忆。
8. 重复快照按「合并」处理:重连/重新 follow 会重复下发基线,直接 reset 会抹掉已翻出的更早历史与正在流式的条目。
9. 静态资源无感升级(不需要任何手写版本号,也不新增接口):
- 静态资源一律带内容哈希 ETag + Cache-Control: no-cache:浏览器每次带 If-None-Match 问一句,没变回 304(只有响应头,几十字节,body 直接来自缓存),变了自动拿到新文件;图片/字体另加长缓存。
- H5 用同一套缓存校验自检:对 5 个静态文件 fetch(..., {cache:"no-cache"}) 并把内容算成指纹,与启动时的指纹比对,变了就 location.reload()。触发时机是「回到前台」与「每 5 分钟」,节流 60s,正在写草稿会推迟到草稿清空;任一文件没取到就跳过本轮,避免断网误判成「有新版本」而无限自刷。
- 因此改完文件不用做任何事:手机下次切回来自动升级;reload 后用 dsh-link-session 回到原会话。
安装
git clone https://github.com/paayton/dsh-link.git
1) 链接插件到 profile(pnpm link)
dsh plugin --profile desktop add ./dsh-link
2) 把 dsh-link 加进 ~/.dsh/profiles/desktop/package.json 的 dsh.profile.bundles 数组
3) 桌面版热重载 profile(编辑 package.json 即触发)后生效
卸载:从 dsh.profile.bundles 移除 "dsh-link",并 dsh plugin --profile desktop remove dsh-link。
配置(cordis.patch.yml 的 config)
| 键 | 默认 | 说明 |
| lanEnabled | true | 是否开启独立监听 |
| lanPort | 19388 | 监听端口 |
| bindHost | 127.0.0.1 | 绑定地址。默认仅回环(安全);要让手机经内网/Tailscale 接入,改为 "0.0.0.0" |
⚠️ 改为 0.0.0.0 会把(受密钥保护的)只读/聊天口暴露到局域网。内网 HTTP 为明文,建议仅在可信网络使用;对安全有要求请走 Tailscale。手机接入前务必先在「设置 → Link」里生成连接密钥。
手机连接(bindHost 设为 0.0.0.0 后)
1. 桌面版 设置 → Link,点「生成密钥」并复制。
2. 手机与 Mac 连同一 Wi-Fi(或登录同一 Tailscale 账号)。
3. 手机浏览器打开设置页里列出的地址,如 http://<内网IP或Tailscale名>:19388/m/。
4. 输入密钥(自动保存),进入会话边栏,开始聊天。
兼容性
dsh-link 依赖 DSH 的内部 API(sessionController 门面、fileUploads 收据、cordis 上下文),因此与桌面版版本强绑定:
| dsh-link | DeepSeek Harness 桌面版 | 说明 |
| 0.1.x | 0.2.0-rc.2 | 当前开发版本,host 段类型即按此版本编写 |
升级桌面版后如果出现接口报错,先跑 pnpm typecheck——@deepseek-ai/ 的 devDependency 版本要同步改成新版本号。
注意 npm 上这些包的 latest tag 指向旧版本(如 dsh-session 的 latest 是 0.0.1-rc.1),必须写死 @0.2.0-rc.2 这类精确版本。
故障排查
| 症状 | 原因 | 处置 |
| 手机端停在密钥门 / 提示密钥失效 | 密钥在桌面版重新生成过 | 设置 → Link 里复制新密钥重输 |
| 新接口 404(/m/api/upload、/m/api/attachment) | host 代码改动没生效:插件是启动时加载的 | 重启桌面版(重组 profile 不够,见 CONTRIBUTING) |
| 发送消息报 Cannot read properties of undefined (reading 'throwIfAborted') | 进程内直调 Remote 门面时漏传 signal | prompt(request, signal) / upload(agent, request, signal),已在 types.ts 固化 |
| 图片发不出去、提示"桌面版还没加载图片接口" | 同上,host 未重载 | 重启桌面版 |
| 历史图片显示成 🖼 文件名 而不是缩略图 | 同上(旧版 host 没有附件读取接口) | 重启桌面版 |
| 界面看起来是旧版 | 浏览器缓存了旧 H5 | 现在有内容 ETag + 构建号自检,刷新一次即可;仍异常就清一次站点数据 |
| 手机连不上 | bindHost 默认只绑回环 | 在 cordis.patch.yml 里改成 "0.0.0.0" 或用 Tailscale |
开发
pnpm install # 只装 dev 依赖,运行时零第三方依赖
pnpm typecheck # 对 DSH 官方类型做编译期检查
pnpm build # 编译 host 段到 dist/
pnpm test # build + 全部测试
改 src/public/ 保存即生效(手机端自动升级);改 src/host/.ts 需要重启桌面版。
详见 CONTRIBUTING.md。
测试
pnpm test # tsc + vitest(149 项)
pnpm test:watch # 开发时监听
pnpm run coverage # 带覆盖率报告
149 项测试,全部跑在 6 秒内,分三层:
| 文件 | 覆盖对象 | 项数 |
| test/md.test.mjs | Markdown 渲染与转义安全(纯函数) | 19 |
| test/transcript.test.mjs | 会话事件归约:历史/实时流/工具卡/分页/附件引用(纯函数) | 20 |
| test/ws-mini.test.mjs | 自研 WebSocket 协议一致性(对照 Node 内置客户端) | 10 |
| test/host-integration.test.mjs | host 全栈:mock DSH 上下文 + 真实 HTTP/WS(密钥门、静态资源与 ETag、会话 API、图片上传与附件、流式转发) | 33 |
| test/client-smoke.test.mjs | 桌面版设置页插件契约 | 6 |
| test/app-ui.test.mjs | H5 客户端 UI 层(jsdom 跑真实 index.html + 真实 app.js,只桩掉网络/WS) | 61 |
UI 层测试覆盖的是以前只能手点的部分:密钥门分支、快照渲染(Markdown/工具卡/思考块)、 host 双层包装的流式帧(回归)、durable 消息接管流式条目、图片选图→压缩→上传→发 prompt 的顺序、上传失败回退托盘、旧版 host 下附件接口 404 的降级。
覆盖率基线(pnpm run coverage):整体 84.4% 语句,其中 app.js 85.8%、transcript.js 93.1%、md.js 93.2%; net.js 偏低的 34.3% 是 Tailscale 探测分支(依赖本机 CLI,未做单测)。
目录
- src/host/ — host 段:index.ts(装配)、routes.ts(HTTP 分发)、stream.ts(WS follow 桥)、key-store.ts(密钥)、net.ts(网络探测)、ws-mini.ts(零依赖 WS)
- src/client/client.js — 设置页「Link」栏(React,手写产物格式)
- src/public/ — H5 静态单页:index.html(结构)、style.css(设计系统)、app.js(界面/连接/输入)、 transcript.js(事件归约,纯函数)、md.js(Markdown,纯函数)、manifest.webmanifest + icon*.png/svg(加到主屏)
- src/host/types.ts — 我们对 DSH 内部 API 的依赖面(官方类型 + 结构化类型)
- dist/ — host 段编译产物(gitignore,发布时随包)
- test/ — 六组自测(见上)
- docs/H5-bridge-design.md — 原始设计文档(部分假设已在实现中修正,见上「关键架构决定」)
- docs/H5-client.md — H5 客户端实现说明:数据模型、实时流形状、已踩过的坑
- dsh-investigation/ — 从 app.asar 提取的官方包源码(本地参考,已 gitignore)
- CONTRIBUTING.md — 开发环路、类型约定、测试约定
许可
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
paayton/dsh-link
用手机浏览器接入桌面会话,随时查看与回复
相关插件 · 安全 / 权限
智能体逆向工程morluto/rea
用智能体逆向工程任何东西,从应用行为到原生二进制。
★ 415,267已汉化DSH
73.3
智能体集群框架ruvnet/ruflo
面向 Claude Code 与 Codex 的智能体元基座meta-harness。
★ 80,414已汉化MCP
71.9
WorkBuddy 模型接入corrinehu/dsh-workbuddy-connect
2026 年 10 月 20 日起,WorkBuddy…
★ 1,604已汉化DSH
71.7
破甲一键通z91772524-ai/pojia-next
十五个 AI…
★ 967已汉化DSH
71.6
AI 代理虚拟终端strukto-ai/mirage
Mirage 是给 AI 智能体用的虚拟终端:一层 shell,统管数据、命令行和运行时。Unix…
★ 3,756已汉化DSH
70.8
Agent 操作层agentic-os-org/ANOLISA
ANOLISA(Agentic Nexus Operating Layer & Interface System Architecture)|智能体操作系统,带运行时、安全、可观测性,以及 Tokenless 响应压缩,降低 token 用量与成本。
★ 649已汉化DSH
70.7