# deepseek-harness-genui

> 让 DeepSeek Harness Agent 现场编写可交互 React 小应用，并把用户选择带回下一轮继续使用。

## Metadata

- Author: [@pengyue-polaron](https://github.com/pengyue-polaron)
- Repo: <https://github.com/pengyue-polaron/deepseek-harness-genui.git>
- GitHub: [pengyue-polaron/deepseek-harness-genui](https://github.com/pengyue-polaron/deepseek-harness-genui)
- Stars: 58
- Language: TypeScript
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Topics: `deepseek-harness`, `dsh`, `dsh-plugin`, `generative-ui`, `genui`, `mcp`, `react`
- Forks: 5
- Open Issues: 1
- Last push: 2026-08-19T09:59:54.000Z
- Added: 2026-08-16T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:pengyue-polaron/deepseek-harness-genui
```

## Wiki

## 一句话定位
让 DeepSeek Harness Agent 在当前任务里现场编写一段 React 小应用（仿真器、选择器、可视控件、交互图），并把用户的选择、表单答案和进度保存回任务里，让下一轮 Agent 直接接上结果继续。

## 核心能力
- 注册 `genui_create` / `genui_update` / `genui_inspect` / `genui_state_read` / `genui_rollback`：Agent 用一组 React+TypeScript 源码直接产出可交互工件，支持增量补丁和回滚到任一历史版本
- 提供三套内置视觉语言（`material-3`、`apple-human-interface`、`shadcn-ui`）以及自定义 `DESIGN.md` 导入：插件在构建时把选定的设计语言打包到生成的 CSS 中
- 沙箱化运行生成代码：生成的 React 应用跑在带 Content Security Policy 的 iframe 里，使用 HMAC 签名的能力令牌访问宿主 API，失败更新不会替换最后一个可用版本
- 持久化任务状态和已授权权限：用户的选择、表单草稿、完成的结构化结果保存 7 天，权限按声明范围一次性授权并 7 天过期
- 提供四种交付面：Inline（嵌在对话里）、Canvas（右侧面板）、fullscreen、CLI/localhost 链接；同一份任务状态在所有入口共享
- 注入工具调用发现预算：每个数据源最多 2 次发现、4 次读取，单轮最多 6 次读取，防止 Agent 在生成界面前把上下文打满

## 技术实现
- **语言**: TypeScript
- **关键依赖**: `@deepseek-ai/cordis`（宿主注入）、`@deepseek-ai/dsh-agent` / `dsh-tools` / `dsh-system-prompt` / `dsh-host-webserver`（宿主服务）、`@deepseek-ai/schemastery`（配置 schema）、`esbuild`（生成代码打包）、`react`/`react-dom`（运行时）
- **架构模式**: Cordis 插件。服务端 `apply` 启动时创建 `ArtifactRegistry`、`DesignStore`、`CapabilityStore`，在宿主 WebServer 上注册 `/genui` 前缀路由和 `/.well-known/dsh-genui` 发现端点，向 systemPrompt 注入两段提示词并注册 7 个工具；客户端 `GenuiToolView` 把工具调用渲染为带进度条、收据卡片、权限弹窗、Canvas 拖拽的卡片视图
- **入口文件**: `src/index.ts`（服务侧，导出 `name`/`inject`/`apply`）→ `src/runtime.ts` → `src/tools.ts`；客户端入口 `src/client/index.tsx`

## 适用场景
当用户提出"挑出几个候选时段 / 调几个参数观察因果 / 追踪一段代码路径 / 做一个可玩的双缝实验"这类需要交互而文字来回很难讲清的任务时，本插件让 Agent 直接生成一段带控件和状态的小应用。普通问答、改写、摘要和简单列表仍只用文字，插件会主动避免"为了显得高级而画蛇添足"。

## 前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DeepSeek Harness（cordis / dsh-agent / dsh-client-runtime / dsh-client-locale / dsh-client-ui-conversation / dsh-client-ui-slots / dsh-client-ui-tool / dsh-host-webserver / dsh-llm / dsh-mcp-client / dsh-session / dsh-system-prompt / dsh-tools） | ^0.1.0-rc.6 | 宿主必须提供这些 peer 依赖，本插件只注入 web profile |
| Node.js | ^22.19.0 或 >=24.0.0 | package.json#engines 硬性要求 |
| pnpm | >=11.17.0 | package.json#packageManager 声明；本地开发构建需要 |
| React | ^18.3.1 | peerDependency；运行时由宿主或插件本身注入 |
| 平台 | 跨平台 | 无 os/cpu 限制，仅依赖 Node.js 内置模块（https / fs / dns） |

## 安装方式
```bash
dsh plugin --profile web add github:pengyue-polaron/deepseek-harness-genui
```

## 配置项
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| artifactRoot | 字符串 | 生成工件和状态文件存放的根目录，相对当前工作目录 | `.dsh/genui` |
| routePrefix | 字符串 | 插件挂在宿主 WebServer 上的 URL 前缀，必须以 `/` 开头、不含 `//`、不以 `/` 结尾 | `/genui` |
| maxSourceBytes | 整数 | 单次工件允许的源码总字节数（含路径与内容），范围 16384–16777216 | `1048576`（1 MiB） |

插件本身另外提供一个 DESIGN.md 默认值（自动 / Material 3 / Apple Human Interface / shadcn-ui / 自定义），在宿主「设置 → 插件 → 插件配置」里切换；不影响上述配置文件。

## 常见问题

**Q: 什么时候应该让 Agent 生成界面，而不是只回文字？**

A: 当任务涉及"看清一个复杂关系"或"同时做几项相互影响的选择"时，例如挑日历时段、调参观察因果、追踪代码路径。普通问答、改写、摘要、简单列表仍只返回文字，插件会主动避免画蛇添足。

**Q: 生成的应用会获取我的 MCP 凭据或 Cookie 吗？**

A: 不会。生成代码在带 CSP 的 iframe 沙箱里运行，只能调用生成时显式声明的工具或 HTTPS 接口；MCP 凭据不会进入生成代码，外部请求必须是无凭据的公开 HTTPS，DNS 解析会过滤私网地址。

**Q: 应用更新失败会怎样，旧版本会被覆盖吗？**

A: 不会。每次更新产生新版本，编译失败时只把该版本标为 failed 并保留最后一个 ready 版本；可以调用 `genui_rollback` 把当前指针切回任一历史 ready 版本，失败版本也不会被立即删除。

**Q: 任务状态和已授权权限会保留多久？**

A: 都是 7 天。任务状态自最后一次更新起 7 天后过期，权限授予 7 天后过期；过期后 Agent 用 `genui_state_read` 读不到数据，需要重新保存或重新授权。

**Q: 支持 TUI 终端 profile 吗？**

A: 支持但不嵌入 Canvas。TUI profile 调用 `genui_create` 时选择 `local-link` 交付方式即可拿到 localhost 链接，Agent 在下一轮用 `genui_state_read` 读取页面上保存的内容。

**Q: DESIGN.md 怎么用，能换默认风格吗？**

A: 在「设置 → 插件 → 插件配置」里切换默认设计：自动选、Material 3、Apple Human Interface、shadcn/ui，或导入自定义 DESIGN.md。已生成的应用保留原设计，后续新建的应用才使用新默认。

**Q: 单次应用源码有多大限制？**

A: 默认 1 MiB，最多可调到 16 MiB。每个应用必须有 `src/main.tsx`，允许的导入被白名单限定为 `react`、`react-dom/client`、`lucide-react`、`recharts`、`date-fns`、`zustand`、`framer-motion` 和 `@dsh-genui/sdk`，其他包会被构建器拒绝。

**Q: 怎么卸载这个插件？**

A: 运行 `dsh plugin --profile web remove github:pengyue-polaron/deepseek-harness-genui` 并重启 dsh web；存放在 `.dsh/genui` 下的工件记录和状态会随 7 天 TTL 到期自动清理。

## 上手难度
进阶 — 普通用户不需要写代码，只要在 prompt 中描述任务并明确"做一个可交互界面"即可触发；想让 Agent 把界面改得更合适，最好熟悉 React + TypeScript，以及插件的 7 个工具和 `useArtifactState` / `callTool` / `reportResult` / `requestExternal` / `watchTool` / `artifactContext` SDK 接口。

## 已知问题与限制
- 生成代码允许的 npm 包被白名单限定为 react、react-dom/client、lucide-react、recharts、date-fns、zustand、framer-motion 和虚拟模块 @dsh-genui/sdk；其他依赖会被构建器直接报错，无法在生成代码里用 lodash、axios、three 等（src/artifacts/builder.ts:7-17）
- 单次工件源码默认上限 1 MiB、最小 16 KiB、最大 16 MiB，且必须包含 src/main.tsx；任何 `..`、绝对路径或 `index.html` 都会被拒绝（src/config.ts:18, src/artifacts/paths.ts:13-25, src/artifacts/registry.ts:36-37）
- 工具调用发现预算硬编码：每个数据源最多 2 次发现、4 次读取，单轮最多 6 次读取；超出后 Agent 必须基于已有证据继续，不能换查询绕开（src/runtime/discovery-budget.ts:5-7, 71-73）
- 外部 HTTPS 请求被限制为无凭据、无 hash、无 query 凭据的公开主机，DNS 解析过滤 10/127/192.168/172.16-31 等私网段，响应体上限 1 MiB、单次超时 30 秒（src/runtime/external.ts:13-40, 70-84, 99-106）
- 工件状态和权限授予 7 天后过期；每个工件最多保留 20 个版本，超出后自动清理非当前、非最新版本（src/lifecycle.ts:1-3, src/artifacts/registry.ts:311-323）
- 仅 web profile 注入客户端组件（client.runtime / client.locale / client.ui-conversation / client.ui-tool）；TUI profile 可用但不会嵌入 Canvas，只能返回 localhost 链接（package.json:121-129, README.md:111）
- 同一个工件可调用工具的调用超时硬限制为 60 秒、外部 HTTPS 30 秒、超大请求体会被直接拒绝；生成代码运行在沙箱 iframe 里，跨域管理接口会被 403 拦截（src/runtime/server.ts:208-218, 311, 337）

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [deepseek-harness-genui](https://deepseek-plugin.org/plugins/pengyue-polaron/deepseek-harness-genui)
Wiki generated by AI (model: `MiniMax-M3`)
