@agent-native/core 0.80.4 → 0.80.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +21 -2
  3. package/corpus/core/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
  4. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -1
  5. package/corpus/core/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
  6. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -1
  7. package/corpus/core/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
  8. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -1
  9. package/corpus/core/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
  10. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -1
  11. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -1
  12. package/corpus/core/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
  13. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -1
  14. package/corpus/core/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
  15. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -1
  16. package/corpus/core/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
  17. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -1
  18. package/corpus/core/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
  19. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -1
  20. package/corpus/core/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
  21. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -1
  22. package/corpus/core/docs/content/real-time-collaboration.mdx +2 -2
  23. package/corpus/core/docs/content/template-design.mdx +1 -1
  24. package/corpus/core/package.json +3 -7
  25. package/corpus/core/src/action.ts +21 -0
  26. package/corpus/core/src/agent/durable-background.ts +32 -11
  27. package/corpus/core/src/agent/production-agent.ts +11 -1
  28. package/corpus/core/src/agent/run-loop-with-resume.ts +3 -1
  29. package/corpus/core/src/brand-kit/fig/index.ts +17 -37
  30. package/corpus/core/src/cli/index.ts +1 -1
  31. package/corpus/core/src/cli/mcp-config-writers.ts +187 -51
  32. package/corpus/core/src/cli/skills.ts +18 -3
  33. package/corpus/core/src/client/AssistantChat.tsx +11 -1
  34. package/corpus/core/src/client/agent-chat.ts +12 -1
  35. package/corpus/core/src/client/composer/PromptComposer.tsx +100 -41
  36. package/corpus/core/src/client/org/OrgSwitcher.tsx +1 -1
  37. package/corpus/core/src/client/sharing/ShareButton.tsx +3 -27
  38. package/corpus/core/src/collab/presence.ts +1 -1
  39. package/corpus/core/src/mcp/connect-route.ts +34 -5
  40. package/corpus/core/src/server/action-discovery.ts +4 -0
  41. package/corpus/core/src/server/agent-chat-plugin.ts +20 -0
  42. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -0
  43. package/corpus/templates/analytics/actions/update-dashboard.ts +8 -0
  44. package/corpus/templates/analytics/app/components/layout/Layout.tsx +1 -1
  45. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +117 -33
  46. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +4 -0
  47. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +7 -0
  48. package/corpus/templates/analytics/changelog/2026-06-27-dashboards-can-now-nest-under-a-parent-in-the-sidebar-via-a-.md +6 -0
  49. package/corpus/templates/analytics/changelog/2026-06-29-analytics-pages-now-sit-closer-under-the-header-with-tighter.md +6 -0
  50. package/corpus/templates/assets/actions/generate-image-batch.ts +3 -0
  51. package/corpus/templates/assets/actions/generate-image.ts +3 -0
  52. package/corpus/templates/assets/changelog/2026-06-29-longer-agent-generation-window.md +6 -0
  53. package/corpus/templates/assets/netlify.toml +3 -3
  54. package/corpus/templates/assets/server/plugins/agent-chat.ts +4 -1
  55. package/corpus/templates/clips/app/components/capture-install-options.tsx +7 -8
  56. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +1 -1
  57. package/corpus/templates/content/AGENTS.md +12 -0
  58. package/corpus/templates/content/app/blocks/BuilderDocsBlocks.tsx +10 -0
  59. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +1 -0
  60. package/corpus/templates/content/app/components/editor/ContentReferencePreview.tsx +185 -0
  61. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +3 -0
  62. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +19 -0
  63. package/corpus/templates/content/app/components/editor/extensions/ContentReferenceNode.tsx +82 -0
  64. package/corpus/templates/content/app/global.css +9 -0
  65. package/corpus/templates/content/app/i18n/zh-TW.ts +12 -0
  66. package/corpus/templates/content/app/i18n-data.ts +140 -0
  67. package/corpus/templates/content/changelog/2026-06-29-reusable-mdx-references-now-preview-linked-local-documents-i.md +6 -0
  68. package/corpus/templates/content/shared/builder-docs-blocks.ts +8 -0
  69. package/corpus/templates/content/shared/builder-mdx.ts +141 -4
  70. package/corpus/templates/content/shared/nfm.ts +62 -0
  71. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +10 -11
  72. package/corpus/templates/design/AGENTS.md +5 -0
  73. package/corpus/templates/design/_gitignore +7 -0
  74. package/corpus/templates/design/actions/apply-visual-edit.ts +22 -12
  75. package/corpus/templates/design/actions/create-design-system.ts +15 -4
  76. package/corpus/templates/design/actions/create-file.ts +20 -1
  77. package/corpus/templates/design/actions/delete-design-system.ts +2 -2
  78. package/corpus/templates/design/actions/duplicate-design.ts +35 -9
  79. package/corpus/templates/design/actions/generate-design.ts +146 -69
  80. package/corpus/templates/design/actions/generate-screens.ts +51 -19
  81. package/corpus/templates/design/actions/get-design-snapshot.ts +5 -1
  82. package/corpus/templates/design/actions/get-design.ts +2 -0
  83. package/corpus/templates/design/actions/import-design-project.ts +28 -9
  84. package/corpus/templates/design/actions/import-document.ts +22 -8
  85. package/corpus/templates/design/actions/index-design-system-with-builder.ts +6 -153
  86. package/corpus/templates/design/actions/navigate.ts +105 -54
  87. package/corpus/templates/design/actions/set-default-design-system.ts +17 -3
  88. package/corpus/templates/design/actions/show-design-questions.ts +2 -0
  89. package/corpus/templates/design/actions/update-design.ts +2 -1
  90. package/corpus/templates/design/actions/view-screen.ts +12 -6
  91. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +4 -4
  92. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +159 -41
  93. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +8 -4
  94. package/corpus/templates/design/app/components/design/DrawOverlay.tsx +37 -42
  95. package/corpus/templates/design/app/components/design/EditPanel.tsx +336 -183
  96. package/corpus/templates/design/app/components/design/LayersPanel.tsx +153 -34
  97. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +135 -33
  98. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +6 -0
  99. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +2 -1
  100. package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +4 -10
  101. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +84 -43
  102. package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +4 -4
  103. package/corpus/templates/design/app/components/design/inspector/{FigmaColorPicker.tsx → DesignColorPicker.tsx} +89 -62
  104. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +14 -26
  105. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +40 -12
  106. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +13 -4
  107. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +13 -13
  108. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +13 -9
  109. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +13 -4
  110. package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +6 -6
  111. package/corpus/templates/design/app/components/design/inspector/{figma-icons.tsx → design-icons.tsx} +2 -2
  112. package/corpus/templates/design/app/components/design/inspector/index.ts +12 -12
  113. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +5 -2
  114. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -3
  115. package/corpus/templates/design/app/components/layout/Layout.tsx +5 -2
  116. package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
  117. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +167 -91
  118. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +16 -3
  119. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +15 -0
  120. package/corpus/templates/design/app/global.css +4 -0
  121. package/corpus/templates/design/app/hooks/use-design-system.ts +4 -1
  122. package/corpus/templates/design/app/hooks/use-navigation-state.ts +38 -3
  123. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +9 -2
  124. package/corpus/templates/design/app/i18n/zh-TW.ts +22 -0
  125. package/corpus/templates/design/app/i18n-data.ts +527 -0
  126. package/corpus/templates/design/app/lib/design-systems.ts +6 -4
  127. package/corpus/templates/design/app/lib/design-templates.ts +15 -3
  128. package/corpus/templates/design/app/pages/DesignEditor.tsx +641 -158
  129. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +42 -34
  130. package/corpus/templates/design/app/pages/VisualEdit.tsx +100 -0
  131. package/corpus/templates/design/app/root.tsx +42 -9
  132. package/corpus/templates/design/app/routes/visual-edit.tsx +7 -0
  133. package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +1 -1
  134. package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +1 -1
  135. package/corpus/templates/design/changelog/2026-06-28-visual-code-design-mode.md +6 -0
  136. package/corpus/templates/design/changelog/2026-06-29-design-generation-prompts-now-show-connect-ai-before-sending.md +6 -0
  137. package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +1 -1
  138. package/corpus/templates/design/changelog/2026-06-29-fixed-design-editor-exports-and-gradient-edits-so-multi-scre.md +6 -0
  139. package/corpus/templates/design/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
  140. package/corpus/templates/design/changelog/2026-06-29-png-export-handles-modern-css-color-functions-more-reliably.md +6 -0
  141. package/corpus/templates/design/changelog/2026-06-29-png-export-now-ignores-duplicate-clicks-while-a-download-is-.md +6 -0
  142. package/corpus/templates/design/changelog/2026-06-29-public-visual-edit-and-shared-design-links-now-invite-visito.md +6 -0
  143. package/corpus/templates/design/changelog/2026-06-29-visual-edit-actions-now-reject-missing-design-targets-before.md +6 -0
  144. package/corpus/templates/design/e2e/README.md +71 -0
  145. package/corpus/templates/design/e2e/global-setup.ts +157 -0
  146. package/corpus/templates/design/e2e/helpers.ts +148 -0
  147. package/corpus/templates/design/netlify.toml +3 -4
  148. package/corpus/templates/design/package.json +5 -1
  149. package/corpus/templates/design/playwright.config.ts +51 -0
  150. package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +121 -0
  151. package/corpus/templates/design/server/handlers/uploads.ts +89 -38
  152. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +181 -0
  153. package/corpus/templates/design/server/lib/coding-handoff.ts +33 -4
  154. package/corpus/templates/design/server/lib/design-export.ts +35 -8
  155. package/corpus/templates/design/server/plugins/agent-chat.ts +4 -0
  156. package/corpus/templates/design/server/plugins/auth.ts +10 -1
  157. package/corpus/templates/design/server/routes/api/index-design-system-with-builder.post.ts +1 -0
  158. package/corpus/templates/design/shared/api.ts +2 -0
  159. package/corpus/templates/design/shared/apply-edits.ts +12 -8
  160. package/corpus/templates/design/shared/canvas-math.ts +19 -1
  161. package/corpus/templates/design/shared/code-layer.ts +87 -28
  162. package/corpus/templates/design/shared/generation-session.ts +1 -0
  163. package/corpus/templates/design/shared/resolve-tweaks.ts +4 -3
  164. package/corpus/templates/design/shared/shader-presets.ts +10 -0
  165. package/corpus/templates/design/shared/source-mode.ts +9 -0
  166. package/corpus/templates/design/vitest.config.ts +2 -1
  167. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +1 -1
  168. package/corpus/templates/plan/.agents/skills/visual-plan/references/canvas.md +1 -1
  169. package/corpus/templates/plan/AGENTS.md +1 -1
  170. package/corpus/templates/plan/actions/create-plan-design.ts +1 -1
  171. package/corpus/templates/plan/actions/validate-local-plan-source.ts +2 -10
  172. package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -0
  173. package/corpus/templates/plan/docs/commenting-ux-plan.md +2 -2
  174. package/corpus/templates/plan/server/plan-content.ts +1 -1
  175. package/corpus/templates/plan/server/ui-plan-html.ts +2 -2
  176. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +6 -153
  177. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +53 -38
  178. package/corpus/templates/slides/app/components/design-system/{fig-import-response.ts → builder-index-response.ts} +9 -6
  179. package/corpus/templates/slides/app/components/visual-editor/MultiSelectChip.tsx +1 -1
  180. package/corpus/templates/slides/changelog/2026-06-29-design-system-setup-now-indexes-uploaded-design-files-throug.md +6 -0
  181. package/corpus/templates/slides/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
  182. package/corpus/templates/slides/netlify.toml +3 -6
  183. package/corpus/templates/slides/server/handlers/index-design-system-with-builder.ts +116 -0
  184. package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +179 -0
  185. package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -1
  186. package/corpus/templates/slides/server/routes/api/index-design-system-with-builder.post.ts +1 -0
  187. package/dist/action.d.ts +15 -0
  188. package/dist/action.d.ts.map +1 -1
  189. package/dist/action.js +6 -0
  190. package/dist/action.js.map +1 -1
  191. package/dist/agent/durable-background.d.ts +9 -7
  192. package/dist/agent/durable-background.d.ts.map +1 -1
  193. package/dist/agent/durable-background.js +27 -11
  194. package/dist/agent/durable-background.js.map +1 -1
  195. package/dist/agent/production-agent.d.ts +7 -0
  196. package/dist/agent/production-agent.d.ts.map +1 -1
  197. package/dist/agent/production-agent.js +4 -1
  198. package/dist/agent/production-agent.js.map +1 -1
  199. package/dist/agent/run-loop-with-resume.d.ts +2 -1
  200. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  201. package/dist/agent/run-loop-with-resume.js +2 -2
  202. package/dist/agent/run-loop-with-resume.js.map +1 -1
  203. package/dist/brand-kit/fig/index.d.ts +4 -4
  204. package/dist/brand-kit/fig/index.d.ts.map +1 -1
  205. package/dist/brand-kit/fig/index.js +14 -27
  206. package/dist/brand-kit/fig/index.js.map +1 -1
  207. package/dist/cli/index.js +1 -1
  208. package/dist/cli/index.js.map +1 -1
  209. package/dist/cli/mcp-config-writers.d.ts +15 -7
  210. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  211. package/dist/cli/mcp-config-writers.js +198 -45
  212. package/dist/cli/mcp-config-writers.js.map +1 -1
  213. package/dist/cli/skills.d.ts +1 -1
  214. package/dist/cli/skills.d.ts.map +1 -1
  215. package/dist/cli/skills.js +18 -3
  216. package/dist/cli/skills.js.map +1 -1
  217. package/dist/client/AssistantChat.d.ts.map +1 -1
  218. package/dist/client/AssistantChat.js +11 -1
  219. package/dist/client/AssistantChat.js.map +1 -1
  220. package/dist/client/agent-chat.d.ts.map +1 -1
  221. package/dist/client/agent-chat.js +15 -2
  222. package/dist/client/agent-chat.js.map +1 -1
  223. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  224. package/dist/client/composer/PromptComposer.js +35 -1
  225. package/dist/client/composer/PromptComposer.js.map +1 -1
  226. package/dist/client/org/OrgSwitcher.js +1 -1
  227. package/dist/client/org/OrgSwitcher.js.map +1 -1
  228. package/dist/client/sharing/ShareButton.d.ts +1 -1
  229. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  230. package/dist/client/sharing/ShareButton.js +2 -15
  231. package/dist/client/sharing/ShareButton.js.map +1 -1
  232. package/dist/collab/presence.d.ts +1 -1
  233. package/dist/collab/presence.js +1 -1
  234. package/dist/collab/presence.js.map +1 -1
  235. package/dist/collab/routes.d.ts +1 -1
  236. package/dist/mcp/connect-route.d.ts.map +1 -1
  237. package/dist/mcp/connect-route.js +34 -5
  238. package/dist/mcp/connect-route.js.map +1 -1
  239. package/dist/notifications/routes.d.ts +3 -3
  240. package/dist/observability/routes.d.ts +3 -3
  241. package/dist/resources/handlers.d.ts +1 -1
  242. package/dist/server/action-discovery.d.ts.map +1 -1
  243. package/dist/server/action-discovery.js +5 -0
  244. package/dist/server/action-discovery.js.map +1 -1
  245. package/dist/server/agent-chat-plugin.d.ts +6 -0
  246. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  247. package/dist/server/agent-chat-plugin.js +12 -3
  248. package/dist/server/agent-chat-plugin.js.map +1 -1
  249. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  250. package/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
  251. package/docs/content/locales/ar-SA/template-design.mdx +1 -1
  252. package/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
  253. package/docs/content/locales/de-DE/template-design.mdx +1 -1
  254. package/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
  255. package/docs/content/locales/es-ES/template-design.mdx +1 -1
  256. package/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
  257. package/docs/content/locales/fr-FR/template-design.mdx +1 -1
  258. package/docs/content/locales/hi-IN/template-design.mdx +1 -1
  259. package/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
  260. package/docs/content/locales/ja-JP/template-design.mdx +1 -1
  261. package/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
  262. package/docs/content/locales/ko-KR/template-design.mdx +1 -1
  263. package/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
  264. package/docs/content/locales/pt-BR/template-design.mdx +1 -1
  265. package/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
  266. package/docs/content/locales/zh-CN/template-design.mdx +1 -1
  267. package/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
  268. package/docs/content/locales/zh-TW/template-design.mdx +1 -1
  269. package/docs/content/real-time-collaboration.mdx +2 -2
  270. package/docs/content/template-design.mdx +1 -1
  271. package/package.json +3 -7
  272. package/corpus/core/src/brand-kit/fig/decode.ts +0 -410
  273. package/corpus/core/src/brand-kit/fig/extract-design-system.ts +0 -947
  274. package/corpus/core/src/brand-kit/fig/fig-to-html.ts +0 -1906
  275. package/corpus/templates/design/actions/import-figma.ts +0 -55
  276. package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +0 -6
  277. package/corpus/templates/design/server/handlers/import-figma-system.ts +0 -86
  278. package/corpus/templates/design/server/routes/api/import-figma-system.post.ts +0 -1
  279. package/corpus/templates/slides/server/handlers/import-figma-system.ts +0 -101
  280. package/corpus/templates/slides/server/routes/api/import-figma-system.post.ts +0 -1
  281. package/dist/brand-kit/fig/decode.d.ts +0 -33
  282. package/dist/brand-kit/fig/decode.d.ts.map +0 -1
  283. package/dist/brand-kit/fig/decode.js +0 -358
  284. package/dist/brand-kit/fig/decode.js.map +0 -1
  285. package/dist/brand-kit/fig/extract-design-system.d.ts +0 -44
  286. package/dist/brand-kit/fig/extract-design-system.d.ts.map +0 -1
  287. package/dist/brand-kit/fig/extract-design-system.js +0 -752
  288. package/dist/brand-kit/fig/extract-design-system.js.map +0 -1
  289. package/dist/brand-kit/fig/fig-to-html.d.ts +0 -246
  290. package/dist/brand-kit/fig/fig-to-html.d.ts.map +0 -1
  291. package/dist/brand-kit/fig/fig-to-html.js +0 -1506
  292. package/dist/brand-kit/fig/fig-to-html.js.map +0 -1
@@ -765,6 +765,16 @@ export function validateDescriptor(descriptor: ShaderDescriptor): {
765
765
  if (def.max !== undefined && num > def.max) {
766
766
  errors.push(`Param "${key}" value ${num} is above maximum ${def.max}`);
767
767
  }
768
+ } else if (def.kind === "enum") {
769
+ if (def.options && !def.options.includes(value as string)) {
770
+ errors.push(
771
+ `Param "${key}" value "${value}" is not in allowed options: ${def.options.join(", ")}`,
772
+ );
773
+ }
774
+ } else if (def.kind === "bool") {
775
+ if (typeof value !== "boolean") {
776
+ errors.push(`Param "${key}" must be a boolean`);
777
+ }
768
778
  }
769
779
  }
770
780
 
@@ -213,8 +213,17 @@ export function normalizeDesignSourceType(
213
213
  export function makeLocalhostRouteId(path: string): string {
214
214
  const normalized = path.trim() || "/";
215
215
  if (normalized === "/") return "route-root";
216
+ // Pure wildcard routes ("/*", "/**") collapse to a single id.
217
+ if (/^\/\*+$/.test(normalized)) return "route-wildcard";
218
+ // Encode structural characters distinctly BEFORE collapsing non-alphanumerics,
219
+ // otherwise paths like "/design/:id" and "/design-id", or "/users" and
220
+ // "/users/*", produce identical ids and silently overwrite each other in the
221
+ // route manifest map.
216
222
  const slug = normalized
217
223
  .replace(/^\/+/, "")
224
+ .replace(/\*/g, "w") // wildcard segment
225
+ .replace(/:/g, "p") // route param prefix (":id" -> "pid")
226
+ .replace(/[[\]]/g, "") // strip [id] bracket syntax
218
227
  .replace(/[^a-zA-Z0-9]+/g, "-")
219
228
  .replace(/^-+|-+$/g, "")
220
229
  .toLowerCase();
@@ -9,6 +9,7 @@ export default {
9
9
  },
10
10
  test: {
11
11
  include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
12
- exclude: ["**/node_modules/**", "**/.git/**", "**/dist/**"],
12
+ // e2e/ holds Playwright (@playwright/test) specs; run via `pnpm e2e`, not vitest.
13
+ exclude: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/e2e/**"],
13
14
  },
14
15
  };
@@ -1317,7 +1317,7 @@ function AppLayoutInner({ children }: AppLayoutProps) {
1317
1317
  <TooltipContent>{t("mail.toolbar.composeShortcut")}</TooltipContent>
1318
1318
  </Tooltip>
1319
1319
 
1320
- {/* Account avatars — overlapping stack like Figma */}
1320
+ {/* Account avatars — overlapping stack */}
1321
1321
  {googleStatus.isLoading && (
1322
1322
  <div className="flex items-center ms-1">
1323
1323
  <Skeleton className="h-7 w-7 rounded-full ring-2 ring-card" />
@@ -35,7 +35,7 @@ and move any frame whose label, connector, or annotation crosses another frame.
35
35
  When in doubt, use larger values — the canvas auto-zooms to fit everything.
36
36
 
37
37
  **Canvas annotations are designer notes on the artboard.** When a top canvas is
38
- present, sprinkle Figma-style notes near the frames they explain: a short
38
+ present, sprinkle design-review notes near the frames they explain: a short
39
39
  heading, supporting text, and bullets — plain text layers, never bordered or
40
40
  shadowed cards, and never a box around a frame. The renderer spaces notes away
41
41
  from frames, so place each note by the frame it describes. Use an arrow only to
@@ -225,7 +225,7 @@ elementId, styles }]`. Elements must have `data-design-id` or
225
225
  `data-plan-design-id`; use `patch-wireframe-html` / `patch-prototype-html` for
226
226
  structural or text changes.
227
227
  - Plan comments include reviewer identity, @mentions, resolver intent
228
- (`agent` or `human`), exact anchors, and Figma-style threads. When adding
228
+ (`agent` or `human`), exact anchors, and design-review threads. When adding
229
229
  human feedback through `update-visual-plan`, preserve `authorEmail` and
230
230
  `authorName` when known; pass `parentCommentId` to reply inline to an
231
231
  existing comment thread. Text feedback should anchor to the nearest prose
@@ -102,7 +102,7 @@ const designContextRecordSchema = z.record(z.string(), z.unknown()).refine(
102
102
 
103
103
  export default defineAction({
104
104
  description:
105
- "Create a full-fidelity branded design plan with a Design tab (Figma-style canvas) and optional Prototype tab. For a document-first plan use create-visual-plan; for a wireframe-canvas plan use create-ui-plan; for a recap of an existing diff use create-visual-recap; for a functional prototype use create-prototype-plan. Use design.md, .fig brand kits, and codebase CSS/Tailwind/token evidence when available. Design screens are bounded HTML/CSS fragments with data-design-id targets. Publish via this tool; never deliver the plan as inline chat text.",
105
+ "Create a full-fidelity branded design plan with a Design tab (editable design canvas) and optional Prototype tab. For a document-first plan use create-visual-plan; for a wireframe-canvas plan use create-ui-plan; for a recap of an existing diff use create-visual-recap; for a functional prototype use create-prototype-plan. Use design.md, .fig brand kits, and codebase CSS/Tailwind/token evidence when available. Design screens are bounded HTML/CSS fragments with data-design-id targets. Publish via this tool; never deliver the plan as inline chat text.",
106
106
  schema: z
107
107
  .object({
108
108
  title: z.string().optional().describe("Short design plan title"),
@@ -1,7 +1,7 @@
1
1
  import { defineAction } from "@agent-native/core";
2
2
  import { z } from "zod";
3
3
 
4
- import { parsePlanMdxFolder, type PlanMdxFolder } from "../server/plan-mdx.js";
4
+ import { parsePlanMdxFolder, planMdxFileSchema } from "../server/plan-mdx.js";
5
5
 
6
6
  /**
7
7
  * Authoritative validation for a local plan MDX folder.
@@ -21,14 +21,6 @@ import { parsePlanMdxFolder, type PlanMdxFolder } from "../server/plan-mdx.js";
21
21
  // large-but-valid plans still get authoritative validation instead of the lint.
22
22
  const MAX_MDX_BYTES = 16 * 1024 * 1024;
23
23
 
24
- const mdxFolderSchema = z.object({
25
- "plan.mdx": z.string().min(1),
26
- "canvas.mdx": z.string().optional(),
27
- "prototype.mdx": z.string().optional(),
28
- ".plan-state.json": z.string().optional(),
29
- "assets/": z.record(z.string(), z.string()).optional(),
30
- }) satisfies z.ZodType<PlanMdxFolder>;
31
-
32
24
  type ValidationIssue = { path: string; message: string };
33
25
 
34
26
  function formatZodPath(segments: Array<string | number>): string {
@@ -73,7 +65,7 @@ export default defineAction({
73
65
  description:
74
66
  "Validate a local plan MDX folder against the live Plan renderer schema (parsePlanMdxFolder + planContentSchema). Returns { valid, issues } where issues carry the renderer's exact schema path (e.g. blocks[1].data.items[0].id). Use this to confirm a plan will render before handing it off — it is the authoritative check behind `plan local verify`. Pure parse: no database, filesystem, or schema.plans access.",
75
67
  schema: z.object({
76
- mdx: mdxFolderSchema.describe(
68
+ mdx: planMdxFileSchema.describe(
77
69
  "The plan MDX folder: plan.mdx plus optional canvas.mdx, prototype.mdx, .plan-state.json, and assets/.",
78
70
  ),
79
71
  }),
@@ -9083,6 +9083,7 @@ function CreatePlanDialog({
9083
9083
  disabled={composerLocked}
9084
9084
  attachmentsEnabled={false}
9085
9085
  showModelSelector={false}
9086
+ modelStatusChecksEnabled={false}
9086
9087
  placeholder={t("plansPage.create.placeholder")}
9087
9088
  draftScope="plans:create-plan"
9088
9089
  initialText={promptSeed}
@@ -5,7 +5,7 @@
5
5
  > clarity** on (a) exactly what is commented on — which text, which part of an
6
6
  > image / wireframe / canvas, with a focused marked screenshot for visual
7
7
  > comments, (b) the diff of edits, (c) whether each comment is for a **human** or
8
- > the **agent** to resolve — plus Figma-grade `@mention` tagging.
8
+ > the **agent** to resolve — plus collaboration-grade `@mention` tagging.
9
9
  >
10
10
  > This plan is written to be merged into an already-in-progress implementation.
11
11
  > It is framed as **what already ships → the real holes → the fixes**, with
@@ -18,7 +18,7 @@
18
18
  | Question | Today | Verdict |
19
19
  | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
20
20
  | Is it clear when a comment should be resolved by a **human vs the agent**? | A `resolutionTarget` (`'agent' \| 'human'`) toggle exists in the draft UI (`PlansPage.tsx:4587`) and is surfaced to the agent as an `Expected resolver:` line (`comment-context.ts:198`) — but it lives **only inside the anchor JSON blob**, is not a DB column, and the handoff doesn't partition the agent's queue by it. | **Partly. Make it queryable + partition the handoff.** |
21
- | Can you `@tag` org members with Figma-style autocomplete + inline chips? | Yes — `CommentMentionEditor` (`:4320`) + `useOrgMemberMentionSearch` → `/_agent-native/org/members` (`:433/:451`) + `@[label](mailto:email)` token grammar (`comment-context.ts:55`). | **Yes, already built. Harden, don't rebuild.** |
21
+ | Can you `@tag` org members with design-editor autocomplete + inline chips? | Yes — `CommentMentionEditor` (`:4320`) + `useOrgMemberMentionSearch` → `/_agent-native/org/members` (`:433/:451`) + `@[label](mailto:email)` token grammar (`comment-context.ts:55`). | **Yes, already built. Harden, don't rebuild.** |
22
22
  | When you comment on a location and pass to the agent, is it **fully clear**? | For **text**: yes-ish — quote + section, with `contextBefore/After` fields that exist but are **unevenly populated**. For **visual/canvas**: **no** — the agent gets coordinates + a label only, and the screenshot path that does exist is **bound to the wrong DOM surface** so canvas pins capture garbage. | **Text: tighten. Visual: broken — this is the #1 fix.** |
23
23
  | Do agents get a **screenshot** of the visual location? | An in-app capture path exists (`captureFocusedFeedbackImages`, `:2289`, html2canvas + red-ring marker) but: (1) it rasterizes the **prose reader**, not the canvas world, so canvas/wireframe/diagram pins produce empty crops; (2) crops reach **only** the in-app inline agent — external/MCP agents get text-only. | **No, not reliably. Fix the surface + deliver via the handoff.** |
24
24
  | Does text-by-location attach to the **nearest text**? | It stores `textQuote` + `sectionTitle`; `contextBefore/After` (prefix/suffix) exist in the type but aren't reliably filled, and `resolveAnchorTarget` silently picks the first match for duplicate phrases. | **Mostly — guarantee prefix/suffix + nearest blockId + ambiguity flag.** |
@@ -1502,7 +1502,7 @@ export function createPlanDesignContent(
1502
1502
  data: {
1503
1503
  markdown: [
1504
1504
  `## Objective\n${input.brief}`,
1505
- "## Design Review\nUse the Design tab as the full-fidelity source of truth. It should contain detailed, on-brand HTML/CSS screens on the Figma-style canvas, with editable `data-design-id` targets for focused style changes. Use the Prototype tab only when interaction, flow, or state needs to be felt before implementation.",
1505
+ "## Design Review\nUse the Design tab as the full-fidelity source of truth. It should contain detailed, on-brand HTML/CSS screens on the editable design canvas, with editable `data-design-id` targets for focused style changes. Use the Prototype tab only when interaction, flow, or state needs to be felt before implementation.",
1506
1506
  sourceLines.length
1507
1507
  ? `## Style Sources\n${sourceLines.join("\n")}`
1508
1508
  : "## Style Sources\nNo external brand kit was provided; infer the smallest useful design system from the inspected codebase and document the assumptions here.",
@@ -58,7 +58,7 @@ const DEFAULT_COMPONENTS: UiPlanComponent[] = [
58
58
  {
59
59
  name: "Comment popover",
60
60
  description:
61
- "One-field Figma-like comment composer with no category picker or coordinate metadata in the user-facing bubble.",
61
+ "One-field compact comment composer with no category picker or coordinate metadata in the user-facing bubble.",
62
62
  },
63
63
  {
64
64
  name: "Drawing controls",
@@ -209,7 +209,7 @@ function renderCanvasAnnotationLayers(
209
209
  ? Math.min(board.width - 380, lastState.x + lastState.width + 96)
210
210
  : 1760;
211
211
  return `<div class="canvas-annotation handoff-note" style="${frameStyle(handoffX, 118, 340, 176)}">
212
- <h4>Read this like a Figma handoff.</h4>
212
+ <h4>Read this like a design handoff.</h4>
213
213
  <ul>
214
214
  <li>Pan and zoom to compare frames.</li>
215
215
  <li>Leave comments directly on artboards.</li>
@@ -7,11 +7,9 @@ import {
7
7
  getRequestOrgId,
8
8
  getRequestUserEmail,
9
9
  } from "@agent-native/core/server/request-context";
10
- import { eq } from "drizzle-orm";
11
- import { nanoid } from "nanoid";
12
10
  import { z } from "zod";
13
11
 
14
- import { getDb, schema } from "../server/db/index.js";
12
+ import { upsertBuilderProxyDesignSystem } from "../server/lib/builder-design-system-proxy.js";
15
13
 
16
14
  const MAX_CODE_FILES = 50;
17
15
  const MAX_TOTAL_CODE_BYTES = 2 * 1024 * 1024;
@@ -52,83 +50,6 @@ function makeFiles(
52
50
  return files;
53
51
  }
54
52
 
55
- function localBuilderDesignSystemId(builderDesignSystemId: string): string {
56
- const slug = builderDesignSystemId
57
- .replace(/[^a-zA-Z0-9_-]+/g, "-")
58
- .replace(/^-+|-+$/g, "")
59
- .slice(0, 96);
60
- return `builder-${slug || "design-system"}`;
61
- }
62
-
63
- function builderProxyData({
64
- builderDesignSystemId,
65
- jobId,
66
- builderUrl,
67
- projectName,
68
- description,
69
- }: {
70
- builderDesignSystemId: string;
71
- jobId: string;
72
- builderUrl: string;
73
- projectName?: string;
74
- description?: string;
75
- }) {
76
- return JSON.stringify({
77
- source: "builder",
78
- builderDesignSystemId,
79
- builderJobId: jobId,
80
- builderUrl,
81
- colors: {
82
- primary: "var(--primary)",
83
- secondary: "var(--secondary)",
84
- accent: "var(--accent)",
85
- background: "var(--background)",
86
- surface: "var(--card)",
87
- text: "var(--foreground)",
88
- textMuted: "var(--muted-foreground)",
89
- },
90
- typography: {
91
- headingFont: "inherit",
92
- bodyFont: "inherit",
93
- headingWeight: "700",
94
- bodyWeight: "400",
95
- headingSizes: { h1: "48px", h2: "32px", h3: "24px" },
96
- },
97
- spacing: { elementGap: "24px", slidePadding: "48px" },
98
- borders: { radius: "12px", accentWidth: "1px" },
99
- logos: [],
100
- notes: [
101
- "This is a local proxy for a Builder-indexed design system.",
102
- `Builder design system id: ${builderDesignSystemId}`,
103
- `Builder indexing job id: ${jobId}`,
104
- `Builder URL: ${builderUrl}`,
105
- projectName ? `Requested name: ${projectName}` : "",
106
- description ? `Context: ${description}` : "",
107
- "Use Builder as the source of truth for extracted tokens and guidance.",
108
- ]
109
- .filter(Boolean)
110
- .join("\n"),
111
- });
112
- }
113
-
114
- function builderProxyInstructions({
115
- builderDesignSystemId,
116
- jobId,
117
- builderUrl,
118
- }: {
119
- builderDesignSystemId: string;
120
- jobId: string;
121
- builderUrl: string;
122
- }) {
123
- return [
124
- "This design system is indexed and owned by Builder.",
125
- `Builder design system id: ${builderDesignSystemId}`,
126
- `Builder job id: ${jobId}`,
127
- `Builder URL: ${builderUrl}`,
128
- "When generating slides, treat Builder as the source of truth for the final extracted tokens, assets, and guidance.",
129
- ].join("\n");
130
- }
131
-
132
53
  export default defineAction({
133
54
  description:
134
55
  "Start Builder design-system indexing from a GitHub repository and/or code files. " +
@@ -174,86 +95,18 @@ export default defineAction({
174
95
  const ownerEmail = getRequestUserEmail();
175
96
  if (!ownerEmail) throw new Error("no authenticated user");
176
97
 
177
- const db = getDb();
178
- const now = new Date().toISOString();
179
- const orgId = getRequestOrgId();
180
- const baseLocalDesignSystemId = localBuilderDesignSystemId(
181
- result.designSystemId,
182
- );
183
- const title = projectName?.trim() || "Builder indexed design system";
184
- const localData = builderProxyData({
185
- builderDesignSystemId: result.designSystemId,
186
- jobId: result.jobId,
187
- builderUrl: result.builderUrl,
98
+ const proxy = await upsertBuilderProxyDesignSystem({
99
+ result,
100
+ ownerEmail,
101
+ orgId: getRequestOrgId(),
188
102
  projectName,
189
103
  description,
190
104
  });
191
- const customInstructions = builderProxyInstructions({
192
- builderDesignSystemId: result.designSystemId,
193
- jobId: result.jobId,
194
- builderUrl: result.builderUrl,
195
- });
196
- const [existing] = await db
197
- .select({
198
- id: schema.designSystems.id,
199
- ownerEmail: schema.designSystems.ownerEmail,
200
- })
201
- .from(schema.designSystems)
202
- .where(eq(schema.designSystems.id, baseLocalDesignSystemId))
203
- .limit(1);
204
- const localDesignSystemId =
205
- existing && existing.ownerEmail !== ownerEmail
206
- ? `${baseLocalDesignSystemId}-${nanoid(8)}`
207
- : baseLocalDesignSystemId;
208
- if (existing && existing.ownerEmail === ownerEmail) {
209
- await db
210
- .update(schema.designSystems)
211
- .set({
212
- title,
213
- description:
214
- description ??
215
- `Builder indexed design system ${result.designSystemId}`,
216
- data: localData,
217
- assets: "[]",
218
- customInstructions,
219
- updatedAt: now,
220
- })
221
- .where(eq(schema.designSystems.id, existing.id));
222
- } else {
223
- const [ownedSystem] = await db
224
- .select({ id: schema.designSystems.id })
225
- .from(schema.designSystems)
226
- .where(eq(schema.designSystems.ownerEmail, ownerEmail))
227
- .limit(1);
228
- await db.insert(schema.designSystems).values({
229
- id: localDesignSystemId,
230
- title,
231
- description:
232
- description ??
233
- `Builder indexed design system ${result.designSystemId}`,
234
- data: localData,
235
- assets: "[]",
236
- customInstructions,
237
- isDefault: !ownedSystem,
238
- ownerEmail,
239
- orgId,
240
- createdAt: now,
241
- updatedAt: now,
242
- });
243
- }
244
105
 
245
106
  return {
246
107
  ...result,
247
- localDesignSystemId,
108
+ ...proxy,
248
109
  uploadedFileCount: files.length,
249
- instructions: [
250
- "Builder design-system indexing has started.",
251
- `Builder design system: ${result.designSystemId}`,
252
- `Local selectable design system: ${localDesignSystemId}`,
253
- `Builder job: ${result.jobId}`,
254
- `Open: ${result.builderUrl}`,
255
- "Use the local design system id in Slides flows; Builder remains the source of truth for the indexed brand kit.",
256
- ].join("\n"),
257
110
  };
258
111
  },
259
112
  });
@@ -36,11 +36,11 @@ import { Textarea } from "@/components/ui/textarea";
36
36
  import { toast } from "@/hooks/use-toast";
37
37
 
38
38
  import {
39
- MAX_FIG_UPLOAD_BYTES,
39
+ MAX_BUILDER_INDEX_UPLOAD_BYTES,
40
+ readBuilderIndexResponse,
40
41
  formatFileSize,
41
- readFigImportResponse,
42
- type FigImportResult,
43
- } from "./fig-import-response";
42
+ type BuilderIndexResult,
43
+ } from "./builder-index-response";
44
44
 
45
45
  interface DesignSystemSetupProps {
46
46
  open: boolean;
@@ -105,9 +105,12 @@ export function DesignSystemSetup({
105
105
  const [brandNotes, setBrandNotes] = useState("");
106
106
  const [customInstructions, setCustomInstructions] = useState("");
107
107
  const [generating, setGenerating] = useState(false);
108
- const [figParsing, setFigParsing] = useState(false);
109
- const [figResult, setFigResult] = useState<FigImportResult | null>(null);
110
- const [figError, setFigError] = useState<string | null>(null);
108
+ const [builderIndexing, setBuilderIndexing] = useState(false);
109
+ const [builderIndexResult, setBuilderIndexResult] =
110
+ useState<BuilderIndexResult | null>(null);
111
+ const [builderIndexError, setBuilderIndexError] = useState<string | null>(
112
+ null,
113
+ );
111
114
 
112
115
  const codeInputRef = useRef<HTMLInputElement>(null);
113
116
  const docInputRef = useRef<HTMLInputElement>(null);
@@ -158,9 +161,9 @@ export function DesignSystemSetup({
158
161
  setBrandNotes("");
159
162
  setCustomInstructions("");
160
163
  setSelectedSystemId("");
161
- setFigParsing(false);
162
- setFigResult(null);
163
- setFigError(null);
164
+ setBuilderIndexing(false);
165
+ setBuilderIndexResult(null);
166
+ setBuilderIndexError(null);
164
167
  }
165
168
  }, [open]);
166
169
 
@@ -170,6 +173,7 @@ export function DesignSystemSetup({
170
173
  websiteUrls.length > 0 ||
171
174
  githubLinks.length > 0 ||
172
175
  codeFiles.length > 0 ||
176
+ builderIndexResult ||
173
177
  docFiles.length > 0 ||
174
178
  imageFiles.length > 0 ||
175
179
  selectedSystemId ||
@@ -181,6 +185,7 @@ export function DesignSystemSetup({
181
185
  websiteUrls,
182
186
  githubLinks,
183
187
  codeFiles,
188
+ builderIndexResult,
184
189
  docFiles,
185
190
  imageFiles,
186
191
  selectedSystemId,
@@ -238,44 +243,47 @@ export function DesignSystemSetup({
238
243
  [t],
239
244
  );
240
245
 
241
- const handleFigImport = useCallback(
246
+ const handleBuilderIndexUpload = useCallback(
242
247
  async (event: React.ChangeEvent<HTMLInputElement>) => {
243
248
  const file = event.target.files?.[0];
244
249
  event.target.value = "";
245
250
  if (!file) return;
246
251
  if (!file.name.toLowerCase().endsWith(".fig")) {
247
- setFigError(t("designSystemSetup.figFileRequired"));
252
+ setBuilderIndexError(t("designSystemSetup.figFileRequired"));
248
253
  return;
249
254
  }
250
- if (file.size > MAX_FIG_UPLOAD_BYTES) {
251
- setFigError(
255
+ if (file.size > MAX_BUILDER_INDEX_UPLOAD_BYTES) {
256
+ setBuilderIndexError(
252
257
  t("designSystemSetup.figFileTooLarge", {
253
- maxSize: formatFileSize(MAX_FIG_UPLOAD_BYTES),
258
+ maxSize: formatFileSize(MAX_BUILDER_INDEX_UPLOAD_BYTES),
254
259
  }),
255
260
  );
256
261
  return;
257
262
  }
258
263
 
259
- setFigError(null);
260
- setFigResult(null);
261
- setFigParsing(true);
264
+ setBuilderIndexError(null);
265
+ setBuilderIndexResult(null);
266
+ setBuilderIndexing(true);
262
267
  try {
263
268
  const body = new FormData();
264
269
  body.append("file", file);
265
- const res = await fetch(appApiPath("/api/import-figma-system"), {
266
- method: "POST",
267
- body,
268
- });
269
- const parsed = await readFigImportResponse(res);
270
- setFigResult(parsed);
270
+ const res = await fetch(
271
+ appApiPath("/api/index-design-system-with-builder"),
272
+ {
273
+ method: "POST",
274
+ body,
275
+ },
276
+ );
277
+ const parsed = await readBuilderIndexResponse(res);
278
+ setBuilderIndexResult(parsed);
271
279
  } catch (err) {
272
- setFigError(
280
+ setBuilderIndexError(
273
281
  err instanceof Error
274
282
  ? err.message
275
283
  : t("designSystemSetup.figParseFailed"),
276
284
  );
277
285
  } finally {
278
- setFigParsing(false);
286
+ setBuilderIndexing(false);
279
287
  }
280
288
  },
281
289
  [t],
@@ -353,6 +361,12 @@ export function DesignSystemSetup({
353
361
  }
354
362
  }
355
363
 
364
+ if (builderIndexResult) {
365
+ parts.push(
366
+ `\n## Builder-Indexed Figma File\nBuilder design-system indexing has already started.\n- Design system: ${builderIndexResult.designSystemId}\n- Local selectable design system: ${builderIndexResult.localDesignSystemId ?? "(not returned)"}\n- Project: ${builderIndexResult.projectId}\n- Job: ${builderIndexResult.jobId}\n- URL: ${builderIndexResult.builderUrl}\n\nUse Builder as the source of truth for extracted tokens, assets, and guidance. Do not call \`create-design-system\` again for this Builder-indexed source.`,
367
+ );
368
+ }
369
+
356
370
  if (docFiles.length > 0) {
357
371
  const inlined = docFiles.filter((f) => f.textContent);
358
372
  const binary = docFiles.filter((f) => !f.textContent);
@@ -419,6 +433,7 @@ export function DesignSystemSetup({
419
433
  websiteUrls,
420
434
  githubLinks,
421
435
  codeFiles,
436
+ builderIndexResult,
422
437
  docFiles,
423
438
  imageFiles,
424
439
  selectedSystemId,
@@ -469,15 +484,15 @@ export function DesignSystemSetup({
469
484
  <IconBrandFigma className="w-3.5 h-3.5" />
470
485
  {t("designSystemSetup.figmaFile")}
471
486
  </Label>
472
- {!figResult ? (
487
+ {!builderIndexResult ? (
473
488
  <>
474
489
  <button
475
490
  type="button"
476
491
  onClick={() => figInputRef.current?.click()}
477
- disabled={figParsing}
492
+ disabled={builderIndexing}
478
493
  className="w-full border border-dashed border-border rounded-lg p-4 text-center hover:border-foreground/20 cursor-pointer disabled:cursor-wait disabled:opacity-70"
479
494
  >
480
- {figParsing ? (
495
+ {builderIndexing ? (
481
496
  <span className="inline-flex items-center gap-2 text-xs text-muted-foreground">
482
497
  <IconLoader2 className="w-3.5 h-3.5 animate-spin" />
483
498
  {t("designSystemSetup.parsingFigmaFile")}
@@ -492,24 +507,24 @@ export function DesignSystemSetup({
492
507
  ref={figInputRef}
493
508
  type="file"
494
509
  accept=".fig"
495
- onChange={handleFigImport}
510
+ onChange={handleBuilderIndexUpload}
496
511
  className="hidden"
497
512
  />
498
- {figError && (
513
+ {builderIndexError && (
499
514
  <div
500
515
  role="alert"
501
516
  className="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive"
502
517
  >
503
- {figError}
518
+ {builderIndexError}
504
519
  </div>
505
520
  )}
506
521
  </>
507
522
  ) : (
508
- <FigImportPreview
509
- result={figResult}
523
+ <BuilderIndexPreview
524
+ result={builderIndexResult}
510
525
  onReset={() => {
511
- setFigResult(null);
512
- setFigError(null);
526
+ setBuilderIndexResult(null);
527
+ setBuilderIndexError(null);
513
528
  }}
514
529
  />
515
530
  )}
@@ -842,11 +857,11 @@ function TagList({
842
857
  );
843
858
  }
844
859
 
845
- function FigImportPreview({
860
+ function BuilderIndexPreview({
846
861
  result,
847
862
  onReset,
848
863
  }: {
849
- result: FigImportResult;
864
+ result: BuilderIndexResult;
850
865
  onReset: () => void;
851
866
  }) {
852
867
  const t = useT();
@@ -1,4 +1,4 @@
1
- export interface FigImportResult {
1
+ export interface BuilderIndexResult {
2
2
  ok: boolean;
3
3
  source: "builder";
4
4
  suggestedTitle: string;
@@ -7,10 +7,13 @@ export interface FigImportResult {
7
7
  designSystemId: string;
8
8
  builderUrl: string;
9
9
  status: "in-progress";
10
+ localDesignSystemId?: string;
11
+ uploadedFileCount?: number;
12
+ instructions?: string;
10
13
  builderConnectUrl?: string;
11
14
  }
12
15
 
13
- export const MAX_FIG_UPLOAD_BYTES = 200 * 1024 * 1024;
16
+ export const MAX_BUILDER_INDEX_UPLOAD_BYTES = 200 * 1024 * 1024;
14
17
 
15
18
  export function formatFileSize(bytes: number): string {
16
19
  return `${Math.round(bytes / 1024 / 1024)} MB`;
@@ -18,7 +21,7 @@ export function formatFileSize(bytes: number): string {
18
21
 
19
22
  function summarizeUploadFailure(status: number, bodyText: string): string {
20
23
  if (status === 413) {
21
- return `File too large (max ${formatFileSize(MAX_FIG_UPLOAD_BYTES)}).`;
24
+ return `File too large (max ${formatFileSize(MAX_BUILDER_INDEX_UPLOAD_BYTES)}).`;
22
25
  }
23
26
 
24
27
  const trimmed = bodyText
@@ -31,9 +34,9 @@ function summarizeUploadFailure(status: number, bodyText: string): string {
31
34
  return `Upload failed (${status})`;
32
35
  }
33
36
 
34
- export async function readFigImportResponse(
37
+ export async function readBuilderIndexResponse(
35
38
  res: Response,
36
- ): Promise<FigImportResult> {
39
+ ): Promise<BuilderIndexResult> {
37
40
  const bodyText = await res.text();
38
41
  let json: unknown = null;
39
42
 
@@ -59,5 +62,5 @@ export async function readFigImportResponse(
59
62
  throw new Error(summarizeUploadFailure(res.status, bodyText));
60
63
  }
61
64
 
62
- return json as FigImportResult;
65
+ return json as BuilderIndexResult;
63
66
  }
@@ -17,7 +17,7 @@ interface MultiSelectChipProps {
17
17
  }
18
18
 
19
19
  /**
20
- * Floating chip that hovers above a multi-select selection (Figma-style).
20
+ * Floating chip that hovers above a multi-select selection (design-editor style).
21
21
  * Rendered via portal so it isn't constrained by the slide canvas's stacking
22
22
  * context. Reusable across the slides editor and the design template.
23
23
  */
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-06-29
4
+ ---
5
+
6
+ Design system setup now indexes uploaded design files through Builder.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-06-29
4
+ ---
5
+
6
+ Hosted deck generation and editing chats have a longer background run window, reducing timeouts during complex creative turns.