@agent-native/core 0.80.2 → 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 (322) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +66 -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 +32 -0
  26. package/corpus/core/src/agent/durable-background.ts +32 -11
  27. package/corpus/core/src/agent/production-agent.ts +14 -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/plan-local.ts +445 -108
  33. package/corpus/core/src/cli/skills.ts +32 -8
  34. package/corpus/core/src/client/AssistantChat.tsx +11 -1
  35. package/corpus/core/src/client/agent-chat.ts +12 -1
  36. package/corpus/core/src/client/composer/PromptComposer.tsx +100 -41
  37. package/corpus/core/src/client/org/OrgSwitcher.tsx +1 -1
  38. package/corpus/core/src/client/sharing/ShareButton.tsx +3 -27
  39. package/corpus/core/src/collab/presence.ts +1 -1
  40. package/corpus/core/src/mcp/connect-route.ts +34 -5
  41. package/corpus/core/src/server/action-discovery.ts +4 -0
  42. package/corpus/core/src/server/action-routes.ts +14 -0
  43. package/corpus/core/src/server/agent-chat-plugin.ts +20 -0
  44. package/corpus/core/src/vite/client.ts +15 -1
  45. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -0
  46. package/corpus/templates/analytics/actions/update-dashboard.ts +8 -0
  47. package/corpus/templates/analytics/app/components/layout/Layout.tsx +1 -1
  48. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +117 -33
  49. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +4 -0
  50. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +7 -0
  51. package/corpus/templates/analytics/changelog/2026-06-27-dashboards-can-now-nest-under-a-parent-in-the-sidebar-via-a-.md +6 -0
  52. package/corpus/templates/analytics/changelog/2026-06-29-analytics-pages-now-sit-closer-under-the-header-with-tighter.md +6 -0
  53. package/corpus/templates/assets/actions/generate-image-batch.ts +3 -0
  54. package/corpus/templates/assets/actions/generate-image.ts +3 -0
  55. package/corpus/templates/assets/changelog/2026-06-29-longer-agent-generation-window.md +6 -0
  56. package/corpus/templates/assets/netlify.toml +3 -3
  57. package/corpus/templates/assets/server/plugins/agent-chat.ts +4 -1
  58. package/corpus/templates/clips/app/components/capture-install-options.tsx +7 -8
  59. package/corpus/templates/clips/app/components/player/timestamped-comment-button.tsx +162 -0
  60. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +1 -1
  61. package/corpus/templates/clips/app/i18n/ar-SA.ts +4 -0
  62. package/corpus/templates/clips/app/i18n/de-DE.ts +4 -0
  63. package/corpus/templates/clips/app/i18n/en-US.ts +4 -0
  64. package/corpus/templates/clips/app/i18n/es-ES.ts +4 -0
  65. package/corpus/templates/clips/app/i18n/fr-FR.ts +4 -0
  66. package/corpus/templates/clips/app/i18n/hi-IN.ts +4 -0
  67. package/corpus/templates/clips/app/i18n/ja-JP.ts +4 -0
  68. package/corpus/templates/clips/app/i18n/ko-KR.ts +4 -0
  69. package/corpus/templates/clips/app/i18n/pt-BR.ts +4 -0
  70. package/corpus/templates/clips/app/i18n/zh-CN.ts +4 -0
  71. package/corpus/templates/clips/app/i18n/zh-TW.ts +4 -0
  72. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +42 -18
  73. package/corpus/templates/content/AGENTS.md +12 -0
  74. package/corpus/templates/content/app/blocks/BuilderDocsBlocks.tsx +10 -0
  75. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +1 -0
  76. package/corpus/templates/content/app/components/editor/ContentReferencePreview.tsx +185 -0
  77. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +3 -0
  78. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +19 -0
  79. package/corpus/templates/content/app/components/editor/extensions/ContentReferenceNode.tsx +82 -0
  80. package/corpus/templates/content/app/global.css +9 -0
  81. package/corpus/templates/content/app/i18n/zh-TW.ts +12 -0
  82. package/corpus/templates/content/app/i18n-data.ts +140 -0
  83. package/corpus/templates/content/changelog/2026-06-29-reusable-mdx-references-now-preview-linked-local-documents-i.md +6 -0
  84. package/corpus/templates/content/shared/builder-docs-blocks.ts +8 -0
  85. package/corpus/templates/content/shared/builder-mdx.ts +141 -4
  86. package/corpus/templates/content/shared/nfm.ts +62 -0
  87. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +10 -11
  88. package/corpus/templates/design/AGENTS.md +5 -0
  89. package/corpus/templates/design/_gitignore +7 -0
  90. package/corpus/templates/design/actions/apply-visual-edit.ts +22 -12
  91. package/corpus/templates/design/actions/create-design-system.ts +15 -4
  92. package/corpus/templates/design/actions/create-file.ts +20 -1
  93. package/corpus/templates/design/actions/delete-design-system.ts +2 -2
  94. package/corpus/templates/design/actions/duplicate-design.ts +35 -9
  95. package/corpus/templates/design/actions/generate-design.ts +146 -69
  96. package/corpus/templates/design/actions/generate-screens.ts +51 -19
  97. package/corpus/templates/design/actions/get-design-snapshot.ts +5 -1
  98. package/corpus/templates/design/actions/get-design.ts +2 -0
  99. package/corpus/templates/design/actions/import-design-project.ts +28 -9
  100. package/corpus/templates/design/actions/import-document.ts +22 -8
  101. package/corpus/templates/design/actions/index-design-system-with-builder.ts +6 -153
  102. package/corpus/templates/design/actions/navigate.ts +105 -54
  103. package/corpus/templates/design/actions/set-default-design-system.ts +17 -3
  104. package/corpus/templates/design/actions/show-design-questions.ts +2 -0
  105. package/corpus/templates/design/actions/update-design.ts +2 -1
  106. package/corpus/templates/design/actions/view-screen.ts +12 -6
  107. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +4 -4
  108. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +159 -41
  109. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +8 -4
  110. package/corpus/templates/design/app/components/design/DrawOverlay.tsx +37 -42
  111. package/corpus/templates/design/app/components/design/EditPanel.tsx +336 -183
  112. package/corpus/templates/design/app/components/design/LayersPanel.tsx +153 -34
  113. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +135 -33
  114. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +6 -0
  115. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +2 -1
  116. package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +4 -10
  117. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +84 -43
  118. package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +4 -4
  119. package/corpus/templates/design/app/components/design/inspector/{FigmaColorPicker.tsx → DesignColorPicker.tsx} +89 -62
  120. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +14 -26
  121. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +40 -12
  122. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +13 -4
  123. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +13 -13
  124. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +13 -9
  125. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +13 -4
  126. package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +6 -6
  127. package/corpus/templates/design/app/components/design/inspector/{figma-icons.tsx → design-icons.tsx} +2 -2
  128. package/corpus/templates/design/app/components/design/inspector/index.ts +12 -12
  129. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +5 -2
  130. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -3
  131. package/corpus/templates/design/app/components/layout/Layout.tsx +5 -2
  132. package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
  133. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +167 -91
  134. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +16 -3
  135. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +15 -0
  136. package/corpus/templates/design/app/global.css +4 -0
  137. package/corpus/templates/design/app/hooks/use-design-system.ts +4 -1
  138. package/corpus/templates/design/app/hooks/use-navigation-state.ts +38 -3
  139. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +9 -2
  140. package/corpus/templates/design/app/i18n/zh-TW.ts +22 -0
  141. package/corpus/templates/design/app/i18n-data.ts +527 -0
  142. package/corpus/templates/design/app/lib/design-systems.ts +6 -4
  143. package/corpus/templates/design/app/lib/design-templates.ts +15 -3
  144. package/corpus/templates/design/app/pages/DesignEditor.tsx +641 -158
  145. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +42 -34
  146. package/corpus/templates/design/app/pages/VisualEdit.tsx +100 -0
  147. package/corpus/templates/design/app/root.tsx +42 -9
  148. package/corpus/templates/design/app/routes/visual-edit.tsx +7 -0
  149. package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +1 -1
  150. package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +1 -1
  151. package/corpus/templates/design/changelog/2026-06-28-visual-code-design-mode.md +6 -0
  152. package/corpus/templates/design/changelog/2026-06-29-design-generation-prompts-now-show-connect-ai-before-sending.md +6 -0
  153. package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +1 -1
  154. package/corpus/templates/design/changelog/2026-06-29-fixed-design-editor-exports-and-gradient-edits-so-multi-scre.md +6 -0
  155. package/corpus/templates/design/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
  156. package/corpus/templates/design/changelog/2026-06-29-png-export-handles-modern-css-color-functions-more-reliably.md +6 -0
  157. package/corpus/templates/design/changelog/2026-06-29-png-export-now-ignores-duplicate-clicks-while-a-download-is-.md +6 -0
  158. package/corpus/templates/design/changelog/2026-06-29-public-visual-edit-and-shared-design-links-now-invite-visito.md +6 -0
  159. package/corpus/templates/design/changelog/2026-06-29-visual-edit-actions-now-reject-missing-design-targets-before.md +6 -0
  160. package/corpus/templates/design/e2e/README.md +71 -0
  161. package/corpus/templates/design/e2e/global-setup.ts +157 -0
  162. package/corpus/templates/design/e2e/helpers.ts +148 -0
  163. package/corpus/templates/design/netlify.toml +3 -4
  164. package/corpus/templates/design/package.json +5 -1
  165. package/corpus/templates/design/playwright.config.ts +51 -0
  166. package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +121 -0
  167. package/corpus/templates/design/server/handlers/uploads.ts +89 -38
  168. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +181 -0
  169. package/corpus/templates/design/server/lib/coding-handoff.ts +33 -4
  170. package/corpus/templates/design/server/lib/design-export.ts +35 -8
  171. package/corpus/templates/design/server/plugins/agent-chat.ts +4 -0
  172. package/corpus/templates/design/server/plugins/auth.ts +10 -1
  173. package/corpus/templates/design/server/routes/api/index-design-system-with-builder.post.ts +1 -0
  174. package/corpus/templates/design/shared/api.ts +2 -0
  175. package/corpus/templates/design/shared/apply-edits.ts +12 -8
  176. package/corpus/templates/design/shared/canvas-math.ts +19 -1
  177. package/corpus/templates/design/shared/code-layer.ts +87 -28
  178. package/corpus/templates/design/shared/generation-session.ts +1 -0
  179. package/corpus/templates/design/shared/resolve-tweaks.ts +4 -3
  180. package/corpus/templates/design/shared/shader-presets.ts +10 -0
  181. package/corpus/templates/design/shared/source-mode.ts +9 -0
  182. package/corpus/templates/design/vitest.config.ts +2 -1
  183. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +1 -1
  184. package/corpus/templates/plan/.agents/skills/visual-plan/references/canvas.md +1 -1
  185. package/corpus/templates/plan/.agents/skills/visual-plan/references/local-files.md +14 -5
  186. package/corpus/templates/plan/.agents/skills/visual-recap/references/local-files.md +14 -5
  187. package/corpus/templates/plan/AGENTS.md +1 -1
  188. package/corpus/templates/plan/actions/create-plan-design.ts +1 -1
  189. package/corpus/templates/plan/actions/validate-local-plan-source.ts +110 -0
  190. package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -0
  191. package/corpus/templates/plan/docs/commenting-ux-plan.md +2 -2
  192. package/corpus/templates/plan/server/lib/plan-connector-catalog.ts +1 -0
  193. package/corpus/templates/plan/server/lib/public-action-paths.ts +1 -0
  194. package/corpus/templates/plan/server/plan-content.ts +1 -1
  195. package/corpus/templates/plan/server/ui-plan-html.ts +2 -2
  196. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +6 -153
  197. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +53 -38
  198. package/corpus/templates/slides/app/components/design-system/{fig-import-response.ts → builder-index-response.ts} +9 -6
  199. package/corpus/templates/slides/app/components/visual-editor/MultiSelectChip.tsx +1 -1
  200. package/corpus/templates/slides/changelog/2026-06-29-design-system-setup-now-indexes-uploaded-design-files-throug.md +6 -0
  201. package/corpus/templates/slides/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
  202. package/corpus/templates/slides/netlify.toml +3 -6
  203. package/corpus/templates/slides/server/handlers/index-design-system-with-builder.ts +116 -0
  204. package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +179 -0
  205. package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -1
  206. package/corpus/templates/slides/server/routes/api/index-design-system-with-builder.post.ts +1 -0
  207. package/dist/action.d.ts +23 -0
  208. package/dist/action.d.ts.map +1 -1
  209. package/dist/action.js +9 -0
  210. package/dist/action.js.map +1 -1
  211. package/dist/agent/durable-background.d.ts +9 -7
  212. package/dist/agent/durable-background.d.ts.map +1 -1
  213. package/dist/agent/durable-background.js +27 -11
  214. package/dist/agent/durable-background.js.map +1 -1
  215. package/dist/agent/production-agent.d.ts +10 -0
  216. package/dist/agent/production-agent.d.ts.map +1 -1
  217. package/dist/agent/production-agent.js +4 -1
  218. package/dist/agent/production-agent.js.map +1 -1
  219. package/dist/agent/run-loop-with-resume.d.ts +2 -1
  220. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  221. package/dist/agent/run-loop-with-resume.js +2 -2
  222. package/dist/agent/run-loop-with-resume.js.map +1 -1
  223. package/dist/brand-kit/fig/index.d.ts +4 -4
  224. package/dist/brand-kit/fig/index.d.ts.map +1 -1
  225. package/dist/brand-kit/fig/index.js +14 -27
  226. package/dist/brand-kit/fig/index.js.map +1 -1
  227. package/dist/cli/index.js +1 -1
  228. package/dist/cli/index.js.map +1 -1
  229. package/dist/cli/mcp-config-writers.d.ts +15 -7
  230. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  231. package/dist/cli/mcp-config-writers.js +198 -45
  232. package/dist/cli/mcp-config-writers.js.map +1 -1
  233. package/dist/cli/plan-local.d.ts +30 -0
  234. package/dist/cli/plan-local.d.ts.map +1 -1
  235. package/dist/cli/plan-local.js +281 -56
  236. package/dist/cli/plan-local.js.map +1 -1
  237. package/dist/cli/skills.d.ts +2 -2
  238. package/dist/cli/skills.d.ts.map +1 -1
  239. package/dist/cli/skills.js +32 -8
  240. package/dist/cli/skills.js.map +1 -1
  241. package/dist/client/AssistantChat.d.ts.map +1 -1
  242. package/dist/client/AssistantChat.js +11 -1
  243. package/dist/client/AssistantChat.js.map +1 -1
  244. package/dist/client/agent-chat.d.ts.map +1 -1
  245. package/dist/client/agent-chat.js +15 -2
  246. package/dist/client/agent-chat.js.map +1 -1
  247. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  248. package/dist/client/composer/PromptComposer.js +35 -1
  249. package/dist/client/composer/PromptComposer.js.map +1 -1
  250. package/dist/client/org/OrgSwitcher.js +1 -1
  251. package/dist/client/org/OrgSwitcher.js.map +1 -1
  252. package/dist/client/sharing/ShareButton.d.ts +1 -1
  253. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  254. package/dist/client/sharing/ShareButton.js +2 -15
  255. package/dist/client/sharing/ShareButton.js.map +1 -1
  256. package/dist/collab/presence.d.ts +1 -1
  257. package/dist/collab/presence.js +1 -1
  258. package/dist/collab/presence.js.map +1 -1
  259. package/dist/collab/routes.d.ts +1 -1
  260. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  261. package/dist/mcp/connect-route.d.ts.map +1 -1
  262. package/dist/mcp/connect-route.js +34 -5
  263. package/dist/mcp/connect-route.js.map +1 -1
  264. package/dist/observability/routes.d.ts +2 -2
  265. package/dist/progress/routes.d.ts +1 -1
  266. package/dist/resources/handlers.d.ts +1 -1
  267. package/dist/server/action-discovery.d.ts.map +1 -1
  268. package/dist/server/action-discovery.js +5 -0
  269. package/dist/server/action-discovery.js.map +1 -1
  270. package/dist/server/action-routes.d.ts.map +1 -1
  271. package/dist/server/action-routes.js +14 -0
  272. package/dist/server/action-routes.js.map +1 -1
  273. package/dist/server/agent-chat-plugin.d.ts +6 -0
  274. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  275. package/dist/server/agent-chat-plugin.js +12 -3
  276. package/dist/server/agent-chat-plugin.js.map +1 -1
  277. package/dist/vite/client.d.ts.map +1 -1
  278. package/dist/vite/client.js +12 -1
  279. package/dist/vite/client.js.map +1 -1
  280. package/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
  281. package/docs/content/locales/ar-SA/template-design.mdx +1 -1
  282. package/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
  283. package/docs/content/locales/de-DE/template-design.mdx +1 -1
  284. package/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
  285. package/docs/content/locales/es-ES/template-design.mdx +1 -1
  286. package/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
  287. package/docs/content/locales/fr-FR/template-design.mdx +1 -1
  288. package/docs/content/locales/hi-IN/template-design.mdx +1 -1
  289. package/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
  290. package/docs/content/locales/ja-JP/template-design.mdx +1 -1
  291. package/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
  292. package/docs/content/locales/ko-KR/template-design.mdx +1 -1
  293. package/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
  294. package/docs/content/locales/pt-BR/template-design.mdx +1 -1
  295. package/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
  296. package/docs/content/locales/zh-CN/template-design.mdx +1 -1
  297. package/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
  298. package/docs/content/locales/zh-TW/template-design.mdx +1 -1
  299. package/docs/content/real-time-collaboration.mdx +2 -2
  300. package/docs/content/template-design.mdx +1 -1
  301. package/package.json +3 -7
  302. package/corpus/core/src/brand-kit/fig/decode.ts +0 -410
  303. package/corpus/core/src/brand-kit/fig/extract-design-system.ts +0 -947
  304. package/corpus/core/src/brand-kit/fig/fig-to-html.ts +0 -1906
  305. package/corpus/templates/design/actions/import-figma.ts +0 -55
  306. package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +0 -6
  307. package/corpus/templates/design/server/handlers/import-figma-system.ts +0 -86
  308. package/corpus/templates/design/server/routes/api/import-figma-system.post.ts +0 -1
  309. package/corpus/templates/slides/server/handlers/import-figma-system.ts +0 -101
  310. package/corpus/templates/slides/server/routes/api/import-figma-system.post.ts +0 -1
  311. package/dist/brand-kit/fig/decode.d.ts +0 -33
  312. package/dist/brand-kit/fig/decode.d.ts.map +0 -1
  313. package/dist/brand-kit/fig/decode.js +0 -358
  314. package/dist/brand-kit/fig/decode.js.map +0 -1
  315. package/dist/brand-kit/fig/extract-design-system.d.ts +0 -44
  316. package/dist/brand-kit/fig/extract-design-system.d.ts.map +0 -1
  317. package/dist/brand-kit/fig/extract-design-system.js +0 -752
  318. package/dist/brand-kit/fig/extract-design-system.js.map +0 -1
  319. package/dist/brand-kit/fig/fig-to-html.d.ts +0 -246
  320. package/dist/brand-kit/fig/fig-to-html.d.ts.map +0 -1
  321. package/dist/brand-kit/fig/fig-to-html.js +0 -1506
  322. 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
@@ -35,8 +35,10 @@ The local-files contract:
35
35
  `id` and `label`; and `Code` / `AnnotatedCode` / `Diff` are whitespace-sensitive
36
36
  — encode multiline code as JSON string attributes such as `code={"const x =\n y"}`
37
37
  (a static template literal is accepted only when it has no `${...}`
38
- interpolation). `plan local check` validates these required fields against the
39
- renderer schema.
38
+ interpolation). `plan local check` is a quick OFFLINE lint (a subset of the
39
+ renderer schema), so a green `check` does not guarantee the plan renders;
40
+ `plan local verify` is the authoritative validation against the real renderer
41
+ schema.
40
42
  - **Write a local MDX folder.** Use `plans/<slug>/` to check the artifact into the
41
43
  repo, or a repo-ignored/temporary folder such as `.agent-native/plans/<slug>/`
42
44
  or `/tmp/agent-native-plans/<slug>/` when it should not be checked in. The
@@ -61,9 +63,16 @@ The local-files contract:
61
63
  running local Plan app.
62
64
  - **Headless verify.** Run
63
65
  `npx @agent-native/core@latest plan local verify --dir <plan-dir> --kind <plan|recap>`.
64
- It starts the bridge, checks the private-network preflight and JSON payload,
65
- prints diagnostics, and exits. If the browser hangs on "Loading plan", fetch the
66
- `bridgeUrl` from the verify/serve JSON to read the concrete validation error.
66
+ It starts the bridge, checks the private-network preflight and JSON payload, AND
67
+ validates the content against the real renderer schema via the Plan app's
68
+ `validate-local-plan-source` action. A non-`ok` result with
69
+ `validation.valid: false` lists the renderer's exact schema-path issues (e.g.
70
+ `blocks[1].data.tabs[0]...`); fix those before handing off. If `validation.ran`
71
+ is `false`, the Plan app did not expose the validate endpoint (older/unreachable
72
+ deploy) — point `--app-url` at a current Plan app (e.g. a local
73
+ `http://localhost:8096`) for the authoritative check. If the browser hangs on
74
+ "Loading plan", fetch the `bridgeUrl` from the verify/serve JSON to read the
75
+ concrete validation error.
67
76
  - **Never call hosted tools for that plan/recap.** Do not call
68
77
  `create-visual-plan`, `create-ui-plan`, `create-prototype-plan`,
69
78
  `create-plan-design`, `create-visual-recap`, `create-visual-questions`,
@@ -35,8 +35,10 @@ The local-files contract:
35
35
  `id` and `label`; and `Code` / `AnnotatedCode` / `Diff` are whitespace-sensitive
36
36
  — encode multiline code as JSON string attributes such as `code={"const x =\n y"}`
37
37
  (a static template literal is accepted only when it has no `${...}`
38
- interpolation). `plan local check` validates these required fields against the
39
- renderer schema.
38
+ interpolation). `plan local check` is a quick OFFLINE lint (a subset of the
39
+ renderer schema), so a green `check` does not guarantee the plan renders;
40
+ `plan local verify` is the authoritative validation against the real renderer
41
+ schema.
40
42
  - **Write a local MDX folder.** Use `plans/<slug>/` to check the artifact into the
41
43
  repo, or a repo-ignored/temporary folder such as `.agent-native/plans/<slug>/`
42
44
  or `/tmp/agent-native-plans/<slug>/` when it should not be checked in. The
@@ -61,9 +63,16 @@ The local-files contract:
61
63
  running local Plan app.
62
64
  - **Headless verify.** Run
63
65
  `npx @agent-native/core@latest plan local verify --dir <plan-dir> --kind <plan|recap>`.
64
- It starts the bridge, checks the private-network preflight and JSON payload,
65
- prints diagnostics, and exits. If the browser hangs on "Loading plan", fetch the
66
- `bridgeUrl` from the verify/serve JSON to read the concrete validation error.
66
+ It starts the bridge, checks the private-network preflight and JSON payload, AND
67
+ validates the content against the real renderer schema via the Plan app's
68
+ `validate-local-plan-source` action. A non-`ok` result with
69
+ `validation.valid: false` lists the renderer's exact schema-path issues (e.g.
70
+ `blocks[1].data.tabs[0]...`); fix those before handing off. If `validation.ran`
71
+ is `false`, the Plan app did not expose the validate endpoint (older/unreachable
72
+ deploy) — point `--app-url` at a current Plan app (e.g. a local
73
+ `http://localhost:8096`) for the authoritative check. If the browser hangs on
74
+ "Loading plan", fetch the `bridgeUrl` from the verify/serve JSON to read the
75
+ concrete validation error.
67
76
  - **Never call hosted tools for that plan/recap.** Do not call
68
77
  `create-visual-plan`, `create-ui-plan`, `create-prototype-plan`,
69
78
  `create-plan-design`, `create-visual-recap`, `create-visual-questions`,
@@ -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"),
@@ -0,0 +1,110 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+
4
+ import { parsePlanMdxFolder, planMdxFileSchema } from "../server/plan-mdx.js";
5
+
6
+ /**
7
+ * Authoritative validation for a local plan MDX folder.
8
+ *
9
+ * This runs the SAME `parsePlanMdxFolder` + `planContentSchema` the renderer
10
+ * uses, so a `valid: true` result here means the Plan app will actually render
11
+ * the folder — closing the "passed locally, broken when rendered" gap between
12
+ * the hand-rolled `plan local check` lint and the real renderer schema.
13
+ *
14
+ * It is intentionally a pure parse: it accepts the posted MDX folder, never
15
+ * reads `schema.plans`, never touches the filesystem, and never writes to the
16
+ * database. That keeps it safe to expose without auth so the offline-friendly
17
+ * `plan local verify` CLI can call it against a local or hosted Plan app.
18
+ */
19
+
20
+ // Covers the CLI's 10 MiB raw asset cap (~13.3 MiB base64) plus MDX text, so
21
+ // large-but-valid plans still get authoritative validation instead of the lint.
22
+ const MAX_MDX_BYTES = 16 * 1024 * 1024;
23
+
24
+ type ValidationIssue = { path: string; message: string };
25
+
26
+ function formatZodPath(segments: Array<string | number>): string {
27
+ let out = "";
28
+ for (const segment of segments) {
29
+ if (typeof segment === "number") out += `[${segment}]`;
30
+ else out += out ? `.${segment}` : segment;
31
+ }
32
+ return out;
33
+ }
34
+
35
+ function toValidationIssues(error: unknown): ValidationIssue[] {
36
+ if (
37
+ error &&
38
+ typeof error === "object" &&
39
+ "issues" in error &&
40
+ Array.isArray((error as { issues?: unknown }).issues)
41
+ ) {
42
+ const issues = (error as { issues: unknown[] }).issues;
43
+ const mapped: ValidationIssue[] = [];
44
+ for (const raw of issues) {
45
+ if (!raw || typeof raw !== "object") continue;
46
+ const issue = raw as { path?: unknown; message?: unknown };
47
+ const path = Array.isArray(issue.path)
48
+ ? formatZodPath(issue.path as Array<string | number>)
49
+ : "";
50
+ const message =
51
+ typeof issue.message === "string" ? issue.message : "Invalid value";
52
+ mapped.push({ path, message });
53
+ }
54
+ if (mapped.length > 0) return mapped;
55
+ }
56
+ return [
57
+ {
58
+ path: "",
59
+ message: error instanceof Error ? error.message : String(error),
60
+ },
61
+ ];
62
+ }
63
+
64
+ export default defineAction({
65
+ description:
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.",
67
+ schema: z.object({
68
+ mdx: planMdxFileSchema.describe(
69
+ "The plan MDX folder: plan.mdx plus optional canvas.mdx, prototype.mdx, .plan-state.json, and assets/.",
70
+ ),
71
+ }),
72
+ http: { method: "POST" },
73
+ readOnly: true,
74
+ requiresAuth: false,
75
+ // Route-level cap (413 before parse). 2x MAX_MDX_BYTES for JSON wire overhead;
76
+ // run() still enforces the precise content limit.
77
+ maxBodyBytes: MAX_MDX_BYTES * 2,
78
+ publicAgent: {
79
+ expose: true,
80
+ readOnly: true,
81
+ requiresAuth: false,
82
+ title: "Validate Local Plan Source",
83
+ description:
84
+ "Validate a local plan MDX folder against the real renderer schema without touching the database.",
85
+ },
86
+ run: async (args) => {
87
+ let totalBytes = 0;
88
+ for (const value of Object.values(args.mdx)) {
89
+ if (typeof value === "string") {
90
+ totalBytes += Buffer.byteLength(value);
91
+ } else if (value && typeof value === "object") {
92
+ for (const asset of Object.values(value)) {
93
+ if (typeof asset === "string") totalBytes += Buffer.byteLength(asset);
94
+ }
95
+ }
96
+ }
97
+ if (totalBytes > MAX_MDX_BYTES) {
98
+ throw new Error(
99
+ `Plan MDX folder is too large to validate (${totalBytes} bytes > ${MAX_MDX_BYTES}).`,
100
+ );
101
+ }
102
+
103
+ try {
104
+ await parsePlanMdxFolder(args.mdx);
105
+ return { valid: true as const, issues: [] as ValidationIssue[] };
106
+ } catch (error) {
107
+ return { valid: false as const, issues: toValidationIssues(error) };
108
+ }
109
+ },
110
+ });
@@ -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.** |
@@ -46,6 +46,7 @@ export const PLAN_CONNECTOR_CATALOG: string[] = [
46
46
  "export-visual-plan",
47
47
  "import-visual-plan-source",
48
48
  "patch-visual-plan-source",
49
+ "validate-local-plan-source",
49
50
  // Plan publish & convert
50
51
  "publish-visual-plan",
51
52
  "convert-visual-plan-to-prototype",
@@ -7,6 +7,7 @@ export const PUBLIC_PLAN_ACTION_PATHS = [
7
7
  "/_agent-native/actions/get-plan-feedback",
8
8
  "/_agent-native/actions/get-plan-access-status",
9
9
  "/_agent-native/actions/get-plan-blocks",
10
+ "/_agent-native/actions/validate-local-plan-source",
10
11
  "/_agent-native/actions/read-visual-plan-source",
11
12
  "/_agent-native/actions/get-plan-version",
12
13
  "/_agent-native/actions/list-plan-versions",
@@ -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
  });