跳到主要内容

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"]

关键服务

服务职责
DesignProjectServiceDesign 项目(= chat_sessions[kind='design'])的元数据 CRUD:选定的 Skill、DS、craft 子集。
DesignProjectMaterializersession 创建时把所选 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 多页打包。
DeckExportServiceDeck 专用导出(Reveal.js 风格幻灯片包)。
SkillSymlinker把 session 工作区下的 skills 软链到 <userData>/elftia/design-skills/ —— 让 Skill 编辑实时反映到正在跑的 session。
TinyElfSkillsParserAdapterTinyElf 引擎专用 —— 把 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' 区分图标,但和普通会话同列表

仅有的差异点:

DesignChat
Persona必须是 DesignStudio任意
Backend必须注册 Design backend任意
工作区session 创建时 materialize
Artifact 服务自动持久化每个产物不参与

子页面

  • 内置资源同步流程 —— resources/design-studio-builtin.lock.json + scripts/sync-design-studio.mjs 的完整流程,包括如何升级到上游最新 commit