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

安卓桌面端 fellow99/dsh-desktop-android

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

在 Android 手机上运行完整 dsh Web 界面

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

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add fellow99/dsh-desktop-android
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · ui
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 3 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

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

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

可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 80 处,展示前 77 条)
  • 读取密钥环境变量
    logs/20261101-2/key-real.js:6
    const key = process.env.DSH_TEST_API_KEY;
  • 写入本地文件
    packages/attachment-image-android/lib/index.js:43
    appendFileSync(path, `${new Date().toISOString()} SHARP ${line}${String.fromCharCode(10)}`)
  • 读取本地文件
    packages/attachment-image-android/lib/index.js:70
    if (typeof input === 'string') return readFileSync(input)
  • 读取本地文件
    packages/attachment-image-android/lib/index.js:71
    if (input !== null && typeof input === 'object' && typeof input.path === 'string') return readFileSync(input.path)
  • 读取本地文件
    packages/facts-android/lib/index.js:154
    return existsSync(candidate)
  • 读取本地文件
    packages/facts-android/lib/index.js:232
    && existsSync(require('node:path').join(libDir, 'libpty_node.so'))
  • 读取本地文件
    packages/git-android/lib/git-credentials.js:162
    return { path, exists: true, entries: parseCredentials(readFileSync(path, 'utf8')) }
  • 读取本地文件
    packages/git-android/lib/git-credentials.js:187
    text = readFileSync(path, 'utf8')
  • 写入本地文件
    packages/git-android/lib/git-credentials.js:211
    mkdirSync(dirname(path), { recursive: true })
  • 写入本地文件
    packages/git-android/lib/git-credentials.js:213
    writeFileSync(temp, body, { mode: 0o600 })
  • 写入本地文件
    packages/git-android/lib/git-credentials.js:215
    chmodSync(temp, 0o600)
  • 写入本地文件
    packages/git-android/lib/git-credentials.js:220
    renameSync(temp, path)
  • 读取本地文件
    packages/git-android/lib/git-credentials.js:237
    text = readFileSync(path, 'utf8')
  • 删除本地文件
    packages/git-android/lib/git-credentials.js:257
    unlinkSync(path)
  • 写入本地文件
    packages/git-android/lib/git-credentials.js:259
    writeFileSync(path, '', { mode: 0o600 })
  • 写入本地文件
    packages/git-android/lib/git-credentials.js:264
    writeFileSync(temp, body, { mode: 0o600 })
  • 读取本地文件
    packages/git-android/lib/runtime.js:159
    return JSON.parse(readFileSync(manifest, 'utf8')).version ?? 'unknown'
  • 读取本地文件
    packages/market-android/lib/index.js:53
    if (!existsSync(dir) || !statSync(dir).isDirectory()) return null
  • 读取本地文件
    packages/market-android/lib/index.js:53
    if (!existsSync(dir) || !statSync(dir).isDirectory()) return null
  • 发起网络请求
    packages/market-android/lib/index.js:101
    const response = await fetch(url, { signal: ac.signal, headers: { accept: 'application/json' } })
  • 读取本地文件
    packages/market-android/lib/index.js:150
    return JSON.parse(readFileSync(file, 'utf8'))
  • 读取本地文件
    packages/market-android/lib/index.js:178
    const installed = (name) => existsSync(join(profileDir, 'node_modules', ...name.split('/'), 'package.json'))
  • 写入本地文件
    packages/market-android/lib/index.js:206
    writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`)
  • 读取本地文件
    packages/market-android/lib/pnpm-inprocess.js:59
    const stat = statSync(entry)
  • 读取本地文件
    packages/open-in-app-android/lib/index.js:284
    info = await stat(target.path)
  • 读取本地文件
    packages/open-in-app-android/lib/index.js:319
    info = await stat(abs)
  • 写入本地文件
    packages/shell-android/lib/output.js:79
    mkdirSync(spill.dir, { recursive: true })
  • 删除本地文件
    packages/shell-android/lib/output.js:107
    unlinkSync(file)
  • 读取本地文件
    packages/subprocess-android/lib/index.js:226
    const stat = statSync(path)
  • 读取本地文件
    packages/subprocess-android/lib/index.js:228
    accessSync(path, fsConstants.X_OK)
  • 读取本地文件
    packages/subprocess-android/lib/index.js:271
    accessSync(candidate, fsConstants.X_OK)
  • 读取本地文件
    packages/subprocess-android/lib/index.js:295
    stat = statSync(canonical)
  • 执行外部命令来自配置/变量
    packages/subprocess-android/lib/index.js:401
    child = nodeSpawn(program, spec.argv.slice(1), {
  • 启用终端会话(PTY)
    packages/subprocess-android/lib/index.js:631
    terminal = pty.spawn(program, spec.argv.slice(1), {
  • 写入本地文件
    packages/subprocess-android/lib/output.js:79
    mkdirSync(spill.dir, { recursive: true })
  • 删除本地文件
    packages/subprocess-android/lib/output.js:107
    unlinkSync(file)
  • 读取本地文件
    packages/subprocess-android/lib/rg-emulation.js:139
    entries = readdirSync(dir, { withFileTypes: true })
  • 读取本地文件
    packages/subprocess-android/lib/rg-emulation.js:163
    const fd = readFileSync(file)
  • 读取本地文件
    packages/subprocess-android/lib/rg-emulation.js:184
    const st = statSync(file)
  • 读取本地文件
    packages/subprocess-android/lib/rg-emulation.js:222
    const st = statSync(file)
  • 读取本地文件
    packages/subprocess-android/lib/rg-emulation.js:224
    content = readFileSync(file, 'utf8')
  • 写入本地文件
    packages/workspace-picker-android/lib/index.js:311
    await mkdir(target)
  • 写入本地文件
    packages/workspace-picker-android/lib/index.js:331
    await mkdir(root.path, { recursive: true })
  • 读取本地文件
    packages/workspace-picker-android/lib/index.js:344
    info = await stat(canonical)
  • 写入本地文件
    packages/workspace-picker-android/lib/index.js:387
    if (root.id === 'sandbox') await mkdir(root.path, { recursive: true }).catch(() => {})
  • 读取本地文件
    packages/workspace-picker-android/lib/index.js:417
    await readdir(root.path)
  • 读取本地文件
    packages/workspace-picker-android/lib/index.js:663
    const dirents = await readdir(target, { withFileTypes: true })
  • 读取本地文件
    packages/workspace-picker-android/lib/index.js:670
    enterable = (await stat(join(target, dirent.name))).isDirectory()
  • 发起网络请求
    packages/workspace-picker-client-android/lib/client.js:118
    const response = await fetch(ROUTES + path, body === undefined
  • 写入本地文件
    payload/bootstrap.js:38
    fs.mkdirSync(path.dirname(APP_LOG), { recursive: true });
  • 写入本地文件
    payload/bootstrap.js:39
    fs.appendFileSync(APP_LOG, text);
  • 写入本地文件
    payload/bootstrap.js:48
    fs.mkdirSync(path.dirname(READY_FILE), { recursive: true });
  • 删除本地文件
    payload/bootstrap.js:50
    fs.rmSync(tmp, { force: true });
  • 写入本地文件
    payload/bootstrap.js:53
    fs.writeFileSync(fd, body);
  • 写入本地文件
    payload/bootstrap.js:58
    fs.renameSync(tmp, READY_FILE);
  • 执行外部命令固定命令
    payload/bootstrap.js:101
    const r = spawnSync('/system/bin/sh', ['-c', 'printf dsh-sh-ok'], { encoding: 'utf8', timeout: 5000 });
  • 读取本地文件
    payload/bootstrap.js:133
    const lines = fs.readFileSync(VERSION_FILE, 'utf8').split('\n');
  • 写入本地文件
    payload/bootstrap.js:162
    fs.mkdirSync(process.env.DSH_HOME, { recursive: true });
  • 读取本地文件
    payload/bootstrap.js:163
    if (!fs.existsSync(file)) {
  • 读取本地文件
    payload/bootstrap.js:188
    if (!fs.existsSync(dshManifest)) {
  • 读取本地文件
    payload/bootstrap.js:194
    if (!fs.existsSync(path.join(profileDir, 'package.json'))) {
  • 读取本地文件
    payload/bootstrap.js:213
    { marker: 'DSH_ANDROID_SHIM flock', installed: fs.existsSync(path.join(RUN_ROOT, 'node_modules', '@deepseek-ai', 'node-addon-system', 'lib', 'flock.js
  • 读取本地文件
    payload/bootstrap.js:221
    const sharpPkg = JSON.parse(fs.readFileSync(path.join(RUN_ROOT, 'node_modules', 'sharp', 'package.json'), 'utf8'));
  • 读取本地文件
    payload/host-boot.js:31
    if (!fs.existsSync(dshManifest)) {
  • 读取本地文件
    payload/host-boot.js:63
    patchFiles: fs.existsSync(userPatch) ? [userPatch] : [],
  • 读取本地文件
    payload/host-boot.js:117
    if (fs.existsSync(engine)) {
  • 读取本地文件
    payload/host-boot.js:126
    if (!fs.existsSync(configFile)) {
  • 写入本地文件
    payload/host-boot.js:139
    fs.writeFileSync(configFile, body);
  • 读取本地文件
    payload/host-boot.js:142
    const current = fs.readFileSync(configFile, 'utf8');
  • 写入本地文件
    payload/host-boot.js:149
    fs.writeFileSync(configFile, rewritten);
  • 写入本地文件
    payload/host-boot.js:159
    try { fs.mkdirSync(dir, { recursive: true }); } catch (error) { log(`market: cannot create ${dir}: ${error.message}`); }
  • 写入本地文件
    payload/shims/fs-link.js:25
    fs.renameSync(existingPath, newPath);
  • 读取本地文件
    payload/shims/fs-symlink.js:19
    const stat = fs.lstatSync(source);
  • 写入本地文件
    payload/shims/fs-symlink.js:21
    fs.mkdirSync(target, { recursive: true });
  • 读取本地文件
    payload/shims/fs-symlink.js:22
    for (const entry of fs.readdirSync(source)) {
  • 写入本地文件
    payload/shims/fs-symlink.js:27
    fs.copyFileSync(source, target);
  • 读取本地文件
    payload/shims/s6-node-pty.js:44
    if (!fs.existsSync(native)) {
扫描于 2026/11/4(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
dsh-desktop-android DSH Desktop(Android 版) — 在 Android 上以「进程内 Node + 系统 WebView」运行 deepseek-harness(dsh)的桌面交付。 - 版本:0.1.0(versionCode 1)| 上游基线 dsh-v0.2.1-rc.2 | 引擎 libnode v24.22.1(small-icu) - 技术栈:Kotlin(View 体系)· 系统 WebView · 进程内 libnode.so(node::Start,JNI 槽位表桥)· dsh Host(HTTP + WebSocket) - 适配原则:上游零补丁 —— android profile + @dsh-android/bundle(三类 patch 操作)+ 带标记垫片/物化期补丁 + 自建 seam 插件(packages/-android) 运行模型 MainActivity(前台 UI) └─ DshRuntime:进程内启动 libnode → dsh Host(仅监听 127.0.0.1:<随机端口>) └─ WebShellView(WebView)→ 加载 http://127.0.0.1:<port>/?
展开完整文档(README 剩余 1 节)
dsh-desktop-android

DSH Desktop(Android 版) — 在 Android 上以「进程内 Node + 系统 WebView」运行 deepseek-harness(dsh)的桌面交付。

- 版本:0.1.0(versionCode 1)| 上游基线 dsh-v0.2.1-rc.2 | 引擎 libnode v24.22.1(small-icu)
- 技术栈:Kotlin(View 体系)· 系统 WebView · 进程内 libnode.so(node::Start,JNI 槽位表桥)· dsh Host(HTTP + WebSocket)
- 适配原则:上游零补丁 —— android profile + @dsh-android/bundle(三类 patch 操作)+ 带标记垫片/物化期补丁 + 自建 seam 插件(packages/-android)

运行模型

MainActivity(前台 UI) └─ DshRuntime:进程内启动 libnode → dsh Host(仅监听 127.0.0.1:<随机端口>) └─ WebShellView(WebView)→ 加载 http://127.0.0.1:<port>/?token=<一次性 token> └─ HostCapabilities:Kotlin↔Node 能力桥(冻结名 17 项,JSON 进出、handler 永不抛) └─ KeepAliveService:agent turn 运行期 dataSync 前台保活(结束即停)

快速开始

1. 载荷装配(物化上游 dsh 运行树 + 本工程 packages/ + bundle patch + 垫片)
node scripts/assemble-payload.mjs --deploy --apply
2. 打包载荷 → app/src/main/assets/dsh-payload/{dsh.tar,dsh.version}
node scripts/package-payload.mjs --src build/payload-stage/root
3. 引擎投放(libnode.so,锁 sha256,八项 ELF 门禁)
node scripts/provision-engine.mjs
4. 构建(full=侧载线含 All-files;store=SAF-only 线) ./gradlew assembleFullDebug # 模拟器/侧载调试 ./gradlew assembleFullRelease # 发布候选(需签名配置)
5. 部署 adb install -r app/build/outputs/apk/full/debug/app-full-debug.apk

环境前置(D.3 核对单):IANA 时区(GMT 偏移名会被拒绝)、Android 13+ 需 POST_NOTIFICATIONS、All-files 授权(文档/下载 tab)、arm64-v8a 引擎(x86_64 模拟器需 ARM 转译镜像)。详见 docs/安卓环境能力清单-v0.2.1.md §D.3。

支持下限 Android 8.0 / API 26(111 起 minSdk 29→26):All-files(文档/下载)仅 API 30+ 可用(26–29 诚实降级);通知运行时权限仅在 33+ 请求(<33 默认授予)。引擎/PTY/桥 AAR minSdk 24。

仓库结构

| 路径 | 内容 |
| app/ | Kotlin 外壳:DshRuntime(启动状态机)、WebShellView、host/HostCapabilities(能力桥)、host/KeepAliveService(保活)、host/PickDelegateActivity(SAF 两段式) |
| packages/ | Node 侧 seam 插件:bundle-android(patch)、subprocess-android(含进程内 rg 替身)、shell-android(哨兵协议 shell)、market-android(desktopPnpm 契约+lookup)、git-android(21 工具)、notify-android(通知+保活接线)、facts-android(/_android/facts,debug-only)、workspace-picker-android(+client)、open-in-app-android、attachment-image-android、branding-android(Web 品牌位:标题/侧栏/hero,官方 logo 几何)、sandbox-android |
| payload/ | 正式载荷入口:bootstrap.js(env 断言/垫片登记)+ host-boot.js + shims/(S1–S5) |
| profiles/android/ | android profile(bundle 引用、npmrc) |
| scripts/ | assemble-payload.mjs / package-payload.mjs / provision-engine.mjs |
| specs/ | 规格文档体系( Constitution C1–C14 + overall-* + 000/101–109/012/201–206 模块 spec/plan) |
| docs/ | 工程规划、P0 门禁报告、安卓环境能力清单(能力矩阵 42 项 + D.2 待办)、任务登记册(020) |
| logs/ | 执行轮日志与取证证据(<YYYYMMDD>-<N>/evidence/) |

关键文档

- docs/000-工程规划.md — 总体规划与实现状态
- docs/112-设置对话框响应式.md — 窄屏 UI 响应式(设置栏目 tabs 上移;左侧边栏浮动展开):@dsh-android/ui-responsive CSS 注入方案与验证
- docs/安卓环境能力清单-v0.2.1.md — 与 ark/hos 三路同表的能力矩阵、待办(§D.2)、门禁记录(§D.4)、任务登记册(§D.5 T-001…)
- specs/README.md — 规格索引;specs/constitution.md — C1–C14 宪法(诚实降级/零补丁/不伪造)

品牌化(2026-10-30):应用名 DSH Desktop;启动图标/圆形图标/通知小图标由 scripts/generate-brand-assets.py 从工作区 ../assets/logo.png(与 hos/ark 同源 #1296db 气泡)生成五密度 mipmap;Web 品牌位 @dsh-android/branding(移植 branding-ohos:页面标题 + sidebar/hero 三槽位 + 标题守卫,上游零补丁)。

已实证能力速览(2026-10-29)

对话与图片分析 ✅ | bash 端到端 ✅ | git clone/push(http(s))✅ | 通知(回合完成/审批)✅ | Documents/Download 写入 ✅ | /_android/facts(debug)✅ | AgentKeepAlive 生命周期 ✅ | grep/glob(进程内 rg 替身)✅(本仓库实现)| PTY 终端 ✅(node-pty:26.13.0,右侧栏真机实证 2026-11-01) | 真机复测(MIX/Android 8.0,minSdk 26)✅ 本轮(2026-11-01)
预览分享卡片长什么样 ↓fellow99/dsh-desktop-android
分享 · DeepSeek Harness Hub
fellow99/dsh-desktop-android

在 Android 手机上运行完整 dsh Web 界面

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部