# deepseek-harness-desktop

> 在 DSH Web 设置页加一个「Web UI 插件」一级分区，归组 dsh-web-ui 全家桶插件的开关与配置；并提供 rc.6 兼容设置桥接，让旧版宿主也能读写这些配置。

## Metadata

- Author: [@ningbainb](https://github.com/ningbainb)
- Repo: <https://github.com/ningbainb/deepseek-harness-desktop.git>
- GitHub: [ningbainb/deepseek-harness-desktop](https://github.com/ningbainb/deepseek-harness-desktop)
- Stars: 156
- Language: TypeScript
- License: [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html)
- Homepage: <https://ningbainb.github.io/deepseek-harness-desktop/>
- Topics: `ai-agent`, `ai-coding-assistant`, `codex`, `deepseek`, `deepseek-harness`, `desktop-app`, `dsh`, `dsh-plugin`, `electron`, `electron-app`, `gui`, `open-source`, `plugin-system`, `plugins`, `remote-access`, `skills`, `ssh-client`, `windows`, `windows-desktop`
- Forks: 5
- Open Issues: 6
- Last push: 2026-08-20T05:29:52.000Z
- Added: 2026-08-20T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:ningbainb/deepseek-harness-desktop/packages/dsh-web-ui-settings
```

## Wiki

## 一句话定位
在 DSH 网页版的设置页加入一个「Web UI 插件」一级分区，把 dsh-web-ui 全家桶插件的启用开关与配置表单聚拢到一处；并附带一套仅限本机回环访问的设置桥接，让旧版宿主（rc.6 时代的 apiproxy）也能读写这些第三方配置。

## 核心能力
- 在设置页注册一个名为「Web UI 插件」的一级分区，承载 dsh-web-ui 全家桶插件的开关卡片
- 声明 `web-ui.plugin.item` 列表型子槽位，供 task-board、git-graph、pet、live-stats、remote-web-ui、ssh、describe-image、particle-theme、skin-background 等兄弟插件挂入各自的配置卡片
- 内置社区插件索引卡片：可折叠的纯链接列表，每条指向贡献者自己的仓库（不收录第三方代码）
- 提供 `webUiSettings.bind()` 兼容性 binder：当官方 settings scope 报告命名空间不可用时，自动改走本机回环 HTTP 桥接，让本机浏览器仍能读到配置表单
- host 半区在 webServer 上注册两个同源端点 `/api/dsh-web-ui-settings/describe` 与 `/mutate`，把宿主 settings seam 的命名空间数据投影成官方 apiproxy 的线协议视图
- 通过 `mountOnce` 在进程内只挂载一次，避免被聚合包与独立包同时加载时重复注册路由

## 技术实现
- **语言**: TypeScript + React 18（CSS Modules 由 lightningcss 编译进 bundle）
- **关键依赖**: `@deepseek-ai/cordis`（插件运行时与 Context 类型）、`@deepseek-ai/dsh-client-ui-settings`（`settings.section` 插槽与 settingsScope）、`@deepseek-ai/dsh-host-webserver`（host 路由注册）、`@deepseek-ai/dsh-settings`（host 设置命名空间与 SettingsConflictError）、`schemastery`（profile Config schema）
- **架构模式**: cordis bundle 插件（`cordis.patch.yml` 在 web profile 中插入 `ui-web-ui-settings` 行）；host 半区（`src/index.ts`）声明 settings namespace 与同源 HTTP 桥接路由；浏览器半区（`src/client/index.ts`）注册 locale、声明 settings.section slot、初始化 `webUiSettings` 兼容性 binder；host/client 通过共享的 `src/protocol.ts` 与 `src/allowlist.ts` 协议常量对齐
- **入口文件**: `src/index.ts`（host 导出 `apply` / `Config` / `resolveProxyAccess` / `DEFAULT_PROXY_TOKEN_ENV`）、`src/client/index.ts`（browser 导出 `apply`）

## 适用场景
希望把 dsh-web-ui 全家桶插件的开关与配置集中到 DSH 设置页同一处管理、减少四处翻找的用户；以及还在跑旧版宿主（无法原生暴露第三方命名空间）、希望本机浏览器侧仍能正常打开配置表单的部署。

## 前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH 平台 SDK | `>=0.1.0-rc.7` | `devDependencies` 中 `@deepseek-ai/dsh-client-*` / `dsh-host-webserver` / `dsh-settings` 等均要求 `^0.1.0-rc.7` |
| 官方 settings UI | `>=0.1.0-rc.7` | 设置分区依赖 `@deepseek-ai/dsh-client-ui-settings` 提供的 `settings.section` 插槽与 `settingsScope` 服务 |
| React | `^18.2.0` | `package.json#peerDependencies` |
| Node 运行时 | `^22.19 \|\| >=24` | 据 `packages/AGENTS.md:9`；本包 `package.json` 未声明 `engines` 字段 |
| 平台 | 跨平台（DSH 网页端） | `dsh.client.platform = web`；桥接默认仅本机回环访问 |
| 原生模块 | 无 | 仅依赖 `schemastery` 与官方 SDK，无 `node-pty` / `node:sqlite` 等原生绑定 |

## 安装方式
```bash
dsh plugin --profile web add github:ningbainb/deepseek-harness-desktop/packages/dsh-web-ui-settings
```

## 配置项
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| `trustedProxyHosts` | 字符串数组 | 允许哪些规范化的 `host[:port]` 走带认证的反向代理转发到本桥接；留空表示只接受本机回环，不开启代理模式 | `[]` |
| `proxyTokenEnv` | 字符串（≥1 字符） | 当 `trustedProxyHosts` 非空时，承载反向代理共享令牌的环境变量名（不允许直接把令牌写在 profile 里） | `DSH_WEB_UI_SETTINGS_PROXY_TOKEN` |

## 常见问题

**Q: 安装后设置页里看不到「Web UI 插件」分区怎么办？**

A: 需要先重启 `dsh web`。分区依赖官方 `@deepseek-ai/dsh-client-ui-settings` 提供 `settings.section` 插槽；如果你的宿主版本未携带此 SDK，分区不会出现在设置页里。

**Q: 这个插件需要我额外配置什么吗？**

A: 默认无需任何配置即可用——桥接默认仅本机回环访问，所有命名空间走内置的回退列表。若要让同主机的反向代理代为转发，需要在 profile 里写 `trustedProxyHosts` 与 `proxyTokenEnv`，并在进程环境里设置同名变量承载共享令牌。

**Q: 我用的是 rc.7 及以上的宿主，还需要本包提供的桥接吗？**

A: 通常不需要。当宿主 apiproxy 已原生暴露相应命名空间时，`createCompatScope` 让官方 scope 保持权威，桥接不会激活；只有当官方 scope 报告 `unavailable` 且浏览器处于本机回环时，本包桥接才接管。

**Q: 卡片显示「未向设置页暴露此命名空间」怎么办？**

A: 表示宿主 apiproxy 当前不识别该命名空间。本包提供的回环桥接会让本机浏览器优先接管，但前提是命名空间已在宿主 settings 中注册；如果仍然无法显示，请确认对应子插件（task-board / git-graph 等）已正确安装并加载。

**Q: `trustedProxyHosts` 该怎么填？**

A: 必须是规范化的 `host[:port]`，例如 `dsh.example.com` 或 `127.0.0.1:8443`。解析时会校验大小写与端口范围，不合规会在启动时抛出错误并阻止 host 半区挂载。

**Q: 我能否把反向代理令牌明文写到 profile 里？**

A: 不行。profile 只允许写 `proxyTokenEnv`（环境变量名），真实令牌必须从进程环境变量读取；这是为了避免令牌泄露到配置仓库或版本控制。

**Q: 「社区插件」卡片里的条目安全吗？**

A: 该卡片只是可折叠的纯链接列表，索引条目由贡献者自行登记，本包不收录、不打包第三方代码；点击后跳转至作者自己的仓库，是否安装由用户自行评估。

**Q: 怎么卸载？**

A: 用 `dsh plugin --profile web remove` 卸载即可。本插件不写本地存储，也不创建宿主外的资源，卸载后无残留数据。

## 上手难度
入门 — 安装重启后设置页即出现分区；绝大多数场景下零配置即可看到 dsh-web-ui 全家桶的开关与配置，需要代理转发时再翻 README 的代理配置示例。

## 已知问题与限制
- 设置分区仅在宿主携带 `@deepseek-ai/dsh-client-ui-settings` SDK 时才会显示；缺少该 SDK 的宿主不会自动出现本分区（README.zh.md:47 / README.md:47）
- 认证代理模式本身不提供身份认证；必须由前置反向代理完成认证、替换 `x-dsh-web-ui-settings-proxy-token` 请求头后，才允许把请求转发到宿主回环监听器（README.zh.md:48 / README.md:48）
- `trustedProxyHosts` 列表必须严格使用规范的 `host[:port]`（小写主机名、合法的端口范围），填错一个字符就会让 host 半区在启动阶段直接抛错并阻止挂载（src/bridge.ts:88-102）
- 桥接只服务于浏览器侧的本机回环请求（`127.0.0.1`、`::1`、`localhost`），远程浏览器永远不会触发桥接，保证不绕过宿主原生的同源策略（src/client/compat-settings-scope.ts:304-315）
- 进程内单实例守卫 `mountOnce` 依赖 `globalThis` 上的 Symbol 注册表；如果插件既被聚合包又通过 link 路径同时挂载，后挂载的实例会被静默丢弃，不会重复注册 webServer 路由（src/mount-once.ts:19-27）

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [deepseek-harness-desktop](https://deepseek-plugin.org/plugins/ningbainb/deepseek-harness-desktop/packages/dsh-web-ui-settings)
Wiki generated by AI (model: `MiniMax-M3`)
