网站上的案例研究: · 技术文章俄语发表在 Habr
36.7/100
综合分
6
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/27 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查未通过:仓库根目录及浅层子目录均无 dsh 插件清单,无法用 dsh 插件安装命令安装。以下命令仍可尝试,但可能失败。
无法用 dsh 插件命令安装(仓库内无 dsh 插件清单)
git clone https://github.com/pavel-logachev/dsh-mobile.git按该仓库 README 的原生方式安装;若作者另行发布了 DSH 插件包,请以其文档为准
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · vision
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 8 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(unknown · 2026/10/27) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装仓库根目录及浅层子目录均无 dsh 插件清单,无法用 dsh 插件安装命令安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-mobile(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/27 23:43:06
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件
查看扫描证据(共 49 处,展示前 46 条)
- 写入本地文件host/src/cli.ts:123
await mkdir(dirname(configPath), { recursive: true, mode: 0o700 }); - 写入本地文件host/src/cli.ts:124
await writeFile(configPath, JSON.stringify(prepared.config, null, 2) + '\n', { flag: 'wx', mode: 0o600 }); - 读取本地文件host/src/config.ts:30
const canonical = await realpath(path); - 读取本地文件host/src/config.ts:31
const info = await stat(canonical); - 读取本地文件host/src/config.ts:57
const path = await realpath(workspace.path); - 读取本地文件host/src/config.ts:58
if (!(await stat(path)).isDirectory() || paths.has(path)) throw new HostError('invalid_config'); - 写入本地文件host/src/config.ts:63
await mkdir(dirname(raw.statePath), { recursive: true, mode: 0o700 }); - 读取本地文件host/src/config.ts:64
const statePath = join(await realpath(dirname(raw.statePath)), basename(raw.statePath)); - 读取本地文件host/src/config.ts:65
try { const info = await lstat(statePath); if (!info.isFile() || info.isSymbolicLink()) throw new HostError('invalid_config'); } - 写入本地文件host/src/demo.ts:16
await Promise.all(workspaces.map(workspace => mkdir(workspace.path, { recursive: true }))); - 写入本地文件host/src/demo.ts:60
await writeFile(path, JSON.stringify(running.invitation), { encoding: 'utf8', flag: 'wx', mode: 0o600 }); - 读取本地文件host/src/dsh-adapter.ts:973
if (workspacePathKey(path) !== workspacePathKey(workspace.path) || !(await stat(path)).isDirectory()) throw new Error(); - 读取本地文件host/src/file-staging.ts:24
try { await lstat(this.directory); } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') return; throw error; } - 读取本地文件host/src/file-staging.ts:26
for (const entry of await readdir(this.directory, { withFileTypes: true })) { - 删除本地文件host/src/file-staging.ts:30
await unlink(target); - 读取本地文件host/src/file-staging.ts:59
return createReadStream(path, { highWaterMark: 65536, signal }); - 删除本地文件host/src/file-staging.ts:66
try { await unlink(path); } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; } - 读取本地文件host/src/private-files.ts:13
if ((await lstat(walk)).isSymbolicLink()) throw new HostError('unsafe_private_path'); - 读取本地文件host/src/private-files.ts:17
try { await lstat(resolve(walk, '.git')); throw new HostError('unsafe_private_path'); } - 读取本地文件host/src/private-files.ts:25
return resolve(await realpath(existing), relative(existing, full)); - 执行外部命令固定命令host/src/private-files.ts:42
try { execFileSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-EncodedCommand', Buffer.from(script, 'utf16le').toString('base64')], { env: { - 读取本地文件host/src/private-files.ts:46
const full = await privatePath(path), info = await lstat(full); - 读取本地文件host/src/private-files.ts:53
try { if (!(await lstat(full)).isDirectory()) throw new HostError('unsafe_private_path'); } - 写入本地文件host/src/private-files.ts:56
await mkdir(full, { recursive: true, mode: 0o700 }); - 写入本地文件host/src/private-files.ts:57
if (process.platform === 'win32') windowsAcl(full, true, true); else await chmod(full, 0o700); - 写入本地文件host/src/private-files.ts:62
if (process.platform === 'win32') windowsAcl(path, true, false); else await chmod(path, 0o600); - 写入本地文件host/src/private-files.ts:67
await writeFile(full, text, { flag: 'wx', mode: 0o600 }); - 读取本地文件host/src/private-files.ts:72
if ((await lstat(path)).size > 65536) throw new HostError('invalid_config'); - 执行外部命令固定命令host/src/setup-direct.ts:17
? execFileSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', "$ErrorActionPreference='Stop'; $global:LASTEXITCODE=0; $dsh=Get-Comman - 执行外部命令固定命令host/src/setup-direct.ts:18
: execFileSync('dsh', ['--version'], { encoding: 'utf8', timeout: 15000, stdio: ['ignore', 'pipe', 'ignore'] }); - 执行外部命令来自配置/变量host/src/setup-direct.ts:37
const result = spawnSync(executable, ['version'], { encoding: 'utf8', windowsHide: true, timeout: 10000 }); - 读取本地文件host/src/setup-direct.ts:53
try { await lstat(configPath); exists = true; } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; } - 读取本地文件host/src/setup-direct.ts:65
try { await lstat(join(dir, name)); throw new HostError('invalid_config'); } - 执行外部命令来自配置/变量host/src/setup-direct.ts:72
const generated = spawnSync(openssl, ['req', '-x509', '-newkey', 'ec', '-pkeyopt', 'ec_paramgen_curve:P-256', '-sha256', '-nodes', '-days', '825', '-k - 读取本地文件host/src/setup-direct.ts:77
const prepared = await prepareConfiguration(raw), cert = new X509Certificate(await readFile(certPath, 'utf8')); - 写入本地文件host/src/state.ts:49
mkdirSync(dirname(path), { recursive: true, mode: 0o700 }); - 写入本地文件host/src/state.ts:51
if (process.platform !== 'win32') chmodSync(path, 0o600); - 读取本地文件host/src/workspace-source.ts:43
async function directory(path: string): Promise<boolean> { try { return (await stat(path)).isDirectory(); } catch { return false; } } - 读取本地文件host/src/workspace-source.ts:117
const path = await realpath(entry.path), key = workspacePathKey(path); - 写入本地文件relay/src/cli.ts:37
await mkdir(dirname(output), { recursive: true, mode: 0o700 }); - 删除本地文件relay/src/cli.ts:48
await unlink(output).catch(() => {}); throw error; - 读取本地文件relay/src/cli.ts:65
const cert = await readFile(resolve(certPath)), key = await readFile(resolve(keyPath)); - 写入本地文件relay/src/state.ts:28
mkdirSync(dirname(path), { recursive: true, mode: 0o700 }); - 读取本地文件relay/src/state.ts:29
if (existsSync(path)) { - 读取本地文件relay/src/state.ts:30
const file = lstatSync(path); - 写入本地文件relay/src/state.ts:36
if (path !== ':memory:' && process.platform !== 'win32') chmodSync(path, 0o600);
扫描于 2026/11/2(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 手机查看项目聊天
- 远程派发任务
- 扫码绑定设备
DeepSeek Harness 的 Android 应用:手机上查看所有项目的聊天、任务和智能体回复。扫码绑定,走 Wi-Fi/Tailscale,不经过云端。
README
由 DeepSeek 最新模型翻译生成DSH Mobile
网站上的案例研究:<https://logachev.net/#case-dsh-mobile> · 技术文章(俄语)发表在 Habr
你的 DeepSeek Harness 智能体跑在电脑上。你用 Android 手机派任务,可以带照片和文件;实时读回复,回答智能体的问题,收到「回答已就绪」通知。
下载 APK 0.8.2 · 安装 · 架构 · 安全
Pavel Logachev 的非官方项目,独立于 DeepSeek 开发。
Android 8.0+ · 二维码配对 · Wi‑Fi 或 Tailscale
模型、工具和订阅都留在电脑上。DSH Mobile 没有云服务器。
用手机能做什么
- 打开所有项目的会话。 搜索会话,按项目筛选。项目列表跟随 DSH 侧边栏,无需重新配对即可更新。
- 派任务。 选好项目和预设,直接写任务:应用会创建会话,并把文本发送一次。
- 发送照片和文件。 相机拍照,照片走系统照片选择器(Photo Picker),文件走系统文件选择器。选完就开始上传。一条消息最多带 20 个附件,总大小不超过 200 MiB,单个文件不超过 20 MiB。PNG、JPEG、WebP 和 GIF 图片会以图片形式交给智能体;文件在发送时交给 DSH 附件存储。未发送的上传会在电脑上 10 分钟后过期,永远不会到达 DSH。
展开完整文档(README 剩余 1 节)
DSH Mobile
网站上的案例研究:<https://logachev.net/#case-dsh-mobile> · 技术文章(俄语)发表在 Habr
你的 DeepSeek Harness 智能体跑在电脑上。你用 Android 手机派任务,可以带照片和文件;实时读回复,回答智能体的问题,收到「回答已就绪」通知。
下载 APK 0.8.2 · 安装 · 架构 · 安全
Pavel Logachev 的非官方项目,独立于 DeepSeek 开发。
Android 8.0+ · 二维码配对 · Wi‑Fi 或 Tailscale
模型、工具和订阅都留在电脑上。DSH Mobile 没有云服务器。
用手机能做什么
- 打开所有项目的会话。 搜索会话,按项目筛选。项目列表跟随 DSH 侧边栏,无需重新配对即可更新。
- 派任务。 选好项目和预设,直接写任务:应用会创建会话,并把文本发送一次。
- 发送照片和文件。 相机拍照,照片走系统照片选择器(Photo Picker),文件走系统文件选择器。选完就开始上传。一条消息最多带 20 个附件,总大小不超过 200 MiB,单个文件不超过 20 MiB。PNG、JPEG、WebP 和 GIF 图片会以图片形式交给智能体;文件在发送时交给 DSH 附件存储。未发送的上传会在电脑上 10 分钟后过期,永远不会到达 DSH。
- 实时查看回复。 支持 Markdown、表格、带复制按钮的代码块。消息里的图片直接显示在对话中;点一下打开全屏查看器,可以缩放、通过 Share 发送或保存。消息里的文件可以下载,最大 20 MiB。服务事件折叠成一行「Agent activity」,点开看全文。长对话被压缩后,旧历史在限制内无法恢复时,会打开最新消息,并提示历史已截断。
- 智能体工作时也能发消息、插话引导。 默认情况下,消息进入 DSH 队列,在智能体下一轮时送达。「Steer」会在智能体下一步送达,不打断当前轮次:长按发送按钮,或点排队消息上的 ↳。也可以把消息从队列里移除。
- 回答智能体的问题。 选一个或多个选项,写自己的答案,或跳过问题。智能体推荐的选项有标记,但不会预先选中。智能体操作的审批仍在电脑上完成。
- 重命名对话、更换模型。 两个操作都在 ⋯ 菜单里。新模型从下一次模型请求开始生效,最早可能是当前轮次的下一步;已经进行中的请求不会切换。
- 停止运行。 单独的 Stop 按钮,点击后需要确认。
- 接收通知。 「Answer ready」和「Agent needs your decision」分别可选「With sound」(带声音的弹窗横幅)、「Silent」和「Off」。每种模式有各自的 Android 通道,应用设置里有跳转到系统通道设置的链接。更新时保留你之前的系统选择:禁用的通道保持禁用,静音的保持静音。每个新事件都有声音,多条提醒会合并,常驻连接通知是静音的。智能体提问的通知会直接打开那个问题。电脑确认完全恢复、没有遗漏后,「Some events may have been missed」警告会自动消失。屏幕上正打开的对话不发送通知。可以按项目、按对话单独关闭通知。
- 回到对话。 支持消息搜索、每个对话的草稿、长按复制。
附件、「Steer」、回答问题、重命名、更换模型、查看和下载文件,以及新的通知功能,都需要配套插件 0.7.0 或更高版本。当前版本里的通知延迟和发送准入修复需要插件 0.7.2。只有连接的插件报告支持某项新功能,应用才会显示它。
主题跟随系统,也可以手动选浅色或深色。界面支持俄语和英语:语言跟随系统,或在应用设置里选择。支持大字号。
截图取自真实应用,用的是合成的演示数据。里面没有真实聊天记录,也没有连接任何模型。
截图
DSH Mobile 0.8
DSH Mobile 0.8:智能体在你电脑上干活,你和它的聊天在手机上。
Chats from all projects
所有 DSH 项目的聊天,汇成一个列表。
A message while the agent is working
智能体正在干活,你补一条消息:放进队列,或者在下一步「Steer」。
Attachments in a message
相机照片、相册图片和文件——一条消息发给智能体。
Agent question
智能体提问:选一个选项、自己写答案,或者跳过。
Chat menu
⋯ 菜单:重命名聊天、切换模型。
Image viewer
聊天里的图片全屏查看:缩放、分享、保存。
Notifications
通知:答案好了,智能体提问了。
工作原理
电脑上装一个配套插件。它通过安全连接,向已配对的手机开放一个窄接口,但不会把 DSH 的 Web 界面暴露到外网。
Android app
│ HTTPS over Wi‑Fi or Tailscale
│ or through your own relay
▼
Companion plugin inside DSH
│
▼
Your projects and agents on the computer
手机只是客户端:关掉应用,智能体照常干活。主要对话历史存在电脑上的 DSH 里。
Android 客户端用 Kotlin 和 Jetpack Compose 编写;插件跑在 Node.js 上。自建中继是可选连接方式;项目不提供共享的公共中继。
安装
你可以把详细的安装指南交给 DSH 智能体。里面有环境检查、命令,以及安装、访问权限和激活的分步确认。
1. 检查环境要求。
电脑:Windows、DeepSeek Harness 0.2.0-rc.2 或 0.2.1-alpha.1、Node.js 24.x、OpenSSL 3。手机:Android 8.0 或更高版本。插件所在的 DSH 进程也要求 Node 24——PATH 上有一个合适版本还不够。
2. 下载并校验发布文件。
从 release 0.8.2 开始,你需要签名的 dsh-mobile-0.8.2.apk、插件归档包 dsh-mobile-host-0.7.2.zip,以及它们的校验和:dsh-mobile-0.8.2.apk.sha256、dsh-mobile-host-0.7.2.zip.sha256。归档包里是配套插件 0.7.2,对应应用 0.8.2。所有文件必须来自同一个 release。UNSIGNED-verification.apk 是校验产物,不是用来安装的文件。
指定下载文件的绝对路径,把哈希与 .sha256 文件比对。对不上就停下。
$zip = '<ABSOLUTE_DOWNLOADED_HOST_ZIP>'
$apk = '<ABSOLUTE_DOWNLOADED_SIGNED_APK>'
(Get-FileHash -LiteralPath $zip -Algorithm SHA256).Hash.ToLowerInvariant()
(Get-FileHash -LiteralPath $apk -Algorithm SHA256).Hash.ToLowerInvariant()
Compare exactly with the release's .sha256 files. A mismatch means STOP.
3. 在电脑上准备插件。
从归档包里解出 installer,读一遍。下面的命令里要替换占位符:脚本路径,以及电脑在家庭网络或 Tailscale 里的地址。如果不需要额外地址,删掉数组的第二个元素。
$installer = '<ABSOLUTE_REVIEWED_INSTALL_HOST_PS1>'
$hosts = @('<ACTUAL_PRIMARY_LAN_OR_TAILSCALE_HOST>', '<OPTIONAL_ADDITIONAL_SAN>')
Remove the second element if not needed. Substitute approved real values locally.
& $installer -ZipPath $zip -Hosts $hosts -WhatIf
& $installer -ZipPath $zip -Hosts $hosts
这一步只准备文件和配置,还没把插件接到 DSH。
4. 激活插件。
确认过将要做的改动之后:
& $installer -ZipPath $zip -Hosts $hosts -Activate
安装脚本不会重启 DSH。如果插件没启动,按指南里的排查步骤处理:可能需要重启,但要单独批准。
如果家庭 Wi‑Fi 需要 Windows 防火墙规则,只在所有者同意后添加,且只对专用网络生效。安装脚本不会自动改防火墙。
5. 在手机上安装 APK。
允许 Android 从所选来源安装应用。装完把这项权限关掉。
6. 用二维码配对手机。
在电脑上,指定已安装插件版本的目录,检查配置:
$plugin = '<EXACT_LOCALAPPDATA_DSHMOBILE_PLUGIN_VERSION_DIRECTORY>'
$cli = Join-Path $plugin 'dist/cli.js'
$config = Join-Path $env:LOCALAPPDATA 'DSHMobile/host/host.json'
node $cli verify-config --config $config
然后选一条配对命令。只读访问全部现有和未来的项目:
node $cli pair --config $config --read all --ttl 300 --qr
或者读访问加运行任务,覆盖这些全部项目——只有你同意把这两项权限交给手机时才这么做:
node $cli pair --config $config --read all --execute all --ttl 300 --qr
在 App 里点「扫描二维码」,核对电脑地址和证书指纹,然后确认配对。摄像头只用来扫码;识别二维码不联网,也不需要 Google 服务。
要在离家时使用,在电脑和手机上安装 Tailscale,把两台设备都连到你的 Tailscale 网络,准备插件时填上电脑的名字。不用在路由器上开端口。另一种做法是在 VPS 上自建中继。
升级: APK 0.8.2 与之前所有版本用同一密钥签名,可以直接覆盖安装,不用先卸载。2026 年 10 月 24 日,在一台搭载 Android 16 的 OnePlus 上验证了 0.8.2 覆盖 0.8.1:配对保留。验证记录:2026 年 10 月 23 日,在一台 OnePlus CPH2747 上验证了 0.8.1 覆盖 0.8.0:应用数据和配对保留。更早的时候,在机主的手机上验证了 0.8.0 覆盖 0.7.1:聊天记录和配对保留;这样升级时设置也会保留。0.6.1 → 0.7.0 和 0.7.0 → 0.7.1 的升级在同一台手机上验证过,0.7.1 覆盖已发布的 0.7.0 也在 Android 11 模拟器上验证过。安装器用 -Upgrade -Activate 开关从新归档把插件升级到 0.7.2:安装器先把 DSH 配置档里的插件块替换成占位符,等上一个插件释放端口,然后才接入新版本,DSH 会即时加载它。智能体继续工作,手机短暂断连。如果 DSH 没开热重载,上一个插件也没释放端口,安装器会停下,不接入新版本,并在配置档里留下占位符。这时需要单独批准重启 DSH,但只重启并不能完成升级:上一个插件停止后,还得把新版本接入这一步做完。重启会结束智能体正在跑的回合,所以挑智能体没在跑任务的时候做。升级记录里,插件 0.7.1 给数据库加了一张新表(schema 3 → 4);不改动已有数据。插件 0.5.1 → 0.6.0 的升级在测试副本上验证过,配置、TLS 密钥和配置档其余内容都保留。升级和回滚流程见指南。
当前发布的版本组合是应用 0.8.2 和插件 0.7.2。兼容性记录(不是对当前组合的检查):应用 0.8.1 只在连接的插件上报新功能时才显示这些功能,所以配插件 0.7.0 时保留核心功能,但没有更快的通知投递和空会话修复;这个组合没有单独测过。应用 0.8.0 应该能配插件 0.7.1:插件保留 API v1 和之前的约定;这个组合也没验证过。应用 0.8.0 配插件 0.6.0 能用,但没有 0.8.0 的功能。应用 0.7.0 也在手机上配插件 0.5.1 验证过:没有子代理指示器,首次打开聊天更慢。应用 0.6.1 与插件 0.6.0 协议兼容。
安全
- 智能体权限不变。 插件在 DSH 里运行,权限跟 DSH 一样。项目过滤不是沙箱:智能体从手机上能做的事,跟从电脑上一样。只给可信设备运行任务的权限。
- 邀请是机密。 二维码只能使用一次,有效期不超过 15 分钟。不要公开它,不要发到聊天里,也不要保存到共享日志中。配对时会检查电脑的证书、有效期、地址和固定的指纹。
- 服务商密钥不会发送到手机。 配对数据由 Android Keystore 保护,并排除在备份之外。插件在 Windows 上的私有文件只有该用户账户的所有者才能访问。
- 手机丢失后要在电脑上撤销。 在应用内退出登录只会从手机上删除配对数据,不会在 DSH 一侧撤销访问权限。
- 通知里不含回复正文。「回答已就绪」通知只显示项目和聊天名称。智能体提问的通知在手机解锁时显示第一个问题的文本,在锁屏上只显示聊天名称。聊天内容在锁屏上隐藏。
- 中继看不到聊天内容。 中继转发加密流量,但能看到 IP 地址、时间以及传输的数据量。
不要把 DSH 的 Web 端口暴露到外网,也不要关闭 TLS 校验。详情见安全概览。
从源码构建
在仓库根目录下,用 PowerShell 执行:
cd host; npm ci; npm ci --prefix ../relay; npm run check # companion plugin, Node 24; the tests need the neighboring relay
cd ..\android
powershell -NoProfile -ExecutionPolicy Bypass -Command "& ../tools/android-build.ps1 -Tasks ':app:assembleDebug', ':app:testDebugUnitTest', ':app:lintDebug'"
推荐使用 JDK 21;Windows 辅助脚本也支持 JDK 17。你需要 Android SDK platform 36 和 build-tools 36.0.0。
常规发布构建出的 APK 未签名,无法直接安装。构建、打包插件以及用你自己的密钥签名,见构建指南和 APK 发布指南。
0.8.2 版本检查
发布版本:应用 0.8.2(versionCode 15)和配套插件 0.7.2;详情见 0.8.2 发布说明。插件 0.7.2 运行在所有者自己的 DSH 中,应用 0.8.2 运行在他的手机上。上一版本的检查见 0.8.0 发布说明。
| 组件 | 检查内容 |
| Android 0.8.2 | 在 Android 代码 3dc0126 上:完整 JVM 测试跑了两轮,每轮 357/357;lintDebug — 0 个错误(46 个警告,1 个提示)。发布辅助脚本会执行 assembleRelease、testDebugUnitTest 和 lintRelease |
| APK 签名 | 同一张证书,SHA-256:F9080C63B49A0BDE6B74AA2ADF7E9531D6C4F305978A24D3F5D271A39F1B7B95;v2/v3 方案,16 KB 对齐;不可调试,仅限 HTTPS |
| 插件 0.7.2 | 在 Cordis 模块环境下 282/282;没有该环境时 275 通过、5 跳过(共 280)。对宿主代码的独立复审:修复三个阻塞问题后通过(GO) |
| 安装器 | 28/28 个合成场景;不是对手机上安装的检查 |
| 实体手机 | OnePlus,Android 16,APK 3dc0126:发送状态在 0.3–0.7 s 后出现;在新会话和已有会话中都能发送,空闲超过 110 s 后也能发送;发送 → 按 Home 键 ×2 —— 每次都送达一条提示词;从 0.8.1 升级后配对仍然保留 |
| 机主观察,2026 年 10 月 24 日,莫斯科时间约 11:40 | App 0.8.2 + 实时主机 0.7.2:「Ну вроде бы всё приходит, и чат открывается нужный」(“嗯,好像都能收到,打开的也是对的会话”)。日常使用,没有用仪器测延迟 |
| 未在手机上用仪器验证 | 主机 0.7.2 下的通知延迟和点击路由;真实网络切换时的自动重试和「未发送」横幅(重连期间发送按钮被禁用);真实 Doze 下的送达 |
| APK 权限 | INTERNET、CAMERA、POST_NOTIFICATIONS、FOREGROUND_SERVICE、FOREGROUND_SERVICE_SPECIAL_USE、ACCESS_NETWORK_STATE,以及应用自己的签名级 receiver 权限。没有遥测,也没有 Google 服务 |
限制
- 电脑和 DSH 必须开着。 手机不会自己运行智能体。
- 通知依赖后台连接。 没有走 Google(FCM)的推送。通知开着时,通知栏里会显示「DSH Mobile connected」条目;Android 可能停掉这条连接。手机重启或应用被强制停止后,重新打开应用。
- 部分厂商手机的省电策略可能延迟通知。 计划通过 UnifiedPush 推送。
- 智能体操作的审批在电脑上完成。 DSH 不让插件访问这些审批。电脑上装了 0.7.0 或更高版本的插件,你就能从手机回答智能体的问题。
- 0.8.2 的通知延迟和发送准入修复需要插件 0.7.2。 旧版本组合不能替代对当前版本的检查。
- 一次配对,一台电脑。 列表包含前 100 个已注册项目。没有连接到电脑时,拿不到完整对话历史。
- 更新 DSH 需要做兼容性检查。 插件从自己的设置里读版本号,不是实际安装的版本。只支持上面列出的已验证版本。
- 连接断开不代表任务没发出去。 应用会向电脑查询状态。只有在电脑应答之前就确定网络失败时,它才会自己重发:最多三次,用同一个请求 ID。发送失败时,草稿会保留,应用显示「未发送」横幅和「重试」按钮;这条路径还没在手机上用真实网络切换测过。如果送达仍不确定,先在电脑上查看结果,再重新发送任务。
文档
- 安装、升级和卸载
- 架构
- 移动客户端协议
- 安全
- DSH 集成
- 部署你自己的中继与其协议
- 从源码构建
- 签名并发布 Android APK
- 参与贡献
需要类似的东西?
本项目由 Pavel Logachev 构建。我承接网站、Web 服务、Telegram 机器人、应用和自动化:从梳理需求、搭建方案到上线,全程由我完成。20 年 IT 从业经历:先做工程师,后做项目经理。把你的需求发邮件或在 Telegram 上告诉我——20–30 分钟的评估免费,你也不需要准备好完整的需求文档。价格和其他项目见 logachev.net 和我的主页。
许可证
MIT © 2026 Pavel Logachev。第三方依赖按各自的许可证分发。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
pavel-logachev/dsh-mobile
网站上的案例研究: · 技术文章俄语发表在 Habr
相关插件 · 视觉能力
智能体工作台Devin-AXIS/iPolloWork
企业级、本地优先的智能体工作台,面向个人和智能体团队——一个工作区,容纳多个智能体引擎;一套统一体系,管理插件和技能;支…
★ 7,359已汉化DSH
72
开源设计工作台nexu-io/open-design
OpenDesign:首个协作式 AI 设计智能体工作区
★ 105,514已汉化DSH
71.8
多智能体编码工作区spacering-net/codeg
多智能体协作的 AI 编程工作区:汇总 Claude Code、Codex、OpenCode、Pi、Grok Build 等来源的会话。支持桌面应用、自托管服务器或 Docker。
★ 4,289已汉化DSH
71.6
GPT 图像提示词库freestylefly/awesome-gpt-image-2
Prompt as Code | GPT Image 2 / 2.5 提示词与案例库,530+ 个案例、20+…
★ 34,534已汉化DSH
71.5
架构图生成器tt-a1i/archify
把你想理解、规划或分享的事,变成可以互动的可视化作品。
★ 92,675已汉化DSH
71.2
AI 用量桌面小部件Javis603/token-monitor
EN | 简 | 繁 | KO | JA | PT
★ 3,522已汉化DSH
71