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

桌面工作台 yansenlei/dsh-desktop

DeepSeek Harnessv0.2.0
yansenlei74 天前有提交已提供中文文档扫描:含敏感能力

双击安装即可在电脑上使用 AI 助手,无需命令行

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

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

自动兼容检查未通过:仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add yansenlei/dsh-desktop
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

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

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

验证判据与等级说明 →

可信度证据

安装兼容性检查需源码安装

仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

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

✓npm 包dsh-desktop @ 0.2.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

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

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/24 11:30:51

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 99 处,展示前 88 条)
  • 发起网络请求
    plugins/plugin-market/lib/index.js:21
    const res = await fetch(`${NPM_SEARCH}?text=${encodeURIComponent(query)}&size=${size}`, {
  • 读取本地文件
    plugins/plugin-market/lib/index.js:70
    const pkg = JSON.parse(readFileSync(`${home}/profiles/web/package.json`, "utf8"));
  • 读取本地文件
    plugins/plugin-market/lib/index.js:136
    const list = JSON.parse(readFileSync(`${home}/plugin-market.json`, "utf8"));
  • 读取本地文件
    plugins/plugin-market/lib/index.js:147
    const pkg = JSON.parse(readFileSync(`${profileDir}/node_modules/${name}/package.json`, "utf8"));
  • 执行外部命令固定命令
    plugins/telegram-bridge/lib/index.js:42
    const enabled = execFileSync(
  • 执行外部命令固定命令
    plugins/telegram-bridge/lib/index.js:48
    const srv = execFileSync(
  • 执行外部命令固定命令
    plugins/telegram-bridge/lib/index.js:62
    const out = execFileSync("scutil", ["--proxy"], { encoding: "utf8" });
  • 读取本地文件
    plugins/telegram-bridge/lib/index.js:80
    if (existsSync(configPath())) {
  • 读取本地文件
    plugins/telegram-bridge/lib/index.js:81
    return JSON.parse(readFileSync(configPath(), "utf8"));
  • 写入本地文件
    plugins/telegram-bridge/lib/index.js:92
    mkdirSync(process.env.DSH_HOME ?? ".", { recursive: true });
  • 写入本地文件
    plugins/telegram-bridge/lib/index.js:93
    writeFileSync(configPath(), JSON.stringify(next, null, 2), "utf8");
  • 发起网络请求
    plugins/telegram-bridge/lib/index.js:120
    return proxyUrl ? new ProxyAgent(proxyUrl) : null;
  • 发起网络请求
    plugins/telegram-bridge/lib/index.js:127
    const res = await ufetch(`${API}${token}/${method}`, {
  • 读取本地文件
    plugins/telegram-bridge/lib/index.js:197
    readFileSync(join(process.env.DSH_HOME ?? ".", "storages", "workspace.json"), "utf8"),
  • 读取本地文件
    plugins/telegram-bridge/lib/index.js:200
    if (first?.path && existsSync(first.path)) return first.path;
  • 读取本地文件
    plugins/telegram-bridge/lib/index.js:229
    const buf = zstdDecompressSync(readFileSync(join(dir, "session.jsonl.zstd")));
  • 读取本地文件
    plugins/telegram-bridge/lib/index.js:430
    readFileSync(join(process.env.DSH_HOME ?? ".", "storages", "session_projcache.json"), "utf8"),
  • 执行外部命令来自配置/变量
    src/main/deps.ts:37
    const child = spawn(cmd, args, {
  • 读取本地文件
    src/main/deps.ts:82
    if (existsSync(framework)) {
  • 读取本地文件
    src/main/deps.ts:84
    for (const v of readdirSync(framework)) {
  • 读取本地文件
    src/main/deps.ts:86
    if (existsSync(exe)) return { version: `Python ${v}`, path: exe, source: exe };
  • 读取本地文件
    src/main/deps.ts:94
    if (existsSync(exe)) {
  • 读取本地文件
    src/main/deps.ts:111
    if (!existsSync(root)) continue;
  • 读取本地文件
    src/main/deps.ts:114
    dirs = readdirSync(root);
  • 执行外部命令来自配置/变量
    src/main/deps.ts:184
    const child = spawn(cmd, args, {
  • 发起网络请求
    src/main/deps.ts:252
    const res = await fetch(PYTHON_INSTALLER_URL);
  • 写入本地文件
    src/main/index.ts:24
    appendFileSync(p, `${new Date().toISOString()} ${msg}\n`);
  • 读取本地文件
    src/main/index.ts:260
    return JSON.parse(readFileSync(autoCheckStatePath, "utf8")) as AutoCheckState;
  • 写入本地文件
    src/main/index.ts:268
    writeFileSync(autoCheckStatePath, JSON.stringify(st, null, 2), "utf8");
  • 读取本地文件
    src/main/index.ts:443
    const raw = readFileSync(join(userDataDir, "window.json"), "utf8");
  • 写入本地文件
    src/main/index.ts:455
    writeFileSync(join(userDataDir, "window.json"), JSON.stringify(mainWindow.getBounds()), "utf8");
  • 读取本地文件
    src/main/index.ts:492
    if (existsSync(join(packaged, "dsh", "node_modules", "@deepseek-ai", "dsh", "package.json"))) {
  • 读取本地文件
    src/main/index.ts:505
    if (existsSync(c)) return c;
  • 读取本地文件
    src/main/index.ts:514
    if (existsSync(pkgPath)) {
  • 读取本地文件
    src/main/index.ts:515
    dshVersion = JSON.parse(readFileSync(pkgPath, "utf8")).version ?? null;
  • 发起网络请求
    src/main/index.ts:562
    const res = await fetch(status.url, { signal: AbortSignal.timeout(10_000) });
  • 写入本地文件
    src/main/index.ts:585
    writeFileSync(smokeOut, JSON.stringify(result, null, 2), "utf8");
  • 发起网络请求
    src/main/ipc.ts:87
    const res = await fetch(url, {
  • 发起网络请求
    src/main/ipc.ts:172
    const res = await fetch(url, { signal: ctl });
  • 写入本地文件
    src/main/ipc.ts:176
    const writer = createWriteStream(dest);
  • 请求外部主机registry.npmjs.org
    src/main/ipc.ts:242
    const res = await fetch("https://registry.npmjs.org/@deepseek-ai/dsh", {
  • 发起网络请求
    src/main/ipc.ts:242
    const res = await fetch("https://registry.npmjs.org/@deepseek-ai/dsh", {
  • 写入本地文件
    src/main/ipc.ts:278
    writeFileSync(join(dshHome, "plugin-market.json"), JSON.stringify(list, null, 2), "utf8");
  • 写入本地文件
    src/main/ipc.ts:294
    writeFileSync(p, JSON.stringify(pkg, null, 2) + "\n", "utf8");
  • 读取本地文件
    src/main/ipc.ts:300
    return JSON.parse(readFileSync(p, "utf8"));
  • 写入本地文件
    src/main/ipc.ts:313
    writeFileSync(join(runtimeDir, "dsh", ".dsh-runtime.json"), JSON.stringify(marker, null, 2), "utf8");
  • 写入本地文件
    src/main/ipc.ts:344
    writeFileSync(enginePersistPath(userDataDir), JSON.stringify(rec, null, 2), "utf8");
  • 读取本地文件
    src/main/ipc.ts:397
    return existsSync(npmCliPath(runtimeDir));
  • 执行外部命令来自配置/变量
    src/main/ipc.ts:405
    const child = spawn(process.execPath, [cli, "--cache", cache, ...args], {
  • 删除本地文件递归
    src/main/ipc.ts:454
    rmSync(pluginsDir, { recursive: true, force: true });
  • 读取本地文件
    src/main/ipc.ts:455
    if (existsSync(pluginsBak)) cpSync(pluginsBak, pluginsDir, { recursive: true });
  • 读取本地文件
    src/main/ipc.ts:460
    if (existsSync(pluginsDir)) {
  • 删除本地文件递归
    src/main/ipc.ts:461
    rmSync(pluginsBak, { recursive: true, force: true });
  • 读取本地文件
    src/main/ipc.ts:482
    if (koffiVer && !existsSync(join(koromixDir, `koffi-darwin-${arch}`))) platPkgs.push(`@koromix/koffi-darwin-${arch}@${koffiVer}`);
  • 读取本地文件
    src/main/ipc.ts:483
    if (!existsSync(join(imgDir, `sharp-darwin-${arch}`))) platPkgs.push(`@img/sharp-darwin-${arch}`);
  • 执行外部命令固定命令
    src/main/ipc.ts:510
    spawnSync("codesign", ["--force", "--deep", "--sign", "-", appRoot], { stdio: "ignore" });
  • 执行外部命令固定命令
    src/main/ipc.ts:511
    spawnSync("xattr", ["-dr", "com.apple.quarantine", appRoot], { stdio: "ignore" });
  • 写入本地文件
    src/main/ipc.ts:682
    await mkdir(destDir, { recursive: true });
  • 删除本地文件
    src/main/ipc.ts:684
    await rm(dest, { force: true });
  • 执行外部命令固定命令
    src/main/ipc.ts:785
    const child = spawn("/bin/sh", [script], { detached: true, stdio: "ignore" });
  • 执行外部命令来自配置/变量
    src/main/ipc.ts:800
    const child = spawn(installer, ["/S"], {
  • 写入本地文件
    src/main/logger.ts:20
    mkdirSync(dir, { recursive: true });
  • 读取本地文件
    src/main/logger.ts:25
    if (!existsSync(logFile)) return;
  • 读取本地文件
    src/main/logger.ts:28
    size = statSync(logFile).size;
  • 读取本地文件
    src/main/logger.ts:37
    if (existsSync(from)) {
  • 写入本地文件
    src/main/logger.ts:39
    renameSync(from, to);
  • 写入本地文件
    src/main/logger.ts:46
    renameSync(logFile, `${logFile}.1`);
  • 写入本地文件
    src/main/logger.ts:67
    appendFileSync(logFile, line + "\n");
  • 写入本地文件
    src/main/server.ts:27
    appendFileSync(p, `${new Date().toISOString()} ${msg}\n`);
  • 读取本地文件
    src/main/server.ts:126
    if (!existsSync(binPath)) {
  • 执行外部命令来自配置/变量
    src/main/server.ts:154
    child = spawn(this.opts.execPath, ["--expose-internals", binPath, "web", "--patch", patchPath, "--port", String(port)], {
  • 发起网络请求
    src/main/server.ts:229
    const res = await fetch(url, { signal: controller.signal });
  • 读取本地文件
    src/main/server.ts:279
    if (existsSync(listPath)) {
  • 读取本地文件
    src/main/server.ts:280
    const list = JSON.parse(readFileSync(listPath, "utf8")) as { plugins?: unknown };
  • 写入本地文件
    src/main/server.ts:294
    mkdirSync(dirname(patchPath), { recursive: true });
  • 写入本地文件
    src/main/server.ts:295
    writeFileSync(patchPath, lines.join("\n") + "\n", "utf8");
  • 读取本地文件
    src/main/server.ts:321
    if (!existsSync(target)) {
  • 读取本地文件
    src/main/server.ts:326
    const st = lstatSync(link);
  • 删除本地文件
    src/main/server.ts:334
    unlinkSync(link);
  • 删除本地文件递归
    src/main/server.ts:336
    rmSync(link, { recursive: true, force: true });
  • 删除本地文件递归
    src/main/server.ts:339
    rmSync(link, { recursive: true, force: true });
  • 写入本地文件
    src/main/server.ts:344
    mkdirSync(dirname(link), { recursive: true });
  • 读取本地文件
    src/main/server.ts:369
    const size = statSync(logPath).size;
  • 执行外部命令固定命令
    src/main/server.ts:443
    spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
  • 读取本地文件
    src/main/settings.ts:24
    if (existsSync(settingsPath)) {
  • 读取本地文件
    src/main/settings.ts:26
    const raw = JSON.parse(readFileSync(settingsPath, "utf8"));
  • 写入本地文件
    src/main/settings.ts:53
    mkdirSync(join(settingsPath, ".."), { recursive: true });
  • 写入本地文件
    src/main/settings.ts:54
    writeFileSync(settingsPath, JSON.stringify(cache, null, 2), "utf8");
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
涉及外部主机:registry.npmjs.org

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

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

功能亮点

  • 一键安装
  • 开箱即用
  • 本地AI助手工作台

README

由 DeepSeek 最新模型翻译生成
DeepSeek Harness Desktop(DeepSeek Harness 桌面版) DeepSeek Harness Desktop 面向非技术用户的 DeepSeek Harness 一键安装 + 桌面客户端。 目标:让没有技术背景的用户也能 30 秒装好并用上 DeepSeek Harness —— 无需安装 Node.js、无需命令行、无需理解「服务」「端口」这些概念。 仓库:github.com/yansenlei/dsh-desktop 下载: - 🖥️ 下载页面(推荐):yansenlei.github.io/dsh-desktop —— 自动识别系统、macOS 区分 Apple Silicon / Intel,内置安装指引与常见问题 - 📦 GitHub Releases:最新版(应用内「设置 → 检查更新」以此为更新源,链接始终指向最新发布,无需维护版本号) 默认内置插件,两种"用手机操作电脑"的方式 - 📱 扫码局域网(lan-access):在家里,手机连上同一 Wi-Fi,扫一下二维码就能操作你的电脑。 - 📱 扫码 Telegram(telegram-bridge):没在家的时候,在自己的 Telegram 里跟机器人对话,随时操作你的电脑。
展开完整文档(README 剩余 1 节)
DeepSeek Harness Desktop(DeepSeek Harness 桌面版)

DeepSeek Harness Desktop

面向非技术用户的 DeepSeek Harness 一键安装 + 桌面客户端。

目标:让没有技术背景的用户也能 30 秒装好并用上 DeepSeek Harness —— 无需安装 Node.js、无需命令行、无需理解「服务」「端口」这些概念。

仓库:github.com/yansenlei/dsh-desktop

下载:
- 🖥️ 下载页面(推荐):yansenlei.github.io/dsh-desktop —— 自动识别系统、macOS 区分 Apple Silicon / Intel,内置安装指引与常见问题
- 📦 GitHub Releases:最新版(应用内「设置 → 检查更新」以此为更新源,链接始终指向最新发布,无需维护版本号)

默认内置插件,两种"用手机操作电脑"的方式

- 📱 扫码局域网(lan-access):在家里,手机连上同一 Wi-Fi,扫一下二维码就能操作你的电脑。
- 📱 扫码 Telegram(telegram-bridge):没在家的时候,在自己的 Telegram 里跟机器人对话,随时操作你的电脑。

插件源码独立开源,也可单独安装到任意 DSH 环境:npx dsh-plugin-lan-access / npx dsh-plugin-telegram-bridge(见 dsh-plugin-lan-access / dsh-plugin-telegram-bridge)。

插件市场:更多 DSH 插件,一键装好

「设置 → 插件 → 搜索安装」:搜索全网 npm 上的 DSH 插件,一键安装(也支持按包名安装、拖入 .tgz 安装包),装好的插件可在「我的插件」里随时禁用 / 启用 / 卸载,全程无需命令行。

产品特性

- 一键安装:NSIS 安装包,双击 → 安装 → 自动启动,桌面/开始菜单快捷方式、卸载器齐全。
- 免装 Node.js:应用自带 Electron(含 Node 24 运行时),DSH 服务在应用内以子进程运行,用户机器完全不需要安装 Node.js。
- 内置 DSH 运行时:DSH 引擎(@deepseek-ai/dsh)与其全部依赖随安装包分发,离线可用(引擎版本以发布包为准,可在设置页「关于」中查看)。
- 桌面壳体验:暗黑科技风品牌启动页(旋转光环 logo + 启动进度 + 运行日志)→ 自动载入 Harness 工作台;系统托盘常驻(状态、打开/重启/设置/退出)。
- 📱 扫码局域网(在家):内置 lan-access 插件。手机连上家里/办公室的同一 Wi-Fi,扫 Harness 侧边栏「手机访问」的二维码,就能在手机上打开你的电脑工作台——躺着也能让 AI 干活。桌面端「设置 → 局域网访问」一键开关(默认关闭,仅本机访问,开启才向局域网开放,见下文安全说明)。
- 📱 扫码 Telegram(出门在外):内置 telegram-bridge 插件。在自己的 Telegram 里加机器人(扫码直达),随时发消息让 AI 操作你的电脑——人不在电脑前,活照干。与浏览器工作台共用同一会话,聊天记录同步。
- 🧩 插件市场(搜索安装):设置 → 插件 →「搜索安装」搜索全网 DSH 插件、一键安装(也支持按包名安装、拖入 .tgz),「我的插件」里可禁用 / 启用 / 卸载已装插件。
- 环境一键补齐:可选组件自动检测与一键安装 —— Python(winget 优先,回退官方安装包)、dsh 命令行工具(自动装 Node LTS + 全局 dsh)。
- 数据自包含:会话、配置、存储都放在应用数据目录,卸载不丢失;端口冲突自动顺延。
- 跨平台:Windows(NSIS 安装器)与 macOS(dmg/zip,x64 + Apple Silicon)均已适配;macOS 构建见 docs/BUILD_MAC.md。
- i18n:壳 UI 与主进程文案支持中/英文,设置页可切换语言。
- 可靠性:服务崩溃自动重启(带退避)、启动超时检测、日志文件轮转、单实例锁、窗口状态记忆。

技术架构

┌────────────────────── Electron 41(Chromium 146 + Node 24)─────────────┐ │ main 进程 │ │ ├─ 窗口/托盘/生命周期 ── 壳 UI(本地 HTML:启动页 / 设置页) │ │ ├─ IPC 桥(contextBridge, sandbox 渲染进程) │ │ └─ DshServerManager:spawn dsh web 子进程(ELECTRON_RUN_AS_NODE) │ │ ├─ 端口探测(默认 3080,被占顺延) │ │ ├─ 健康轮询(HTTP 200 → ready) │ │ ├─ 崩溃自动重启(≤3 次,退避 2s) │ │ └─ 局域网访问:生成 patch(host=0.0.0.0)+ 插件 junction 链接 │ ├─ resources/dsh-runtime/:@deepseek-ai/dsh + 依赖 + lan-access 插件 │ ├─ 内置插件 @dsh-desktop/lan-access(局域网二维码) │ │ ├─ node half:注册 /lan-info(返回局域网 IP/URL/开关状态) │ │ └─ client half:侧边栏「手机访问」按钮 + 二维码面板(qrcode 打包) │ └─ 子进程:dsh web(Node 24 · DSH_HOME=userData/dsh-home · 端口动态) │ └─ http://127.0.0.1: → BrowserWindow 加载 Harness UI │

- 服务与壳隔离:Harness 服务是独立子进程,崩溃不影响应用壳,可随时重启。
- 无外部依赖启动:Electron 内置 Node 24 满足 DSH rc.6 的要求(zstd / type-stripping)。
- 局域网访问机制:开启后通过 --patch 把 webserver 绑定到 0.0.0.0; DSH 的 resolveLanTrust 会自动把本机局域网 IPv4 加入 browser-trust 放行列表,手机等局域网设备即可访问。插件通过 $DSH_HOME/profiles/web/node_modules 的 junction 链接注入(loader 从 profile 目录做模块解析)。
- Python / dsh CLI 是可选项:仅在用户需要时一键安装,不阻塞主流程。

目录结构

dsh-desktop/
├── src/
│ ├── main/ # Electron 主进程(index/server/deps/ipc/settings/logger) │ ├── preload/ # contextBridge 桥接 │ ├── renderer/ # 壳 UI(boot 启动页 / settings 设置页 + i18n) │ └── shared/ # 主进程与渲染层共享的类型与常量 ├── runtime/ # DSH 运行时(node_modules 由 prepare-runtime 安装) ├── scripts/ # build(esbuild)/ prepare-runtime / make-icon / smoke ├── build/ # 生成的应用图标(icon.ico/icon.png/tray.png) └── docs/ # 用户指南、FAQ

本地开发

要求:Windows 10+,Node 22(仅用于构建,最终产品不需要)。

npm install # 安装 electron/electron-builder/esbuild 等
npm run prepare:runtime # 安装并裁剪 DSH 运行时到 runtime/
npm run build # esbuild 打包 main/preload/renderer 到 dist/
npm run smoke # 端到端冒烟测试(启动服务→HTTP 探活→退出)
npm start # 本地运行(构建后启动 Electron)
npm run dist # 打包 NSIS 一键安装器(release/ 目录)
npm run check:upstream # 检查 runtime 内置 dsh 是否为 npm 最新版(维护用)

构建时若无法访问 GitHub(下载 Electron/NSIS 工具链),可设置镜像: $env:ELECTRON_BUILDER_BINARIES_MIRROR="https://npmmirror.com/mirrors/electron-builder-binaries/"

Smoke 测试

npm run smoke 以无窗口模式启动应用,验证:DSH 服务启动 → HTTP 200 →
window.__DSH_BOOT__ 注入 → 干净退出。结果写入 smoke-result.json。

CI 构建与发布

.github/workflows/build-release.yml 提供 GitHub Actions 流水线:
- push 到 main:自动构建 Windows / macOS 安装包并上传 artifact
- 打 v* tag:自动发布 GitHub Release(应用内「检查更新」以此为源)

安装包产物

- release/DeepSeek-Harness-Desktop-Setup-.exe — NSIS 一键安装器(约 130MB,含完整 DSH 运行时与 Electron)
- 安装到 %LOCALAPPDATA%\Programs\dsh-desktop\,创建桌面/开始菜单快捷方式,安装后自动启动
- release/win-unpacked/ — 免安装绿色版(直接运行 DeepSeek Harness Desktop.exe)
- 卸载通过 Windows「应用与功能」或 Uninstall DeepSeek Harness Desktop.exe 完成;卸载不删除用户数据(%APPDATA%\DeepSeek Harness Desktop)

已验证的完整链路(本机实测)

| 环节 | 结果 |
| 构建 | esbuild 打包 main/preload/renderer + lan-access 插件 ✔ |
| 冒烟测试(无窗口) | DSH 服务 4-8s 就绪,HTTP 200,__DSH_BOOT__ 注入,干净退出 ✔ |
| 内置插件 | /lan-info 路由 + __DSH_BOOT__ 注入 + /plugins/@dsh-desktop/lan-access/client.js 可加载 ✔ |
| 局域网访问 | 开启后 http://: HTTP 200(browser-trust 自动放行)✔ |
| 打包 | electron-builder 产出 NSIS 安装器 ✔ |
| 静默安装 | 安装成功,注册表卸载项、快捷方式创建 ✔ |
| 正常 GUI 启动 | 主窗口加载 Harness UI;托盘正常 ✔ |
| 端口冲突 | 3080 被占用时自动顺延 ✔ |
| 优雅退出 | 服务子进程干净停止 ✔ |

局域网访问安全说明

「设置 → 局域网访问」默认关闭(服务仅监听 127.0.0.1)。开启后:
- 服务改为监听 0.0.0.0,同一局域网内的任何设备都能访问(无登录鉴权,仅靠 browser-trust 校验来源)。
- 请只在可信网络(家庭/办公 Wi-Fi)开启;公共 Wi-Fi 下不要开启。
- 关闭后重启服务即恢复仅本机可访问。

已知边界(v0.2)

- 未做 Apple 官方签名/公证(v0.2.4 起构建时带 ad-hoc 签名,无需终端即可打开):
- Windows:SmartScreen 会提示「未知发布者」,选择「仍要运行」即可。
- macOS:从网上下载的未公证应用首次打开会提示「无法验证开发者」——点「打开」(或右键应用 → 打开)即可,只需一次,无需终端;之后的「检查更新 → 下载并安装」由应用自动替换并清除隔离属性,全程无感。
- ⚠️ 若旧版本(v0.2.3 及更早)提示「已损坏,无法打开」:这是旧包残留无效签名导致的,请改用 v0.2.4 及更新版本;或临时在终端执行 codesign --force --sign - "/Applications/DeepSeek Harness Desktop.app" 后右键打开。
- 正式分发建议配置 Apple 开发者证书 + 公证(用户零点击,见 docs/BUILD_MAC.md)。
- 更新为「检查更新 + 自动安装」模式:设置页查询 GitHub Releases 最新版,检测到新版本后可直接「下载并安装」:
- Windows:流式下载 NSIS 安装包(带进度)→ /S 静默安装 → 应用退出并由安装器拉起新版本。
- macOS:流式下载对应架构的 zip(带进度)→ 应用退出 → 解压替换 .app(移除 quarantine 属性,未签名场景可继续打开)→ 自动重启。
- macOS 已发布(v0.2.0 起,dmg/zip × x64/arm64),自动更新与 Windows 同步支持。
- Linux 目标尚未打包(package.json 中无 linux 配置,可按需扩展)。

许可

MIT。DeepSeek Harness 本身遵循其上游许可(MIT)。
预览分享卡片长什么样 ↓yansenlei/dsh-desktop
分享 · DeepSeek Harness Hub
yansenlei/dsh-desktop

双击安装即可在电脑上使用 AI 助手,无需命令行

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