🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

手机端宿主 EricFL1998/deepseek-harness-mobile

DeepSeek Harness
EricFL19985 天前有提交已提供中文文档扫描:含敏感能力

在安卓手机上本地运行完整智能体与插件

37.9/100
综合分
4
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/27 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查未通过:仓库根目录无 package.json,浅层子目录有 2 份 dsh 插件清单(test-plugin/dsh-archive-manager-main/package.json、test-plugin/dsh-genui-main/package.json),无法唯一定位安装名。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add EricFL1998/deepseek-harness-mobile
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · other
装得上吗
作者未把包发布到 npm,只能用源码安装
插件本身没问题,是分发方式不同
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

仓库根目录无 package.json,浅层子目录有 2 份 dsh 插件清单(test-plugin/dsh-archive-manager-main/package.json、test-plugin/dsh-genui-main/package.json),无法唯一定位安装名

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包deepseek-harness-mobile(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/27 00:30:26

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 70 处,展示前 68 条)
  • 写入剪贴板
    test-plugin/dsh-archive-manager-main/lib/archive-discovery.js:81
    await clipboard.writeText(text);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/plugin-updater.js:68
    if (isDshCliEntry(entry, JSON.parse(readFileSync(manifestPath, "utf8")), directory)) return entry;
  • 请求外部主机registry.npmjs.org
    test-plugin/dsh-archive-manager-main/lib/plugin-updater.js:209
    const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, { signal: AbortSignal.timeout(8e3) });
  • 发起网络请求
    test-plugin/dsh-archive-manager-main/lib/plugin-updater.js:209
    const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, { signal: AbortSignal.timeout(8e3) });
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/plugin-updater.js:220
    const value = record(JSON.parse(await readFile(manifestUrl, "utf8")));
  • 执行外部命令来自配置/变量
    test-plugin/dsh-archive-manager-main/lib/plugin-updater.js:241
    const child = spawn(process.execPath, [entry, "plugin", "--profile", target.profileName, "add", "--config.minimumReleaseAge=0", packageSpec, "--regist
  • 执行外部命令来自配置/变量
    test-plugin/dsh-archive-manager-main/lib/plugin-updater.js:273
    const child = spawn(manager.command, [...manager.args, "add", "--config.minimumReleaseAge=0", packageSpec, "--registry=https://registry.npmjs.org/"],
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:121
    const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:121
    const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:127
    await writeFile(tmp, next, "utf8");
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:129
    await rename(tmp, file);
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:134
    await unlink(tmp).catch(() => {
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:139
    await unlink(backup).catch(() => {
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:141
    await rename(file, backup);
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:143
    await rename(tmp, file);
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:145
    await rename(backup, file).catch(() => {
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:147
    await unlink(tmp).catch(() => {
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:151
    await unlink(backup).catch(() => {
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:156
    const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/release-age.js:156
    const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/session-repair.js:79
    const stat = await lstat(path);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/session-repair.js:87
    const stat = await lstat(current);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/session-repair.js:103
    const names = (await readdir(directory)).filter((name) => /^session(?:\.v[1-9][0-9]*)?\.jsonl(?:\.zstd)?$/.test(name));
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/session-repair.js:108
    const bytes = await readFile(source);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/session-repair.js:131
    previousTarget = await readFile(target);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/session-repair.js:138
    if (digest(await readFile(source)) !== digest(bytes)) throw new Error("\u65E5\u5FD7\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u8BCA\u65AD");
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/lib/session-repair.js:159
    if (previousTarget) await rename(temp, target);
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/lib/session-repair.js:163
    await unlink(temp).catch((error) => {
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/workspace.js:49
    await lstat(path);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/workspace.js:399
    await lstat(path);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/lib/workspace.js:1115
    stat = await lstat(path);
  • 删除本地文件递归
    test-plugin/dsh-archive-manager-main/lib/workspace.js:1131
    await rm(target.path, { recursive: true, force: true });
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/lib/workspace.js:1247
    await rm(sessionDir(spill.root, sessionId), {
  • 写入剪贴板
    test-plugin/dsh-archive-manager-main/src/archive-discovery.ts:96
    try { await clipboard.writeText(text); }
  • 发起网络请求
    test-plugin/dsh-archive-manager-main/src/plugin-update-ui.ts:43
    const response = await fetch(endpoint, method === "GET" ? { cache: "no-store", ...signalOption } : {
  • 写入剪贴板
    test-plugin/dsh-archive-manager-main/src/plugin-update-ui.ts:98
    const write = navigator.clipboard?.writeText(command);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/plugin-updater.ts:78
    if (isDshCliEntry(entry, JSON.parse(readFileSync(manifestPath, "utf8")), directory)) return entry;
  • 请求外部主机registry.npmjs.org
    test-plugin/dsh-archive-manager-main/src/plugin-updater.ts:221
    const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, { signal: AbortSignal.timeout(8e3) });
  • 发起网络请求
    test-plugin/dsh-archive-manager-main/src/plugin-updater.ts:221
    const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, { signal: AbortSignal.timeout(8e3) });
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/plugin-updater.ts:232
    const value = record(JSON.parse(await readFile(manifestUrl, "utf8")));
  • 执行外部命令来自配置/变量
    test-plugin/dsh-archive-manager-main/src/plugin-updater.ts:253
    const child = spawn(process.execPath, [entry, "plugin", "--profile", target.profileName, "add", "--config.minimumReleaseAge=0", packageSpec, "--regist
  • 执行外部命令来自配置/变量
    test-plugin/dsh-archive-manager-main/src/plugin-updater.ts:285
    const child = spawn(manager.command, [...manager.args, "add", "--config.minimumReleaseAge=0", packageSpec, "--registry=https://registry.npmjs.org/"],
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:119
    const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:119
    const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:125
    await writeFile(tmp, next, "utf8");
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:127
    await rename(tmp, file);
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:132
    await unlink(tmp).catch(() => {});
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:136
    await unlink(backup).catch(() => {});
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:137
    await rename(file, backup);
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:139
    await rename(tmp, file);
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:141
    await rename(backup, file).catch(() => {});
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:142
    await unlink(tmp).catch(() => {});
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:145
    await unlink(backup).catch(() => {});
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:149
    const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/release-age.ts:149
    const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/session-repair.ts:77
    const stat = await lstat(path);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/session-repair.ts:87
    const stat = await lstat(current);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/session-repair.ts:105
    const names = (await readdir(directory)).filter(name => /^session(?:\.v[1-9][0-9]*)?\.jsonl(?:\.zstd)?$/.test(name));
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/session-repair.ts:109
    const bytes = await readFile(source);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/session-repair.ts:132
    await regularFile(target); previousTarget = await readFile(target);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/session-repair.ts:140
    if (digest(await readFile(source)) !== digest(bytes)) throw new Error('日志已变化,请重新诊断');
  • 写入本地文件
    test-plugin/dsh-archive-manager-main/src/session-repair.ts:157
    if (previousTarget) await rename(temp, target); else await link(temp, target);
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/src/session-repair.ts:160
    await unlink(temp).catch(error => { if (error.code !== 'ENOENT') throw error; });
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/workspace.ts:105
    await lstat(path);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/workspace.ts:522
    await lstat(path);
  • 读取本地文件
    test-plugin/dsh-archive-manager-main/src/workspace.ts:1260
    stat = await lstat(path);
  • 删除本地文件递归
    test-plugin/dsh-archive-manager-main/src/workspace.ts:1276
    await rm(target.path, { recursive: true, force: true });
  • 删除本地文件
    test-plugin/dsh-archive-manager-main/src/workspace.ts:1402
    await rm(sessionDir(spill.root, sessionId), {
扫描于 2026/10/31(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库
涉及外部主机:registry.npmjs.org

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

一个完整的 DeepSeek Harness 移动客户端

README

由 DeepSeek 最新模型翻译生成
🌐 产品介绍页 · English page DSH 手机端(完整版 DeepSeek Harness) DSH 手机端不是「连到电脑的远程客户端」,也不是只保留聊天界面的精简壳。它把完整版 DeepSeek Harness 装进 Android 手机:真实的 DSH Host、智能体循环、工具运行时与插件系统都在手机上本地运行,桌面端能做的事在这里同样能做。 核心 - 完整 DSH Host 在手机本地运行:内置 Debian (glibc) + proot 用户空间与 Node 运行时,直接启动上游 DSH。会话、智能体、工具调用、审批、定时任务、智能体 Team、插件加载全部由真实 Host 处理,不是重新实现的「手机版协议」。 - 插件生态原样兼容:Host 侧插件、bundle、client-slots 注册与 bridge/v1 协议全部保留。需要 DOM 的重型界面跑在 Web 岛,核心界面由原生 Compose 渲染,插件不需要为手机重写业务逻辑。 - 伴生原生 UI:APK 形式的伴随插件可以用 DSH Native UI SDK 以 Kotlin + Compose 编写真正的原生界面,并注册到聊天、设置、侧栏、输入栏等落点。
展开完整文档(README 剩余 1 节)
🌐 产品介绍页 · English page

DSH 手机端(完整版 DeepSeek Harness)

DSH 手机端不是「连到电脑的远程客户端」,也不是只保留聊天界面的精简壳。它把完整版 DeepSeek Harness 装进 Android 手机:真实的 DSH Host、智能体循环、工具运行时与插件系统都在手机上本地运行,桌面端能做的事在这里同样能做。

核心

- 完整 DSH Host 在手机本地运行:内置 Debian (glibc) + proot 用户空间与 Node 运行时,直接启动上游 DSH。会话、智能体、工具调用、审批、定时任务、智能体 Team、插件加载全部由真实 Host 处理,不是重新实现的「手机版协议」。
- 插件生态原样兼容:Host 侧插件、bundle、client-slots 注册与 bridge/v1 协议全部保留。需要 DOM 的重型界面跑在 Web 岛,核心界面由原生 Compose 渲染,插件不需要为手机重写业务逻辑。
- 伴生原生 UI:APK 形式的伴随插件可以用 DSH Native UI SDK 以 Kotlin + Compose 编写真正的原生界面,并注册到聊天、设置、侧栏、输入栏等落点。
- 真实工作区:默认工作区根目录是手机共享存储的 /storage/emulated/0/Documents/DSH-Workspace,在容器内挂载为 /workspace;系统文件管理器直接可见,产物无需导出。
- 多 Host:本地 Host 与远程私有网关 Host 并存、随时切换。

功能概览

| 能力 | 说明 |
| 对话与智能体 | 完整 DSH 智能体会话、流式消息、思考折叠、工具调用与审批;错误原样展示 |
| 工作过程展示 | 聚焦结果 / 关键细节 / 完整过程,与桌面端 transcriptView 语义一致 |
| 模型与推理等级 | 模型目录、服务商凭据、推理档位全部来自 Host modelCatalog(含本地缓存) |
| 文件与交付物 | 原生文件浏览、文档预览、交付物列表,直接读写手机工作区 |
| 右侧栏(Drawer) | 官方 dock 样式:文件 / 终端 / 浏览器 / 计划 / 交付,开始页胶囊与插件页面均可扩展 |
| 自动化与团队 | 定时任务、智能体 Team 任务看板、终端、浏览器入口 |
| 插件 | 安装 / 启停 / 卸载、插件详情、Web 岛,以及原生插件 APK 的发现与加载 |
| 账号与引导 | 官方欢迎页(登录 / 添加 API Key)、首次引导、模型登录态与凭据管理 |
| 多主机 | 本地 Host + 远程 Host 配对、切换与独立凭据 |

插件与伴生原生 UI

DSH 手机端保留两层插件能力:

1. Host 插件(与桌面同一套) 插件仍运行在真实 DSH Host 里,通过官方 slot 注册界面。手机端把核心 slot 映射为原生 Compose 组件,需要 Web 的界面跑在 Web 岛;插件代码不需要分叉。

2. 伴生原生 UI 插件(Native UI SDK) 以 APK 形式随插件分发的原生界面,使用 DSH Native UI SDK 编写:
- Kotlin + Jetpack Compose,直接使用 DSH 设计令牌与控件;
- 通过 NativeSlot 注册到 RIGHT_PANEL、RIGHT_PANEL_GUIDE_ENTRY、SETTINGS_SHEET、COMPOSER_DOCK 等落点;
- 与 Host 的 RPC、主题、模型数据通过 SDK 提供的 Host API 交互。

SDK 源码、接入方式与示例: https://github.com/EricFL1998/dsh-mobile-plugin-sdk

插件商店(用户视角)

打开 App 左下角抽屉 → 插件,就是插件商店入口。这里可以像桌面端一样管理整套插件生态:

- 浏览与安装:内置官方插件与第三方插件列表,点进详情即可一键安装;安装过程由 Host 完成,不需要电脑或命令行。
- 启用 / 停用:每个插件、每个组件都有开关;改动即时生效,少数需要重启 Host 的会明确提示。
- 更新与卸载:插件版本、来源、包含组件都能在详情页看到;可单独卸载,不会影响其他插件。
- 按需扩展:需要什么能力就装什么插件,不装也不影响核心智能体;插件安装后会自动出现在设置、侧栏、输入栏等对应位置。
- 原生插件也在商店里:带原生界面的伴生插件同样是普通 APK,安装后由 App 发现并加载。

插件商店负责「发现和安装」,真正的插件代码运行在手机本地的 Host 里;这也是 DSH Mobile 和普通聊天客户端的区别。

Bridge 与 Rootfs(简单说)

- Bridge:Host 里的一层兼容/设备能力插件。它把官方客户端的 slot 注册转成手机端能渲染的界面,并把文件、通知、剪贴板、调度等手机能力暴露给 Host。你不需要配置它,随镜像内置。
- Rootfs:手机里的一套 Debian + Node + DSH 运行时镜像,首次启动自动准备。版本串由 rootfs-dsh…-bridge… 三段组成:DSH 段变化会要求重装镜像,只有 rootfs 段变化时是设置里的可选更新。

App 是如何运作的

启动 App └─ 检查/安装 Rootfs(Debian + Node + DSH) └─ 在 proot 用户空间启动真实 DSH Host(优先使用打包好的 Host 入口) ├─ Host 监听本地 loopback Web GUI 与 Remote RPC ├─ Bridge 插件注册界面 slot / 暴露设备能力 └─ App 通过 Remote + bridge 读取会话、模型、插件、文件 ├─ 原生 Compose 渲染聊天、设置、侧栏等核心界面 ├─ 插件 Web 界面放进 Web 岛 └─ 伴生插件 APK 通过 Native UI SDK 渲染原生界面

所以数据流是:手机上真实的 Host 处理 Agent 与工具 → App 只做原生呈现与交互。插件、会话、文件、模型都在本机,不经过第三方服务器;远程 Host 模式只是把这条链路换成你指定的网关。

工程结构

app/ 应用入口、导航、设置、右侧栏等原生界面 core/ 模型、协议、bridge、Room 缓存、设计系统 feature/ 聊天、会话、文件、审批、设置、运行时 plugin/ Web 岛、Surface 适配层、原生插件宿主(NativeSlot / Native UI SDK 接入) runtime/ 本地 proot Host 生命周期、bridge 设备能力 tooling/ 协议代码生成、契约回放、前端补丁

构建 bash ./gradlew :app:assembleDebug

产物:app/build/outputs/apk/debug/app-debug.apk

要求:JDK 21、Android SDK 35。Native UI SDK 通过 Gradle 组合构建(includeBuild)引用同级目录的 SDK 仓库,可用 -PdshSdkRepo=<path> 覆盖路径。
bash
./gradlew test

更新日志

版本变化见 CHANGELOG.md;发版顺序与版本约束见 RELEASING.md。

相关仓库

- 本仓库(Android App):https://github.com/EricFL1998/deepseek-harness-mobile
- 伴生原生 UI SDK:https://github.com/EricFL1998/dsh-mobile-plugin-sdk
- 上游 DeepSeek Harness:https://github.com/deepseek-ai/dsh
预览分享卡片长什么样 ↓EricFL1998/deepseek-harness-mobile
分享 · DeepSeek Harness Hub
EricFL1998/deepseek-harness-mobile

在安卓手机上本地运行完整智能体与插件

回到顶部