Обзор архитектуры Design Studio
Design Studio на базовом уровне переиспользует систему чата (chat_sessions + EngineDispatcher), поверх которой добавлен набор сервисов домена дизайна. На этой странице описан общий конвейер, а подробные разборы отдельных компонентов вынесены на дочерние страницы.
Расположение модуля
- Renderer:
packages/renderer/src/features/design-studio/components/design-studio/ - Сервисы главного процесса:
packages/desktop/app/main/services/content/workspace/design/ - Встроенные ресурсы (не в git):
resources/design-studio-builtin/— см. Процесс синхронизации встроенных ресурсов - Закрепление встроенных ресурсов:
resources/design-studio-builtin.lock.json(единственная часть в git)
Поток данных
graph TB
User["User selects Skill + DS in new session page, enters requirements"] --> Persona["DesignStudio persona"]
Persona --> Create["AgentRouter.createSession<br/>kind='design'"]
Create --> DPS["DesignProjectService<br/>Create project metadata"]
Create --> DPM["DesignProjectMaterializer<br/>Copy Skill / DS into session workspace"]
DPS --> ChatSess["chat_sessions row<br/>(kind='design')"]
DPM --> Workspace["session workspace directory<br/>(skills + design-system + craft)"]
ChatSess --> Disp["EngineDispatcher"]
Disp --> Adapter["Design Backend adapter<br/>(per-engine)"]
Workspace --> Adapter
Adapter --> Engine["TinyElf / ClaudeSdk / CliRunner"]
Engine --> Out["AI output artifact"]
Out --> AS["ArtifactService<br/>Persist artifact"]
AS --> ALS["ArtifactLintService<br/>Validate token / boundaries"]
AS --> AES["ArtifactExportService<br/>HTML/PNG/PDF/Deck"]
Ключевые сервисы
| Сервис | Ответственность |
|---|---|
DesignProjectService | CRUD метаданных Design-проекта (= chat_sessions[kind='design']): выбранные Skill, DS, подмножество craft. |
DesignProjectMaterializer | При создании сессии копирует выбранные Skill / DS / craft в рабочую область конкретной сессии, предоставляя движку чистое представление только для чтения. |
SkillDiscoveryService | Сканирует пользовательский каталог и встроенный каталог на наличие манифестов skill, объединяет их и удаляет дубликаты. |
DesignSystemService | То же самое для дизайн-систем: таблицы token, ссылки на компоненты, рендеринг примеров. |
CraftService | Предоставляет соединяемые фрагменты HTML/CSS/SVG. |
ArtifactService | Записывает и читает файлы artifact (продукты), связывает их с конкретным сообщением. |
ArtifactLintService | Проверяет артефакты: цвета в пределах DS token, корректность стеков шрифтов, базовый уровень доступности и т. д. |
ArtifactExportService | Экспорт артефактов: встроенный HTML, скриншот Puppeteer (PNG/JPG/PDF), многостраничная упаковка Deck. |
DeckExportService | Экспорт, специфичный для Deck (пакет презентации в стиле Reveal.js). |
SkillSymlinker | Создает символьные ссылки для skills из рабочей области сессии в <userData>/elftia/design-skills/ — изменения Skill сразу отражаются в работающей сессии. |
TinyElfSkillsParserAdapter | Специфично для движка TinyElf — преобразует Design Skill в формат tools/context, потребляемый TinyElf. |
backends/ | Каталог адаптеров по движкам. Каждый движок должен реализовать собственный backend, чтобы работать в Design-режиме. |
prompts/ | Встроенные системные промпты (из upstream open-design), разбитые по типам Skill. |
mcp/ | Экспонирование MCP-инструментов, специфичных для Design-режима. |
Адаптация движка (Design Backend)
Не каждый движок может запускать Design-проекты. Backend-адаптеры в каталоге backends/ устроены по принципу реестра: движки, которые хотят поддерживать Design-режим, должны явно зарегистрировать backend.
// Simplified signature
interface DesignBackend {
engineType: EngineType;
prepareSession(ctx, project): Promise<DesignContext>;
// …
}
Для движков без зарегистрированного backend renderer-хук useDesignStudioGate() возвращает unavailable, а главная страница и панель новой сессии деградируют до placeholder UI (без сбоя на половине экрана).
Связь Artifact и сообщения
Каждое AI-сообщение, создающее artifact, привязывается к ID артефакта (записывается в metadata сообщения):
- Персистентность:
<userData>/elftia/design-artifacts/<sessionId>/<artifactId>.html - Renderer читает по
artifactId, у отдельного сообщения есть кнопка Preview - "Open workspace" автоматически привязывает последний artifact текущей сессии; нажатие Preview у старого сообщения воспроизводит историческую версию в рабочей области
Это естественным образом поддерживает ветвление: каждая операция "regenerate" создает новый artifact, а старые версии не теряются.
Связь с чатом
Design-проекты по сути являются строками chat_sessions плюс набором связанных таблиц. Поэтому они:
- Используют тот же IPC (
chatSessions:*+agents:*) - Используют ту же диспетчеризацию движков (EngineDispatcher)
- Переиспользуют ту же логику ветвления сообщений, вложений и API Key Pool
- Отличаются в главной боковой панели значком
kind='design', но находятся в том же списке, что и обычные сессии
Единственные различия:
| Точка | Design | Chat |
|---|---|---|
| Persona | Должна быть DesignStudio | Любая |
| Backend | Должен зарегистрировать Design backend | Любой |
| Workspace | Материализуется при создании сессии | Нет |
| Artifact Service | Автоматически сохраняет каждый продукт | Не участвует |
Дочерние страницы
- Процесс синхронизации встроенных ресурсов — полный поток для
resources/design-studio-builtin.lock.json+scripts/sync-design-studio.mjs, включая способ обновления до последнего upstream commit