# Deepseek-Harness-Desktop

> dsh 的 Web 表层组合包：在 base 之上挂载 Web 宿主、Web 服务器、API 网关、浏览器插件清单与前端静态回退席位，并提供 dsh --profile web 命令行参数解析与启动 URL 输出

## Metadata

- Author: [@ChisaAlter](https://github.com/ChisaAlter)
- Repo: <https://github.com/ChisaAlter/Deepseek-Harness-Desktop.git>
- GitHub: [ChisaAlter/Deepseek-Harness-Desktop](https://github.com/ChisaAlter/Deepseek-Harness-Desktop)
- Stars: 127
- Language: JavaScript
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Topics: `deepseek`, `deepseek-harness`, `dsh-plugin`
- Forks: 9
- Open Issues: 0
- Last push: 2026-08-20T11:02:01.000Z
- Added: 2026-08-20T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:ChisaAlter/Deepseek-Harness-Desktop/vendor/deepseek-harness/packages/bundle/web-app
```

## Wiki

> 本文档对应 vendor 仓中 `vendor/deepseek-harness/packages/bundle/web-app` 子路径，是落地页 `/plugins/{owner}/{repo}` 中**插件百科**模块的内容来源。

## 一句话定位
`@deepseek-ai/dsh-web-app` 是 DSH 的浏览器表层组合包：在 `dsh-base` 之上挂载 Web 服务器、API 网关、workspace、投影缓存、存储、浏览器插件清单与前端 dist 回退席位，并由内置的 `web-runtime` 粘合插件解析构建产物、向模型注册 Web 表层提示、注入 `DSH_WEB_URL` bash 变量以及打印 `dsh web:` URL 行。

## 核心能力
- 覆盖 dsh-base 之上 Web 表面所需的宿主持行：Web 服务器、API 网关、workspace、投影缓存、JSON/域存储、消息反馈、目录选择器、插件/MCP/技能清单
- 挂载浏览器端插件清单（约 40 个 `dsh.client` 行）以及始终挂载的客户端 HMR 监听链（在 `pnpm run dev:web` 改写 client bundle 前保持空闲）
- 提供 `dsh --profile web` 的命令行解析：解析 `--host`、`--port`、可重复 `--trusted-host` 与 `--help`，并拒绝 `--host 0.0.0.0` 和非数字端口
- 解析已构建的前端 dist（`@deepseek-ai/dsh-web-frontend/dist/index.html`）并挂载 `frontend-static` 回退席位
- 采样一次绑定后的 LAN 信任快照，作为 `webRuntime` 服务提供给浏览器信任栅栏和 UI 端
- 注册 `app:web-surface` 系统提示段落和 `DSH_WEB_URL` 受管 bash 环境变量，让模型能识别"这个 GUI"以及"this page"指代什么
- 等 Loader 配置树结算后再打印 `dsh web: http://127.0.0.1:<port>` URL 行，绑定的 host 是全网卡时附带 LAN URL
- 显式禁用 agent-plane 工具行（bash / pwsh / fs / skill / subagent / workflow / todo / web / goal / plan / compact 等），把这些能力留给 agent preset 在每个会话里按需挂载

## 技术实现
- **语言**: TypeScript（ESM，包声明 `"type": "module"`，三个入口文件：`src/index.ts` web-runtime 粘合插件 + `src/startup.ts` 命令行提供方 + `src/invariant.ts` invariant 配套）
- **关键依赖**: `@deepseek-ai/cordis`（peer，宿主运行时）、`@deepseek-ai/cordis-plugin-loader`（peer，profile 加载）、`@deepseek-ai/dsh-system-prompt`（peer，提示词注册）、`@deepseek-ai/dsh-shell-env`（peer，受管 bash 变量）；实质 patch 由组合器读取
- **架构模式**: Profile 组合包（bundle）—— `cordis.patch.yml` 通过 manifest 字段 `dsh.bundle.patch` 暴露，由 profile 组合器读出按行插入；包内同时挂载两个运行时 Cordis 插件：`web-startup`（普通 service 插件，解析 CLI 并发布 `webStartup`）和 `web-app`（依赖 `webServer` 与 `webStartup`，发布 `webRuntime`）
- **入口文件**: `src/index.ts:135`（`apply()`，web-runtime 粘合逻辑）/ `src/startup.ts:65`（`apply()`，commander 命令行解析）/ `cordis.patch.yml:1-473`（约 60 余行 patch 列表，是真正的产品载荷）

## 适用场景
当用户想在自己机器上跑出 DSH 官方浏览器界面（即 `dsh web` 那个 GUI）时，需要把这个组合包连同 `dsh-base` 一起装进 profile：它提供 Web 服务器、API 网关、workspace、持久化、客户端插件清单以及启动 URL 输出，是把 dsh-base 的基础能力暴露成浏览器交互形态的必备叠层；如果只是想跑一次性任务不想开 GUI，应该改用 `dsh-headless` 这条相邻 profile，不挂载本组合包。

## 前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH | 0.1.0-rc.6+ | 包 `version` 与上游基线 `0.1.0-rc.7` 一致；peer 中包含 `@deepseek-ai/cordis` `@deepseek-ai/cordis-plugin-loader` `@deepseek-ai/dsh-shell-env` `@deepseek-ai/dsh-invariants` `@deepseek-ai/dsh-system-prompt` 需在宿主中可用 |
| Node | >=22.19.0 | 来自上游 monorepo `engines.node`：`^22.19.0 \|\| >=24.0.0`；本包未单独声明 |
| 平台 | macOS / Windows / Linux | patch 不做平台分支，跨平台同一份；CLI 解析里把端口和 host 校验留给 commander |
| 原生模块 | 无 | 本包本身不直接引入原生依赖；下层组合用的 `node:sqlite`（全文本搜索，默认不打开）与 `node-pty` 来自其他 bundle / 桌面壳 |

## 安装方式
```bash
dsh plugin --profile web add github:ChisaAlter/Deepseek-Harness-Desktop/vendor/deepseek-harness/packages/bundle/web-app
```

## 配置项

web-runtime 粘合插件（`src/index.ts`）声明的三项 Config（由 cordis.patch.yml 顶层赋值）：

| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| `printUrl` | 布尔 | 是否在启动后等 Loader 配置树结算再打印 `dsh web: http://127.0.0.1:<port>`（绑定全网卡时附 LAN URL）。非交互式上层可关掉 | `true` |
| `surfaceContext` | 布尔 | 是否注册 `app:web-surface` 系统提示段落以及 `DSH_WEB_URL` 受管 bash 变量；非 GUI 调用方关闭后可避免让模型误读上下文 | `true` |
| `trustedHosts` | 字符串数组 | 显式 `--trusted-host` 列表（在 /api 浏览器信任栅栏里追加的 host 或 host:port），按 CLI 入参顺序叠加 | `[]` |

命令行（`src/startup.ts`）解析的四个标志，由 `dsh --profile web` 直接接受：

| 标志 | 说明 |
|---|---|
| `--host <host>` | 绑定 host；为安全原因，`0.0.0.0` 会被显式拒绝 |
| `--port <port>` | 监听端口；`0` 让 OS 选一个空闲端口；非数字直接报错 |
| `--trusted-host <authority...>` | 可重复，向 /api 浏览器信任栅栏追加 host 或 host:port |
| `-h, --help` | 打印自身帮助并以退出码 0 终止；该模式下不发布 `webStartup`，所以不会启动服务器 |

> patch 还包含一组静态默认值（`session-query-sqlite.path: ':memory:'`、`message-feedback.maxNoteBytes: 8192`、`session-projection-cache.writeEveryEvents: 200` 与 `writeIntervalMs: 5000`、工具 `mode` 取环境变量 `DSH_TOOLS_MODE`、`agent-presets.default: standard` 等），它们是 patch 内置配置，不是面向用户的独立配置入口。

## 常见问题

**Q: 装上这个 bundle 之后会得到 `dsh --profile web` 那个浏览器界面吗？**

A: 是。patch 把 webserver、API 网关、workspace、投影缓存、存储、浏览器插件清单以及前端 dist 回退席位都挂上，再由 web-runtime 粘合插件解析构建产物并打印 `dsh web: http://127.0.0.1:3080` URL 行。

**Q: 需要单独构建一次前端 dist 才能用吗？**

A: 是。runtime 粘合插件通过 `require.resolve('@deepseek-ai/dsh-web-frontend/dist/index.html')` 定位 dist，未构建时会在激活阶段直接报错并提示先 `pnpm run build`，没有从源码服务的回退。

**Q: 启动后我想换端口或者只允许特定 host 访问，应该怎么写？**

A: 用 CLI 标志：`dsh --profile web --port 8080 --host 127.0.0.1`，可重复 `--trusted-host app.internal` 把主机名/IP 加入 /api 浏览器信任栅栏；这些都是 web-startup 行在加载阶段解析，不写进 patch。

**Q: 这个 bundle 跟 `dsh-base` 是什么关系？**

A: 必装叠加：base 是任何 profile 的公共地基（模型、工具、沙箱、遥测、持久化），web-app 在 base 之上插入 Web 特有的宿主持行（webserver、api-gateway、storage、workspace）、命令行列与浏览器插件清单，并禁用 base 中将被 agent preset 接管的那批 agent-plane 工具行。

**Q: `--host 0.0.0.0` 为什么不让用？**

A: CLI 在 publish `webStartup` 之前显式拒绝这个值，避免绑定全网卡把代码执行能力暴露给整个网络；改用 `--host 127.0.0.1` 或具体 LAN IP 即可。

**Q: 启动后我在浏览器里访问不到 LAN IP 上的页面，怎么办？**

A: 把对应的 LAN 网卡 IP 追加到 `--trusted-host` 中，浏览器信任栅栏和 UI 列出来的 LAN URL 都使用同一份快照。变更只在启动时采样一次，运行中网卡变化不会被重新公告。

**Q: Agent 用的 bash / fs / skill 工具去哪了？**

A: 这部分 agent-plane 工具行在 patch 里被显式 `disabled: true`，原因是它们改由 agent preset 在每个会话里按需挂载。基座的进程级服务（`shell-env`、子代理注册表、目标服务、远程 /api 网关等）保留在 host 平面，由 web 表面继续使用。

## 上手难度
入门 — 只要把它加进 `--profile web` 即可获得官方 GUI；要换端口/host/信任源都用现成 CLI 标志，不用动 patch。

## 已知问题与限制
- **前端 dist 必须先构建**：runtime 粘合插件在激活时通过 `require.resolve('@deepseek-ai/dsh-web-frontend/dist/index.html')` 定位 dist，未构建会直接抛错并提示先 `pnpm run build`，没有源码即服务的回退
- **`lanAddresses` 是启动期快照**：bind 后网卡变更不会被重新公告；打印出来的 LAN URL 始终与配置的信任栅栏一致，需要重启才能让变更生效
- **不支持 `--host 0.0.0.0`**：CLI 在 publish `webStartup` 之前显式拒绝，避免把 RCE 能力暴露给整个网络；目前不支持绑定所有网卡是有意为之
- **共享 HMR 暂未启用**：patch 中 `hmr` 行被 `disabled: true` 并标注 TODO（"Re-enable shared HMR for Web after its reload lifecycle is tested"）；目前 client-hmr 是常驻空闲链，只有在同 checkout 跑 `pnpm run dev:web` 时才会触发无刷新重载
- **未配置 trusted-hosts 时仅信任本机**：默认 `--trusted-host` 为空、`host` 为 `127.0.0.1`，所以 LAN / 公网访问会被 /api 浏览器信任栅栏拒绝，需要显式声明才能打开

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [Deepseek-Harness-Desktop](https://deepseek-plugin.org/plugins/ChisaAlter/Deepseek-Harness-Desktop/vendor/deepseek-harness/packages/bundle/web-app)
Wiki generated by AI (model: `MiniMax-M3`)
