PRD:dsh-design(DSH 原型画布)
August 21, 2026 · View on GitHub
| 字段 | 值 |
|---|---|
| 产品 | dsh-design |
| 版本 | MVP 0.1 |
| 状态 | Approved for implementation |
| 仓库 | 本仓库(开源 MIT bundle) |
| 日期 | 2026-08-20 |
1. Executive Summary
问题。 在 DeepSeek Harness 里做界面,Agent 只能在聊天里丢 HTML 代码块。用户看不见真实交互,也无法自己点一遍登录、切 tab、弹窗。Tutti 的 Prototype Design(vibe-design)解决了「可点原型」,但它是第二套 Agent 运行时,和 DSH 会话抢控制权。
方案。 做一个官方形态的 DSH bundle:聊天仍只用当前 DSH 会话。插件提供 Agent 可调用的工具,把可点击的 HTML 写进当前 workspace;预览挂在已安装的 dsh-better-sidebar 的「原型」tab。用户在侧边栏点交互,要改就回到同一个输入框。
成功标准。 用户说「做个登录页」→ Agent 调用工具写出 HTML → 侧边栏原型 tab 能打开并能点提交/校验;用户说「按钮再大」→ Agent 覆写同一文件 → 预览更新。全程不出现第二套对话框,不拉起 Claude / Codex。
2. Problem Definition
2.1 用户问题
- Who:在 DSH 里同时写产品和前端的开发者 / 设计师 / PM;已装 better-sidebar。
- What:需要「能点的原型」,而不是聊天里的代码块。
- When:探索界面、对齐交互、给 Agent 视觉反馈的时候。
- Where:DSH Desktop / web profile 的当前 workspace。
- Why:DSH 有模型和写文件,没有设计画布;把 vibe-design 整仓搬过来会引入第二套 Agent。
- Impact:不解决就继续复制粘贴、截图、口头描述按钮位置。
2.2 非目标市场
不是 Tutti 多 Agent 工作台,也不是 Figma。不做多人实时、不做设计系统后台、不做从零实现的独立 IDE。
3. Solution Overview
3.1 一句话
聊天还是 DSH,画布挂在 better-sidebar。
3.2 用户旅程
用户在 DSH 输入框:「做个移动端登录页,要有忘记密码」
│
▼
当前会话 Agent
design_status → design_create → design_write(index.html) → design_open
│
▼
workspace/.dsh-design/projects/<id>/index.html
│
▼
better-sidebar「原型」tab(+ 菜单可手动打开)
拉取 snapshot → loopback 静态预览 iframe 渲染 → 用户自己点
│
▼
用户:「主按钮再大,错误态用红字」
│
▼
同一会话 Agent 再 design_write → 预览按 revision 刷新
3.3 In Scope(MVP / P0)
| ID | 能力 | 优先级 |
|---|---|---|
| FR1 | Host 工具:创建项目、写 HTML、列出文件、打开预览、查看状态 | P0 |
| FR2 | 产物落在当前 workspace 的 .dsh-design/,可进 git | P0 |
| FR3 | ctx.systemPrompt.section 指导 Agent:自包含可运行 HTML,不要空谈 | P0 |
| FR4 | better-sidebar 注册单实例 tab dsh-design:prototype | P0 |
| FR5 | tab 内 iframe 预览当前页,用户可点 | P0 |
| FR6 | 未安装 better-sidebar 时插件不崩,工具仍能写文件 | P0 |
| FR7 | 官方 bundle 契约:dsh.bundle.patch + dsh.client,不改 DSH 源码 | P0 |
3.4 Out of Scope
- 第二套 Agent / ACP / 再拉起 Claude Code 或 Codex
- 插件内聊天窗、项目仪表盘、属性检查器、画布就地改 HTML
- 任何官方 UI 槽:
sidebar.footer.action、shell.overlay、官方 sidebar。唯一入口是 better-sidebar 的「原型」tab - 16 套设计系统管理后台(MVP 只在 system prompt 里给生成约束)
- 批注钉点:已做坐标 sidecar;截图 / DOM 锚定仍不在本迭代
- 多页相对资源:已做;最多两层目录(css/app.css、assets/logo.png)
- value-import
dsh-better-sidebar或@deepseek-ai/schemastery
3.5 MVP 完成定义
pnpm test(或node --test)在无 DSH peer 时跳过 Host 注册、在有 store 时全绿。- 工具能在临时目录创建项目并写出可解析的 HTML。
- Client bundle 是
window.__ModuleLoader__.load,软挂betterSidebar。 - README 写清:聊天框设计 → 侧边栏点。
4. User Stories
US1 — 用聊天生成可点原型
As a DSH 用户,I want 在输入框里让当前 Agent 设计界面,So that 我不用离开会话去别的设计工具。
Acceptance:
- Agent 使用
design_*工具,而不是只在聊天里贴一大段未落盘代码 -
.dsh-design/projects/<id>/下有project.json和至少一个.html - 不出现插件自己的 composer
US2 — 在侧边栏点交互
As a 已安装 better-sidebar 的用户,I want 在右侧「原型」tab 里点这个页面,So that 我能验证登录、tab、弹窗是否真的能用。
Acceptance:
-
+菜单有「原型」/ Prototype - 当前打开的 HTML 在沙箱 iframe 里运行脚本和表单
- tab 不可见时不轮询
US3 — 同一会话里改稿
As a 用户,I want 看完再说「改这里」,So that 上下文不丢。
Acceptance:
- Agent 覆写同一文件后
current.revision变化 - 打开的 tab 刷新预览,不必手动重建项目
US4 — 没装 better-sidebar 也不炸
As a 只装了本插件的用户,I want Agent 仍然能把 HTML 写进仓库,So that 我可以用浏览器或别的预览打开文件。
Acceptance:
-
betterSidebar不在静态inject里 - 服务缺失时注册跳过
- Host 工具与 RPC 仍可用
5. Functional Requirements
| ID | 需求 | 优先级 |
|---|---|---|
| FR-T1 | design_status:当前 workspace 的项目列表与 current 预览 | P0 |
| FR-T2 | design_create:按标题建项目 | P0 |
| FR-T3 | design_write:向项目写入文本文件(默认 .html);open 默认 true | P0 |
| FR-T4 | design_list:列出项目内页面 | P0 |
| FR-T5 | design_open:把某 HTML 标为当前预览并 bump revision | P0 |
| FR-P1 | 路径限制在 <cwd>/.dsh-design/**,拒绝 .. 与绝对路径 | P0 |
| FR-P2 | 文件名 ^[A-Za-z0-9._-]{1,128}$,扩展名 html|css|js|svg|png|jpg|gif|webp|ico | P0 |
| FR-P3 | 单文件上限 512KiB;超限失败,不截断装成成功 | P0 |
| FR-U1 | Client RPC snapshot / file,payload 带 cwd | P0 |
| FR-U2 | iframe sandbox="allow-scripts allow-forms",无 allow-same-origin | P0 |
| FR-U3 | 预览用 loopback 静态服务 iframe src(相对资源可解析) | P0 |
| FR-S1 | better-sidebar tab id dsh-design:prototype,single: true,order 55 | P0 |
| FR-S2 | 通过 ctx.plugin({ inject: ['betterSidebar'] }) 子 fiber 挂载 | P0 |
6. Design & UX
6.1 原则
- 生成内容是主角:chrome 让路给 iframe。
- 文案说用户能做什么,不说 RPC / bundle。
- 空状态给下一步:「在聊天里描述一个界面」而不是「暂无数据」。
- 失败说清:cwd 没有、文件超限、项目不存在。
6.2 原型 tab 视觉
工作台是「灯箱」:暗色舞台托住一张白纸原型,而不是再做一套聊天皮肤。
| Token | Hex | 用途 |
|---|---|---|
| stage | #252A32 | tab 底 |
| brass | #C9A36A | 唯一强调:当前页标记、空状态短线 |
| ink | #E8EDF2 | 主文字 |
| dim | #8B95A1 | 次级文字 |
| rule | #3A424C | 分割 |
| paper | #F7F5F2 | iframe 周围纸边 |
字体:界面用系统 UI 栈;文件名用 ui-monospace。不加载网页字体。
结构:
┌ title · 页名 刷新 ┐
│ [page] [page] │
│ ┌──────────────────────────────────┐ │
│ │ iframe stage │ │
│ └──────────────────────────────────┘ │
签名元素:舞台四角的铜质定位十字,让它像印前灯箱而不是普通网页预览器。
6.3 空 / 错
- 无项目:「还没有原型。在左边聊天里说要做什么界面。」
- 无 better-sidebar:不渲染 tab;工具结果里提示文件路径。
- RPC 失败:「读不了当前工作区的原型文件。」 + 重试。
7. Technical Specifications
7.1 契约
package.json:dsh.bundle.patch、dsh.client.platform=web、exports["."]与exports["./client"]- Host:
name、inject: ["tools","systemPrompt"]、apply;省略Config,不 import schemastery - YAML
config仍可作为 plain object 进入apply - Client:
window.__ModuleLoader__.loadlazy-CJS;inject: ["connection"] dsh-better-sidebar:optional,运行时探测,禁止 value-import- 不改 DSH 源码、不改 better-sidebar 源码
7.2 数据
<cwd>/.dsh-design/
current.json { projectId, file, title, revision, updatedAt }
projects/<id>/
project.json { id, title, entry, createdAt, updatedAt }
index.html
revision 为单调整数,每次 design_write(open) / design_open 加一,供 UI 刷新。
7.3 RPC
Channel /design,authority: "loopback",永不抛出;返回 { ok, value | error }。
| endpoint | payload | value |
|---|---|---|
snapshot | { cwd } | 项目列表 + current |
file | { cwd, projectId, name } | { content, mime } |
7.4 Agent 工具约定
写出的 HTML 必须:
- 完整文档(
<!DOCTYPE html>) - CSS/JS 内联,可单独在 iframe 里点
- 真实控件,而不是截图
- 语言跟随用户
禁止:
- 再开 Agent
- 只回复「这是设计思路」而不写文件
- 把文件写到
.dsh-design之外(除非用户明确要求落地到产品代码,那时用内置 fs,不走本插件)
8. Risks
| 风险 | 缓解 |
|---|---|
link: 安装解析不到 @deepseek-ai/dsh-tools | 不 import 该包;ctx.tools.register 直接挂普通对象 |
better-sidebar 未装或版本无 registerTab | 子 fiber + 特性探测,失败跳过 |
| Desktop webview 拦 loopback | iframe 走 127.0.0.1 + token 路径;失败再考虑降级 |
| iframe 脚本攻击父页 | 无 allow-same-origin |
| 范围膨胀成 vibe-design | 本 PRD 的 Out of Scope 作为拒绝清单 |
9. 后续(非本迭代)
- 发现流程:第一份 HTML 前必须有 platform / viewport / look(已做)
- 多页相对资源:loopback 预览 + 最多两层目录(已做)
- 设计系统样例页 paper/ink(已做);管理后台仍不做
- 批注选择器(已做);截图仍不做
- 只读设计系统目录(从 vibe-design 思路借鉴,不复制资产除非许可清晰)
- 批注、多页资源、设计系统目录仍走 Prototype tab,不新增官方 slot
10. 决策记录
- 一套 Agent:只使用当前 DSH 会话。
- UI 入口只在 better-sidebar:tab
dsh-design:prototype。禁止sidebar.footer.action/shell.overlay/ 官方 sidebar。未装 better-sidebar 时不注册 UI,Host 工具仍写文件。 - 不是 vibe-design fork:新 bundle,MIT。
- 文件在 workspace:
.dsh-design/,不用插件私有 SQLite。