Skip to content
dsh.fish
Bundle

dsh-marketplace

A safe, live plugin marketplace for DeepSeek Harness

Source
ouyangyipeng
stars
2 stars
License
MIT
Updated
Updated 10 days ago

Readme

<p align="center">
  <img src="assets/brand/marketplace-cover.svg" alt="DSH Marketplace — 把插件社区变成你的应用市场" width="100%">
</p>

<p align="center">
  <strong>简体中文</strong> · <a href="README.en.md">English</a>
</p>

<p align="center">
  <a href="https://ouyangyipeng.github.io/dsh-marketplace/">官网</a> ·
  <a href="#安装">安装</a> ·
  <a href="#安全边界">安全</a> ·
  <a href="#原生-dsh-结构">架构</a> ·
  <a href="#ds-harness-desktop">Desktop</a> ·
  <a href="#开发与验证">开发</a>
</p>

`dsh-marketplace` 本身就是一个 DeepSeek Harness bundle。它把 GitHub [`topic:dsh-plugin`](https://github.com/topics/dsh-plugin) 的实时社区仓库放进 **设置 → 插件 → Marketplace**,让插件发现、搜索、检查、安装、更新和卸载留在同一个 Harness 界面里。

<p align="center">
  <img src="assets/screenshots/marketplace-desktop.png" alt="真实 DeepSeek Harness 设置页面中的 DSH Marketplace 插件列表" width="920">
</p>

> [!IMPORTANT]
> Marketplace 能检查包格式和收紧安装过程,不能证明第三方插件可信。插件重启后会在 DSH 进程内运行;启用前仍应阅读源码。

## 安装

### DS-Harness Desktop

[DS-Harness Desktop](https://github.com/ouyangyipeng/dsh-desktop) 从 `desktop-v0.2.0` 起离线内置固定版本的 Marketplace。打开应用后进入 **设置 → 插件 → Marketplace**,不需要先安装本插件。

内置版本显示“Desktop 内置”,不能在 Marketplace 里更新或卸载自己;它随经过验证的 Desktop release 更新。其他插件仍安装进 Desktop 隔离的 `web` profile。

### 标准 DSH Web profile

需要当前 DeepSeek Harness、Node.js `^22.19.0 || >=24.0.0` 和位于 `PATH` 中的 `pnpm`:

```sh
dsh plugin --profile web add "github:ouyangyipeng/dsh-marketplace#v0.1.1"
```

重启 `dsh web`,然后打开 **设置 → 插件 → Marketplace**。

更新或卸载独立安装的 Marketplace 使用 DSH 原生命令:

```sh
dsh plugin --profile web update dsh-marketplace
dsh plugin --profile web remove dsh-marketplace
```

## 一条插件从发现到激活

```mermaid
flowchart LR
  Topic["GitHub topic:dsh-plugin"] --> Cache["Catalog cache + ETag"]
  Cache --> UI["Marketplace Client"]
  UI --> Stage["pnpm add --ignore-scripts"]
  Stage --> Inspect["Manifest + exports + path checks"]
  Inspect --> Profile["Atomic profile edit"]
  Profile --> Restart["Restart DSH"]
```

1. Host 最多读取 GitHub Search 的 10 页、每页 100 个公开仓库。
2. Client 在本地按名称、作者、简介和 topic 搜索,并按更新时间、Stars 或名称排序。
3. 点击安装时,候选包先进入独立临时项目;这一步不修改用户 profile。
4. 包通过预构建入口、bundle patch 和路径检查后,才正式写入 profile dependency。
5. `dsh.profile.bundles` 使用原子文件替换;安装失败时不激活,卸载失败时恢复旧 manifest。
6. 生命周期变化在重启 DSH 后生效。

## 安全边界

| Marketplace 会做 | Marketplace 不会承诺 |
| --- | --- |
| 用严格的 `owner/repository` 语法解析仓库 | 审核插件业务逻辑或作者身份 |
| 始终以 `pnpm add --ignore-scripts` 暂存和安装 | 把安装后的插件放进运行时沙箱 |
| 要求安全包名、预构建 Host 与标准 `dsh.bundle.patch` | 证明仓库没有恶意代码 |
| 声明 Web Client 时要求预构建 `./client` export | 读取私有仓库或保存 GitHub token |
| 检查 patch/entry 的真实路径仍位于包目录内 | 让源码包或依赖构建脚本的仓库自动兼容 |
| 逐项传递子进程参数,不拼接 shell command | 绕过 DSH 的重启激活语义 |
| 只允许同源 loopback + 进程 nonce 调用写接口 | 把 Marketplace 变成远程管理 API |
| 把 GitHub 数据作为 React 文本渲染,不插入 HTML | 加载远端头像或仓库 HTML |

只有 TypeScript 源码、依赖 `prepare`/`postinstall`、实际是独立应用或没有标准 DSH bundle 声明的仓库仍会出现在目录中,但安装会明确失败。Marketplace 不会退回执行它们的脚本。

## 原生 DSH 结构

本包有两个 DSH face:

```mermaid
flowchart LR
  Patch["cordis.patch.yml"] --> Host["Host face"]
  Host --> API["/dsh-marketplace/v1"]
  Manifest["package.json#dsh.client"] --> Client["Client face"]
  API --> Client
  Client --> Slot["settings.plugins.tab"]
  Host --> Profile["$DSH_HOME/profiles/web"]
```

- [`cordis.patch.yml`](cordis.patch.yml) 挂载 Host。
- `package.json#dsh.bundle.patch` 声明可安装的 profile bundle。
- `package.json#dsh.client` 声明 Web Client 和注入的 DSH 服务。
- Host 只注册一个 effect-scoped 路由前缀;Client 只注册一个设置页 Tab。
- Host 不根据进程名或路径猜测宿主。Desktop 等发行版通过 `bundledRepositories` 明确声明自己的固定内容。

## HTTP API

所有响应均为 JSON,并带 `Cache-Control: no-store`。

| Method | Path | 用途 |
| --- | --- | --- |
| `GET` | `/dsh-marketplace/v1/bootstrap` | nonce、写权限、profile inventory 与 host-bundled repositories |
| `GET` | `/dsh-marketplace/v1/catalog` | 缓存目录;`?refresh=1` 强制重验证 |
| `POST` | `/dsh-marketplace/v1/install` | 暂存、验证、安装/更新并激活仓库 |
| `POST` | `/dsh-marketplace/v1/remove` | 按 package + repository 停用并移除插件 |

写接口要求 TCP 对端、`Host` 和可选 `Origin` 均为 loopback,同时提交同源 bootstrap 返回的进程 nonce。LAN 客户端、远端 Origin、错误 nonce、非 JSON 内容、超过 16 KiB 的 body 和 host-bundled repository mutation 都会被拒绝;bundled conflict 返回 HTTP 409。

## 配置

独立安装使用以下保守默认值:

```yaml
- insert:
    - id: dsh-marketplace
      name: dsh-marketplace
      config:
        profile: web
        cacheTtlMs: 600000
```

可选配置:

- `home`:覆盖 DSH Home;空值依次使用 `DSH_HOME` 和 `~/.dsh`。
- `bundledRepositories`:宿主拥有的不可变 `owner/repository` 列表;默认 `[]`。坐标在加载时规范化,非法值和大小写归一后的重复值会让插件启动失败。

## 目录与限流

- GitHub Search 对一个查询最多返回 1,000 条结果。
- 未登录 Search API 限流较低;Marketplace 不收集或持久化 GitHub token。
- Host 使用十分钟缓存、ETag 重验证、可见的 rate-limit 状态和 stale-on-error 回退。
- 兼容性只在用户点击安装或更新时验证,避免提前 clone 1,000 个未知仓库。
- GitHub 不可用不会阻止 Harness 或 Desktop 启动。

## 开发与验证

```sh
git clone https://github.com/ouyangyipeng/dsh-marketplace.git
cd dsh-marketplace
pnpm install

pnpm test
pnpm run typecheck
pnpm run build
pnpm site:check
pnpm pack --dry-run
```

把本地 checkout 接入 DSH:

```sh
dsh plugin --profile web add "link:$(pwd)"
dsh web
```

测试覆盖目录分页与缓存、仓库坐标、manifest/entry/patch 验证、真实路径和符号链接逃逸、禁脚本子进程参数、profile 原子更新与回滚、Host HTTP policy、bundled mutation、远端文本渲染、Client 搜索和产品站静态约束。

## License

[MIT](LICENSE)。DeepSeek Harness、DeepSeek 名称与社区插件保留各自的许可证和商标。本项目是社区维护的非官方插件。

Install

dsh plugin --profile web add github:ouyangyipeng/dsh-marketplace

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source