在桌面端运行 dsh 引擎,管理会话与凭证
29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/18 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查未通过:仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Oissp/dsh-desktop该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · desktop
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 46 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装仓库 package.json 标记 private,未发布到 npm,需从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-desktop @ 0.2.0
✓Node 引擎要求 >=22.19.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖要求 0.2.1-rc.2 · 最新 0.2.1-rc.2 兼容
✓入口文件main/exports/bin 已声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/20 04:29:30
🔴 安全扫描发现高危能力自动 · 静态分析源码
v2.7.0🔴 扫描:高危尚无人工评估
静态扫描发现安装期即执行代码,或命令参数由运行时变量拼接(参数来源无法静态判定,从严处理)。
安装时即执行脚本命令参数由运行时变量拼接读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 124 处,展示前 106 条)
- 读取本地文件scripts/ensure-electron.mjs:29
if (!existsSync(electronDir)) { - 读取本地文件scripts/ensure-electron.mjs:37
if (existsSync(bin)) { - 执行外部命令来自配置/变量scripts/ensure-electron.mjs:48
const res = spawnSync(process.execPath, [installScript], { - 读取本地文件scripts/ensure-electron.mjs:53
if (res.status === 0 && existsSync(bin)) { - 发起网络请求adapter/dsh-client.ts:139
await this.request('session/modelCatalog', {}) - 发起网络请求adapter/dsh-client.ts:193
return this.request('session/list', { _request: {} }) - 发起网络请求adapter/dsh-client.ts:197
return this.request('session/create', { request: payload }) - 发起网络请求adapter/dsh-client.ts:201
return this.request('session/prompt', { - 发起网络请求adapter/dsh-client.ts:207
return this.request('session/cancel', { request: payload }) - 发起网络请求adapter/dsh-client.ts:216
return this.request('session/modelCatalog', {}) - 写入本地文件electron/crash-report.ts:210
mkdirSync(directory, { recursive: true }) - 写入本地文件electron/crash-report.ts:213
writeFile(path, content, { encoding: 'utf8', mode: 0o600 }), - 读取本地文件electron/crash-report.ts:252
names = readdirSync(directory).filter((n) => CRASH_REPORT_NAME.test(n)) - 删除本地文件electron/crash-report.ts:261
unlinkSync(join(directory, name)) - 读取本地文件electron/credential-store.ts:22
if (!existsSync(file)) return {} - 读取本地文件electron/credential-store.ts:23
const parsed = JSON.parse(readFileSync(file, 'utf8')) as Record<string, unknown> - 写入本地文件electron/credential-store.ts:36
mkdirSync(dirname(file), { recursive: true }) - 写入本地文件electron/credential-store.ts:37
writeFileSync(file, `${JSON.stringify(map, null, 2)}\n`, 'utf8') - 读取本地文件electron/dsh-manager.ts:42
if (existsSync(c)) return c - 读取本地文件electron/dsh-manager.ts:54
const pkg = JSON.parse(readFileSync(join(pkgRoot, 'package.json'), 'utf8')) as { version?: string } - 执行外部命令表达式求值electron/dsh-manager.ts:232
private async spawn(): Promise<void> { - 执行外部命令来自配置/变量electron/dsh-manager.ts:245
const child = spawn(exec, args, { - 写入本地文件electron/guard-snapshot.ts:38
mkdirSync(dir, { recursive: true }) - 读取本地文件electron/guard-snapshot.ts:49
if (existsSync(src)) { - 读取本地文件electron/guard-snapshot.ts:58
for (const f of readdirSync(dir)) { - 删除本地文件递归electron/guard-snapshot.ts:59
rmSync(join(dir, f), { force: true, recursive: true }) - 读取本地文件electron/guard-snapshot.ts:93
const files = existsSync(lastGood) ? readdirSync(lastGood) : [] - 读取本地文件electron/guard-snapshot.ts:93
const files = existsSync(lastGood) ? readdirSync(lastGood) : [] - 写入本地文件electron/guard-snapshot.ts:104
mkdirSync(join(dest, '..'), { recursive: true }) - 读取本地文件electron/guard-snapshot.ts:128
if (!existsSync(filePath)) return false - 读取本地文件electron/guard-snapshot.ts:131
const content = readFileSync(filePath, 'utf8') - 写入本地文件electron/guard-snapshot.ts:148
writeFileSync(filePath, rebuilt, 'utf8') - 读取本地文件electron/log-sink.ts:64
if (existsSync(dir)) { - 读取本地文件electron/log-sink.ts:65
const st = lstatSync(dir) - 写入本地文件electron/log-sink.ts:68
mkdirSync(dir, { recursive: true, mode: 0o700 }) - 写入本地文件electron/log-sink.ts:70
mkdirSync(dir, { recursive: true, mode: 0o700 }) - 读取本地文件electron/log-sink.ts:97
for (const f of readdirSync(this.dir)) { - 删除本地文件electron/log-sink.ts:100
unlinkSync(join(this.dir, f)) - 写入本地文件electron/log-sink.ts:119
appendFileSync(path, line, { mode: 0o600 }) - 读取本地文件electron/log-sink.ts:154
for (const f of readdirSync(this.dir)) { - 读取本地文件electron/log-sink.ts:171
const files = readdirSync(this.dir) - 读取本地文件electron/log-sink.ts:175
return { name: f, path: p, mtime: statSync(p).mtimeMs } - 删除本地文件electron/log-sink.ts:182
unlinkSync(f.path) - 删除本地文件electron/log-sink.ts:203
unlinkSync(p) - 执行外部命令固定命令electron/node-runtime.ts:25
const out = execFileSync('where', [cmd], { encoding: 'utf8' }).split('\n')[0]?.trim() - 执行外部命令固定命令electron/node-runtime.ts:32
const out = execFileSync('sh', ['-c', `command -v ${cmd}`], { encoding: 'utf8' }).trim() - 读取本地文件electron/node-runtime.ts:59
if (fromNpm && existsSync(fromNpm)) { - 读取本地文件electron/node-runtime.ts:66
if (existsSync(bundled)) { - 读取本地文件electron/profile-setup.ts:73
return existsSync(join(pluginTargetDir(dshHome, name), DESKTOP_MANAGED_MARKER)) - 读取本地文件electron/profile-setup.ts:79
if (!existsSync(join(src, 'index.js'))) { - 写入本地文件electron/profile-setup.ts:85
mkdirSync(join(target, '..'), { recursive: true }) - 写入本地文件electron/profile-setup.ts:88
writeFileSync(join(target, DESKTOP_MANAGED_MARKER), 'desktop-managed\n') - 读取本地文件electron/profile-setup.ts:90
if (existsSync(manifestPath)) { - 读取本地文件electron/profile-setup.ts:91
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) - 写入本地文件electron/profile-setup.ts:96
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8') - 读取本地文件electron/profile-setup.ts:110
if (!existsSync(manifestPath)) { - 读取本地文件electron/profile-setup.ts:148
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) - 写入本地文件electron/profile-setup.ts:156
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8') - 删除本地文件递归electron/profile-setup.ts:158
rmSync(pluginTargetDir(dshHome, name), { recursive: true, force: true }) - 读取本地文件electron/settings-store.ts:34
if (!existsSync(this.file)) return {} - 读取本地文件electron/settings-store.ts:37
raw = readFileSync(this.file, 'utf8') - 写入本地文件electron/settings-store.ts:48
renameSync(this.file, broken) - 写入本地文件electron/settings-store.ts:59
mkdirSync(dirname(this.file), { recursive: true }) - 写入本地文件electron/settings-store.ts:60
writeFileSync(this.file, JSON.stringify(this.settings, null, 2), 'utf8') - 写入剪贴板electron/update-lifecycle.ts:289
clipboard.writeText(debPath ? `sudo dpkg -i "${debPath}"` : 'sudo dpkg -i <下载的 .deb 路径>') - 读取本地文件electron/update-lifecycle.ts:299
if (!existsSync(pending)) return null - 读取本地文件electron/update-lifecycle.ts:300
const debs = readdirSync(pending).filter((f) => f.endsWith('.deb')) - 读取本地文件electron/update-lifecycle.ts:303
debs.sort((a, b) => statSync(join(pending, b)).mtimeMs - statSync(join(pending, a)).mtimeMs) - 读取本地文件electron/update-state.ts:40
if (!existsSync(this.file)) return {} - 读取本地文件electron/update-state.ts:42
const raw = readFileSync(this.file, 'utf8') - 写入本地文件electron/update-state.ts:54
mkdirSync(dirname(this.file), { recursive: true, mode: 0o700 }) - 写入本地文件electron/update-state.ts:56
writeFileSync(tmp, JSON.stringify(this.data), { mode: 0o600 }) - 写入本地文件electron/update-state.ts:57
renameSync(tmp, this.file) - 读取本地文件scripts/after-pack.mjs:32
if (existsSync(nativeBin)) { - 执行外部命令固定命令scripts/after-pack.mjs:42
execFileSync('npm', ['pack', `${scoped}/${pkgName}`, '--pack-destination', projectRoot], { - 读取本地文件scripts/after-pack.mjs:49
const tgzFile = readdirSync(projectRoot).find((f) => f.includes(pkgName) && f.endsWith('.tgz')) - 删除本地文件递归scripts/after-pack.mjs:54
rmSync(tmpDir, { recursive: true, force: true }) - 写入本地文件scripts/after-pack.mjs:55
mkdirSync(tmpDir, { recursive: true }) - 执行外部命令固定命令scripts/after-pack.mjs:56
execFileSync('tar', ['-xzf', tgz, '-C', tmpDir], { cwd: projectRoot, stdio: 'inherit' }) - 读取本地文件scripts/after-pack.mjs:58
if (!existsSync(unpacked)) throw new Error('tarball 无 package/ 目录') - 写入本地文件scripts/after-pack.mjs:59
mkdirSync(scopedDir, { recursive: true }) - 删除本地文件递归scripts/after-pack.mjs:60
rmSync(pkgDir, { recursive: true, force: true }) - 删除本地文件递归scripts/after-pack.mjs:62
rmSync(tmpDir, { recursive: true, force: true }) - 删除本地文件scripts/after-pack.mjs:63
rmSync(tgz, { force: true }) - 读取本地文件scripts/after-pack.mjs:64
if (!existsSync(nativeBin)) { - 读取本地文件scripts/after-pack.mjs:77
const pkg = JSON.parse(readFileSync(join(projectRoot, 'package.json'), 'utf8')) - 执行外部命令固定命令scripts/after-pack.mjs:110
const all = spawnSync('pnpm', ['list', '--json', '--depth', 'Infinity'], opts) - 执行外部命令固定命令scripts/after-pack.mjs:111
const prod = spawnSync('pnpm', ['list', '--prod', '--json', '--depth', 'Infinity'], opts) - 读取本地文件scripts/after-pack.mjs:227
if (!existsSync(src)) { - 删除本地文件递归scripts/after-pack.mjs:250
rmSync(dest, { recursive: true, force: true }) - 读取本地文件scripts/smoke-test.mjs:32
if (!existsSync(executable)) { - 删除本地文件递归scripts/smoke-test.mjs:40
rmSync(tmpHome, { recursive: true, force: true }) - 读取本地文件scripts/smoke-test.mjs:43
if (!existsSync(mainJs)) { - 读取本地文件scripts/smoke-test.mjs:50
if (!existsSync(join(nmRoot, dep))) { - 读取本地文件scripts/smoke-test.mjs:62
if (!existsSync(pkgDir)) { - 读取本地文件scripts/smoke-test.mjs:64
} else if (!bin || !existsSync(bin)) { - 读取本地文件scripts/smoke-test.mjs:74
if (!existsSync(bundledNode)) { - 执行外部命令来自配置/变量scripts/smoke-test.mjs:77
const ver = spawnSync(bundledNode, ['--version'], { encoding: 'utf8' }) - 执行外部命令来自配置/变量scripts/smoke-test.mjs:102
const child = spawn(executable, ['--no-sandbox', '--disable-gpu'], { - 删除本地文件递归scripts/smoke-test.mjs:196
rmSync(tmpHome, { recursive: true, force: true }) - 读取本地文件scripts/verify-deb.mjs:22
?? readdirSync('out').map((f) => `out/${f}`).filter((f) => f.endsWith('.deb')).sort()[0] - 执行外部命令固定命令scripts/verify-deb.mjs:49
const res = spawnSync( - 读取本地文件scripts/verify-deb.mjs:58
console.log(`\n[verify-deb] 校验 ${deb}(${(statSync(deb).size / 1024 / 1024).toFixed(1)} MB)`) - 执行外部命令固定命令scripts/verify-deb.mjs:83
const res = spawnSync('dpkg-deb', ['-c', deb], { - 读取本地文件scripts/verify-deb.mjs:189
const pkgMeta = JSON.parse(readFileSync(join(process.cwd(), 'package.json'), 'utf8')) - 发起网络请求shared/fetch-timeout.ts:13
return await fetch(url, { ...init, signal: ctrl.signal })
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 桌面端运行引擎
- 管理会话
- 管理凭证
README
由 DeepSeek 最新模型翻译生成DSH Desktop
DSH Desktop 是 DeepSeek Harness 的桌面客户端(Debian / macOS)。应用内置 dsh 引擎,启动后直接加载官方 Web UI;Electron 负责本地运行时、凭证保护、托盘、自动更新和桌面扩展。
非 DeepSeek 官方产品,与 DeepSeek 无附属关系。
功能
- 内置 dsh 引擎,首次初始化后可直接使用
- 官方 Web UI,支持流式回复、思考过程、工作区、模型和会话管理
- 首启向导配置工作区与模型凭证;引擎崩溃进入恢复模式,可回滚配置快照重启
- 归档会话查看(官方插件面板 plugins/dsh-desktop-archived,标题由桌面侧快照兜底)
- 凭证通过 Electron safeStorage 加密保存;启用 CSP、导航限制和单实例锁
- 崩溃环检测 + 配置快照恢复、落盘日志
- 托盘常驻、后台更新检查和下载后安装
- 发布 Debian 13 / amd64 .deb 与 macOS(arm64).dmg / .zip 安装包
安装
从项目的 GitHub Releases 下载对应平台的安装包:
- Debian 13 / amd64:dsh-desktop__amd64.deb,然后执行:
展开完整文档(README 剩余 1 节)
DSH Desktop DSH Desktop 是 DeepSeek Harness 的桌面客户端(Debian / macOS)。应用内置 dsh 引擎,启动后直接加载官方 Web UI;Electron 负责本地运行时、凭证保护、托盘、自动更新和桌面扩展。 非 DeepSeek 官方产品,与 DeepSeek 无附属关系。 功能 - 内置 dsh 引擎,首次初始化后可直接使用 - 官方 Web UI,支持流式回复、思考过程、工作区、模型和会话管理 - 首启向导配置工作区与模型凭证;引擎崩溃进入恢复模式,可回滚配置快照重启 - 归档会话查看(官方插件面板 plugins/dsh-desktop-archived,标题由桌面侧快照兜底) - 凭证通过 Electron safeStorage 加密保存;启用 CSP、导航限制和单实例锁 - 崩溃环检测 + 配置快照恢复、落盘日志 - 托盘常驻、后台更新检查和下载后安装 - 发布 Debian 13 / amd64 .deb 与 macOS(arm64).dmg / .zip 安装包 安装 从项目的 GitHub Releases 下载对应平台的安装包: - Debian 13 / amd64:dsh-desktop__amd64.deb,然后执行: sudo apt install ./dsh-desktop__amd64.deb - macOS(arm64 / Apple Silicon):dsh-desktop--arm64.dmg,打开后把应用拖入 Applications。 首次启动会初始化 dsh Web profile,时间取决于本机网络与依赖缓存。随后在首启向导中配置模型凭证。 开发 要求:Node.js >=22.19.0、pnpm >=9。项目使用 pnpm 11;推荐通过 Corepack 管理。 corepack enable pnpm install pnpm dev 常用命令: pnpm typecheck # 检查 renderer 与 Electron 两个 TypeScript 项目 pnpm test # 运行 Vitest pnpm build # 构建 renderer 与 Electron 主进程 pnpm dist # 构建 Debian amd64 .deb 到 out/ pnpm dist:mac # 构建 macOS dmg + zip 到 out/(需在 macOS 上执行) pnpm dev 会启动 Vite(5173)与 Electron。正式应用界面由本地 dsh Web 服务提供;Vite 页面用于启动、首启向导和引擎故障回退。 架构 React fallback UI (src/) -> preload -> IPC -> Electron main -> adapter -> dsh web engine - adapter/:dsh Typert Remote 协议适配(HTTP RPC + WebSocket mux)与事件归一化 - shared/:renderer 与主进程共享的稳定类型和 IPC 契约 - electron/:引擎生命周期、IPC、凭证、profile、托盘、更新和桌面桥接 - src/:React 回退 UI(启动、首启向导、恢复页与引擎就绪过渡占位) - plugins/:注入官方引擎 UI 的伴随插件(归档会话面板) - scripts/:打包钩子、校验脚本、原生模块定义 License MIT
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Oissp/dsh-desktop
在桌面端运行 dsh 引擎,管理会话与凭证
相关插件 · 桌面端
Codex 任务面板chuspeeism/dashi-taskboard
现代化可灵活嵌入的任务面板,支持 Codex、DeepSeek Harness
★ 3,409已汉化DSH
71.7
多智能体自进化开发平台Prism-Shadow/penguin-harness
统一、稳定的 Agent 自进化框架全自动优化:任意模型 · 任意算法 · 任意 Benchmark
★ 3,111已汉化DSH
71.1
桌面宠物PC2005-cloud/dsh-pet
DSH 桌面宠物:一行命令装好即用的透明动画小桌宠,支持多开、大小位置随心配置;还内置 DIY 素材链,能用 AI…
★ 5,341已汉化DSH
71
多端 Agent 工作台GCWing/OpenBitFun
OpenBitFun 是一个高度可定制的开源 Agent 工作台,让任务按你的方式持续推进。
★ 3,449已汉化DSH
70.8
DSH Desktopanywhere-labs/dsh-desktop
为 DeepSeek Harness DSH 插件生态打造的现代化桌面端解决方案。万物皆「插件」,桌面本身也是「插件」。
★ 34,532已汉化DSH
70.7
桌面宠物伴侣OpenPetsHQ/openpets
桌面伴侣平台,带宠物、插件,还能选配本地智能体集成。
★ 1,353已汉化DSH
70.2
这是你的仓库?认领条目