Design Studio 架构概览
Design Studio 在底层复用了聊天系统(chat_sessions + EngineDispatcher),上层叠加了一组设计领域服务。本页给出整体链路,单点深潜放在子页面。
模块定位
- 渲染端:
packages/renderer/src/features/design-studio/components/design-studio/ - 主进程服务:
packages/desktop/app/main/services/content/workspace/design/ - 内置资源(不入 git):
resources/design-studio-builtin/—— 见 内置资源同步流程 - 内置资源 pin:
resources/design-studio-builtin.lock.json(唯一入 git 的部分)
数据流
graph TB
User["用户在新会话页选 Skill + DS, 输入需求"] --> Persona["DesignStudio persona"]
Persona --> Create["AgentRouter.createSession<br/>kind='design'"]
Create --> DPS["DesignProjectService<br/>建项目元数据"]
Create --> DPM["DesignProjectMaterializer<br/>把 Skill / DS 拷进 session 工作区"]
DPS --> ChatSess["chat_sessions 行<br/>(kind='design')"]
DPM --> Workspace["session 工作区目录<br/>(skills + design-system + craft)"]
ChatSess --> Disp["EngineDispatcher"]
Disp --> Adapter["Design Backend 适配器<br/>(per-engine)"]
Workspace --> Adapter
Adapter --> Engine["TinyElf / ClaudeSdk / CliRunner"]
Engine --> Out["AI 输出 artifact"]
Out --> AS["ArtifactService<br/>持久化产物"]
AS --> ALS["ArtifactLintService<br/>校验 token / 边界"]
AS --> AES["ArtifactExportService<br/>HTML/PNG/PDF/Deck"]
关键服务
| 服务 | 职责 |
|---|---|
DesignProjectService | Design 项目(= chat_sessions[kind='design'])的元数据 CRUD:选定的 Skill、DS、craft 子集。 |
DesignProjectMaterializer | session 创建时把所选 Skill / DS / craft 复制到 session 专属工作区,给引擎一个干净的只读视图。 |
SkillDiscoveryService | 扫描用户目录 + builtin 目录下的 skill manifest,合并去重。 |
DesignSystemService | 同上但针对设计系统 —— token 表、组件参考、示例渲染。 |
CraftService | 提供可拼接的 HTML/CSS/SVG 片段。 |
ArtifactService | 写入 / 读取 artifact 文件(产物),关联到具体 message。 |
ArtifactLintService | 校验产物:颜色是否越出 DS token、字体栈是否合法、可访问性基线等。 |
ArtifactExportService | 产物导出 —— HTML 内联、Puppeteer 截图(PNG/JPG/PDF)、Deck 多页打包。 |
DeckExportService | Deck 专用导出(Reveal.js 风格幻灯片包)。 |
SkillSymlinker | 把 session 工作区下的 skills 软链到 <userData>/elftia/design-skills/ —— 让 Skill 编辑实时反映到正在跑的 session。 |
TinyElfSkillsParserAdapter | TinyElf 引擎专用 —— 把 Design Skill 翻译为 TinyElf 能消费的工具/上下文格式。 |
backends/ | per-engine 适配器目录。每个引擎需要自己实现一个 backend 才能在 Design 模式下跑通。 |
prompts/ | 内置系统提示词(来自上游 open-design),按 Skill 类型裁切。 |
mcp/ | Design 模式专用的 MCP 工具暴露。 |
引擎适配(Design Backend)
不是每个引擎都能跑 Design 项目。backends/ 目录下的 backend 适配器是注册表式的 —— 引擎要支持 Design 模式必须显式注册一个 backend。
// 简化签名
interface DesignBackend {
engineType: EngineType;
prepareSession(ctx, project): Promise<DesignContext>;
// …
}
未注册 backend 的引擎,渲染端 useDesignStudioGate() 会返回 unavailable,主页与新会话面板降级为占位 UI(不会半截崩)。
Artifact 与消息绑定
每条产生 artifact 的 AI 消息绑定到一个 artifact ID(写在 message metadata 里):
- 持久化:
<userData>/elftia/design-artifacts/<sessionId>/<artifactId>.html - 渲染端按
artifactId读取,单条消息上挂一个 Preview 按钮 - "打开 workspace" 自动绑当前 session 最新的 artifact;点旧消息的 Preview 会回放历史版本到工作区
这让产物天然支持分支:每次"重新生成"产生一个新 artifact,旧版本不会丢。
与聊天的关系
Design 项目本质是 chat_sessions 行 + 一组关联表。所以:
- 走同一套 IPC(
chatSessions:*+agents:*) - 走同一套引擎分发(EngineDispatcher)
- 复用同一套消息分支、附件、API Key Pool 逻辑
- 在主侧边栏里以
kind='design'区分图标,但和普通会话同列表
仅有的差异点:
| 点 | Design | Chat |
|---|---|---|
| Persona | 必须是 DesignStudio | 任意 |
| Backend | 必须注册 Design backend | 任意 |
| 工作区 | session 创建时 materialize | 无 |
| Artifact 服务 | 自动持久化每个产物 | 不参与 |
子页面
- 内置资源同步流程 ——
resources/design-studio-builtin.lock.json+scripts/sync-design-studio.mjs的完整流程,包括如何升级到上游最新 commit