@agent-native/core 0.92.7 → 0.92.9

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 (295) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +18 -0
  3. package/corpus/core/docs/content/a2a-protocol.mdx +12 -0
  4. package/corpus/core/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
  5. package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
  6. package/corpus/core/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
  7. package/corpus/core/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
  8. package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
  9. package/corpus/core/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
  10. package/corpus/core/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
  11. package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
  12. package/corpus/core/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
  13. package/corpus/core/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
  14. package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
  15. package/corpus/core/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
  16. package/corpus/core/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
  17. package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
  18. package/corpus/core/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
  19. package/corpus/core/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
  20. package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
  21. package/corpus/core/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
  22. package/corpus/core/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
  23. package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
  24. package/corpus/core/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
  25. package/corpus/core/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
  26. package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
  27. package/corpus/core/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
  28. package/corpus/core/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
  29. package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
  30. package/corpus/core/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
  31. package/corpus/core/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
  32. package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
  33. package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
  34. package/corpus/core/docs/content/pr-visual-recap.mdx +3 -3
  35. package/corpus/core/docs/content/pure-agent-apps.mdx +22 -0
  36. package/corpus/core/package.json +1 -1
  37. package/corpus/core/src/agent/engine/builtin.ts +1 -1
  38. package/corpus/core/src/agent/model-config.ts +30 -30
  39. package/corpus/core/src/agent/production-agent.ts +129 -7
  40. package/corpus/core/src/cli/design-connect.ts +438 -83
  41. package/corpus/core/src/cli/recap.ts +17 -3
  42. package/corpus/core/src/client/AgentPanel.tsx +8 -1
  43. package/corpus/core/src/client/agent-chat-adapter.ts +12 -7
  44. package/corpus/core/src/client/composer/TiptapComposer.tsx +1 -1
  45. package/corpus/core/src/client/index.ts +4 -0
  46. package/corpus/core/src/client/org/TeamPage.tsx +41 -26
  47. package/corpus/core/src/client/use-action.ts +113 -1
  48. package/corpus/core/src/db/client.ts +12 -2
  49. package/corpus/core/src/db/create-get-db.ts +4 -1
  50. package/corpus/core/src/scripts/agent-engines/manage-agent-engine.ts +1 -1
  51. package/corpus/core/src/scripts/agent-engines/set-agent-engine.ts +1 -1
  52. package/corpus/core/src/server/ssr-handler.ts +7 -0
  53. package/corpus/core/src/server/transcribe-voice.ts +1 -1
  54. package/corpus/core/src/usage/store.ts +13 -4
  55. package/corpus/core/src/vite/client.ts +38 -1
  56. package/corpus/templates/analytics/AGENTS.md +3 -0
  57. package/corpus/templates/analytics/actions/get-data-program.ts +78 -0
  58. package/corpus/templates/analytics/actions/list-data-programs.ts +49 -0
  59. package/corpus/templates/analytics/app/global.css +11 -0
  60. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +163 -17
  61. package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
  62. package/corpus/templates/analytics/app/i18n-data.ts +20 -0
  63. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +96 -3
  64. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -1
  65. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +61 -4
  66. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +40 -2
  67. package/corpus/templates/analytics/changelog/2026-07-09-analytics-no-longer-forgets-successful-data-queries-when-a-l.md +6 -0
  68. package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-keep-consistent-spacing-when-they-stack-ver.md +6 -0
  69. package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-tables-and-extensions-can-be-selected-and-d.md +6 -0
  70. package/corpus/templates/analytics/changelog/2026-07-09-long-running-analytics-requests-now-recover-automatically-wh.md +6 -0
  71. package/corpus/templates/analytics/server/db/index.ts +6 -0
  72. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +1 -7
  73. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +102 -15
  74. package/corpus/templates/content/app/hooks/use-content-database.ts +52 -0
  75. package/corpus/templates/content/app/hooks/use-document-properties.ts +50 -6
  76. package/corpus/templates/content/app/i18n/zh-TW.ts +2 -0
  77. package/corpus/templates/content/app/i18n-data.ts +28 -0
  78. package/corpus/templates/content/changelog/2026-07-09-notion-conflict-warnings-no-longer-flash-during-normal-synce.md +6 -0
  79. package/corpus/templates/content/changelog/2026-07-09-property-menus-and-delete-confirmations-now-open-visibly-and.md +6 -0
  80. package/corpus/templates/content/server/lib/notion-sync.ts +130 -28
  81. package/corpus/templates/design/actions/add-breakpoint.ts +48 -68
  82. package/corpus/templates/design/actions/add-localhost-screens.ts +496 -61
  83. package/corpus/templates/design/actions/apply-component-prop-edit.ts +2 -18
  84. package/corpus/templates/design/actions/apply-design-token-edit.ts +51 -82
  85. package/corpus/templates/design/actions/apply-tweaks.ts +63 -41
  86. package/corpus/templates/design/actions/capture-design-state.ts +2 -2
  87. package/corpus/templates/design/actions/connect-localhost.ts +58 -12
  88. package/corpus/templates/design/actions/create-component.ts +2 -18
  89. package/corpus/templates/design/actions/create-design-branch.ts +38 -18
  90. package/corpus/templates/design/actions/create-fusion-app.ts +15 -11
  91. package/corpus/templates/design/actions/delete-file.ts +19 -34
  92. package/corpus/templates/design/actions/deploy-design-preview.ts +59 -27
  93. package/corpus/templates/design/actions/deploy-fusion-app.ts +22 -15
  94. package/corpus/templates/design/actions/export-pdf.ts +2 -1
  95. package/corpus/templates/design/actions/export-zip.ts +9 -3
  96. package/corpus/templates/design/actions/generate-design.ts +107 -70
  97. package/corpus/templates/design/actions/get-component-details.ts +2 -18
  98. package/corpus/templates/design/actions/get-design-branch-diff.ts +2 -3
  99. package/corpus/templates/design/actions/get-design-surface-index.ts +2 -18
  100. package/corpus/templates/design/actions/get-design.ts +2 -1
  101. package/corpus/templates/design/actions/grant-localhost-write-consent.ts +7 -1
  102. package/corpus/templates/design/actions/import-design-tokens.ts +114 -76
  103. package/corpus/templates/design/actions/index-components.ts +2 -18
  104. package/corpus/templates/design/actions/list-design-source-capabilities.ts +23 -28
  105. package/corpus/templates/design/actions/list-local-files.ts +9 -2
  106. package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +82 -98
  107. package/corpus/templates/design/actions/open-component-source.ts +2 -18
  108. package/corpus/templates/design/actions/open-visual-edit.ts +19 -1
  109. package/corpus/templates/design/actions/present-design-variants.ts +70 -70
  110. package/corpus/templates/design/actions/preview-component-prop-edit.ts +4 -14
  111. package/corpus/templates/design/actions/read-local-file.ts +9 -2
  112. package/corpus/templates/design/actions/remove-breakpoint.ts +40 -61
  113. package/corpus/templates/design/actions/rename-screen.ts +425 -0
  114. package/corpus/templates/design/actions/request-localhost-write-consent.ts +12 -2
  115. package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +9 -2
  116. package/corpus/templates/design/actions/sync-fusion-app.ts +56 -39
  117. package/corpus/templates/design/actions/update-design.ts +376 -61
  118. package/corpus/templates/design/actions/update-file.ts +455 -188
  119. package/corpus/templates/design/actions/write-local-file.ts +10 -2
  120. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +685 -608
  121. package/corpus/templates/design/app/components/design/LayersPanel.tsx +43 -15
  122. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +576 -2015
  123. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +62 -14
  124. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +263 -25
  125. package/corpus/templates/design/app/components/design/design-canvas/annotation-submit.ts +34 -0
  126. package/corpus/templates/design/app/components/design/design-canvas/coordinate-transforms.ts +40 -0
  127. package/corpus/templates/design/app/components/design/design-canvas/creation.ts +47 -0
  128. package/corpus/templates/design/app/components/design/design-canvas/element-payload.ts +27 -0
  129. package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +62 -0
  130. package/corpus/templates/design/app/components/design/design-canvas/external-preview.ts +137 -0
  131. package/corpus/templates/design/app/components/design/design-canvas/file-drop.ts +10 -0
  132. package/corpus/templates/design/app/components/design/design-canvas/hit-test.ts +23 -0
  133. package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +23 -0
  134. package/corpus/templates/design/app/components/design/design-canvas/iframe-pan.ts +177 -0
  135. package/corpus/templates/design/app/components/design/design-canvas/motion-types.ts +7 -0
  136. package/corpus/templates/design/app/components/design/design-canvas/pending-text-edit.ts +62 -0
  137. package/corpus/templates/design/app/components/design/index.ts +2 -2
  138. package/corpus/templates/design/app/components/design/multi-screen/canvas-tools.ts +100 -0
  139. package/corpus/templates/design/app/components/design/multi-screen/coordinate-transforms.ts +81 -0
  140. package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +23 -13
  141. package/corpus/templates/design/app/components/design/multi-screen/culling.ts +238 -19
  142. package/corpus/templates/design/app/components/design/multi-screen/draft-primitives.ts +424 -0
  143. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +341 -0
  144. package/corpus/templates/design/app/components/design/multi-screen/iframe-targeting.ts +52 -0
  145. package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +62 -0
  146. package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +283 -0
  147. package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +272 -0
  148. package/corpus/templates/design/app/components/design/multi-screen/types.ts +5 -1
  149. package/corpus/templates/design/app/components/design/multi-screen/wheel-gesture-state.ts +12 -0
  150. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +325 -84
  151. package/corpus/templates/design/app/hooks/use-navigation-state.ts +15 -1
  152. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +119 -47
  153. package/corpus/templates/design/app/i18n/zh-TW.ts +9 -0
  154. package/corpus/templates/design/app/i18n-data.ts +223 -0
  155. package/corpus/templates/design/app/lib/design-save-outbox.ts +379 -0
  156. package/corpus/templates/design/app/lib/png-clipboard.ts +113 -0
  157. package/corpus/templates/design/app/pages/design-editor/canvas-primitives.ts +229 -0
  158. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +918 -0
  159. package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +43 -0
  160. package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +336 -0
  161. package/corpus/templates/design/app/pages/design-editor/data-operations.ts +270 -0
  162. package/corpus/templates/design/app/pages/design-editor/dom-guards.ts +24 -0
  163. package/corpus/templates/design/app/pages/design-editor/dom-utils.ts +11 -0
  164. package/corpus/templates/design/app/pages/design-editor/editor-session.ts +20 -0
  165. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +408 -0
  166. package/corpus/templates/design/app/pages/design-editor/export-capture.ts +115 -0
  167. package/corpus/templates/design/app/pages/design-editor/geometry-persistence.ts +93 -0
  168. package/corpus/templates/design/app/pages/design-editor/history.ts +169 -0
  169. package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +185 -0
  170. package/corpus/templates/design/app/pages/design-editor/motion-state.ts +309 -0
  171. package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +438 -0
  172. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +510 -0
  173. package/corpus/templates/design/app/pages/design-editor/portable-style.ts +115 -0
  174. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +337 -0
  175. package/corpus/templates/design/app/pages/design-editor/style-utils.ts +5 -0
  176. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +92 -0
  177. package/corpus/templates/design/app/pages/design-editor/tweak-save.ts +87 -0
  178. package/corpus/templates/design/app/pages/design-editor/types.ts +36 -0
  179. package/corpus/templates/design/app/routes/design.$id.tsx +11 -1
  180. package/corpus/templates/design/changelog/2026-07-09-design-edits-canvas-positions-tools-and-tab-context-now-pers.md +6 -0
  181. package/corpus/templates/design/changelog/2026-07-09-figma-style-shortcuts-drawing-annotations-and-cross-screen-d.md +6 -0
  182. package/corpus/templates/design/changelog/2026-07-09-hand-and-scale-tools-now-keep-their-active-toolbar-identity-.md +6 -0
  183. package/corpus/templates/design/changelog/2026-07-09-large-multi-screen-designs-now-stay-responsive-during-long-c.md +6 -0
  184. package/corpus/templates/design/changelog/2026-07-09-layer-drags-now-land-exactly-where-the-insertion-indicator-s.md +6 -0
  185. package/corpus/templates/design/server/db/index.ts +2 -52
  186. package/corpus/templates/design/server/db/schema.ts +16 -0
  187. package/corpus/templates/design/server/lib/design-data-access.ts +70 -0
  188. package/corpus/templates/design/server/lib/design-data-mutation.ts +249 -0
  189. package/corpus/templates/design/server/lib/fusion-screens.ts +89 -76
  190. package/corpus/templates/design/server/lib/import-design-files.ts +76 -35
  191. package/corpus/templates/design/server/lib/verify-write-grant.ts +7 -2
  192. package/corpus/templates/design/server/plugins/db.ts +19 -0
  193. package/corpus/templates/design/server/source-workspace.ts +12 -13
  194. package/corpus/templates/design/shared/resolve-tweaks.ts +15 -0
  195. package/corpus/templates/design/shared/screen-rename.ts +42 -0
  196. package/corpus/templates/design/shared/source-mode.ts +84 -4
  197. package/dist/agent/engine/builder-engine.d.ts +1 -1
  198. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  199. package/dist/agent/engine/builtin.js +1 -1
  200. package/dist/agent/engine/builtin.js.map +1 -1
  201. package/dist/agent/model-config.d.ts +9 -9
  202. package/dist/agent/model-config.d.ts.map +1 -1
  203. package/dist/agent/model-config.js +30 -30
  204. package/dist/agent/model-config.js.map +1 -1
  205. package/dist/agent/production-agent.d.ts +60 -1
  206. package/dist/agent/production-agent.d.ts.map +1 -1
  207. package/dist/agent/production-agent.js +106 -7
  208. package/dist/agent/production-agent.js.map +1 -1
  209. package/dist/cli/design-connect.d.ts +30 -1
  210. package/dist/cli/design-connect.d.ts.map +1 -1
  211. package/dist/cli/design-connect.js +359 -75
  212. package/dist/cli/design-connect.js.map +1 -1
  213. package/dist/cli/recap.d.ts.map +1 -1
  214. package/dist/cli/recap.js +13 -3
  215. package/dist/cli/recap.js.map +1 -1
  216. package/dist/client/AgentPanel.d.ts.map +1 -1
  217. package/dist/client/AgentPanel.js +6 -1
  218. package/dist/client/AgentPanel.js.map +1 -1
  219. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  220. package/dist/client/agent-chat-adapter.js +10 -5
  221. package/dist/client/agent-chat-adapter.js.map +1 -1
  222. package/dist/client/composer/TiptapComposer.js +1 -1
  223. package/dist/client/composer/TiptapComposer.js.map +1 -1
  224. package/dist/client/index.d.ts +1 -1
  225. package/dist/client/index.d.ts.map +1 -1
  226. package/dist/client/index.js +1 -1
  227. package/dist/client/index.js.map +1 -1
  228. package/dist/client/org/TeamPage.d.ts.map +1 -1
  229. package/dist/client/org/TeamPage.js +6 -5
  230. package/dist/client/org/TeamPage.js.map +1 -1
  231. package/dist/client/use-action.d.ts +32 -0
  232. package/dist/client/use-action.d.ts.map +1 -1
  233. package/dist/client/use-action.js +68 -1
  234. package/dist/client/use-action.js.map +1 -1
  235. package/dist/collab/struct-routes.d.ts +1 -1
  236. package/dist/db/client.d.ts +3 -0
  237. package/dist/db/client.d.ts.map +1 -1
  238. package/dist/db/client.js +7 -2
  239. package/dist/db/client.js.map +1 -1
  240. package/dist/db/create-get-db.d.ts.map +1 -1
  241. package/dist/db/create-get-db.js +2 -2
  242. package/dist/db/create-get-db.js.map +1 -1
  243. package/dist/notifications/routes.d.ts +3 -3
  244. package/dist/observability/routes.d.ts +1 -1
  245. package/dist/resources/handlers.d.ts +3 -3
  246. package/dist/scripts/agent-engines/manage-agent-engine.js +1 -1
  247. package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
  248. package/dist/scripts/agent-engines/set-agent-engine.js +1 -1
  249. package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
  250. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  251. package/dist/server/ssr-handler.d.ts.map +1 -1
  252. package/dist/server/ssr-handler.js +7 -0
  253. package/dist/server/ssr-handler.js.map +1 -1
  254. package/dist/server/transcribe-voice.js +1 -1
  255. package/dist/server/transcribe-voice.js.map +1 -1
  256. package/dist/usage/store.d.ts.map +1 -1
  257. package/dist/usage/store.js +13 -4
  258. package/dist/usage/store.js.map +1 -1
  259. package/dist/vite/client.d.ts.map +1 -1
  260. package/dist/vite/client.js +36 -1
  261. package/dist/vite/client.js.map +1 -1
  262. package/docs/content/a2a-protocol.mdx +12 -0
  263. package/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
  264. package/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
  265. package/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
  266. package/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
  267. package/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
  268. package/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
  269. package/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
  270. package/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
  271. package/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
  272. package/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
  273. package/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
  274. package/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
  275. package/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
  276. package/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
  277. package/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
  278. package/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
  279. package/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
  280. package/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
  281. package/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
  282. package/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
  283. package/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
  284. package/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
  285. package/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
  286. package/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
  287. package/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
  288. package/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
  289. package/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
  290. package/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
  291. package/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
  292. package/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
  293. package/docs/content/pr-visual-recap.mdx +3 -3
  294. package/docs/content/pure-agent-apps.mdx +22 -0
  295. package/package.json +2 -2
@@ -4,21 +4,12 @@ import { and, eq } from "drizzle-orm";
4
4
  import { z } from "zod";
5
5
 
6
6
  import { getDb, schema } from "../server/db/index.js";
7
+ import { mutateDesignData } from "../server/lib/design-data-mutation.js";
7
8
 
8
9
  function isRecord(value: unknown): value is Record<string, unknown> {
9
10
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
10
11
  }
11
12
 
12
- function parseDesignData(value: unknown): Record<string, unknown> {
13
- if (typeof value !== "string" || !value.trim()) return {};
14
- try {
15
- const parsed = JSON.parse(value);
16
- return isRecord(parsed) ? parsed : {};
17
- } catch {
18
- return {};
19
- }
20
- }
21
-
22
13
  function pruneKeyedRecord(
23
14
  value: unknown,
24
15
  fileId: string,
@@ -100,30 +91,24 @@ export default defineAction({
100
91
 
101
92
  await assertAccess("design", file.designId, "editor");
102
93
 
103
- const now = new Date().toISOString();
104
-
105
- await db.transaction(async (tx) => {
106
- const [currentDesign] = await tx
107
- .select({ data: schema.designs.data })
108
- .from(schema.designs)
109
- .where(eq(schema.designs.id, file.designId))
110
- .limit(1);
111
- const nextData = pruneDeletedFileMetadata(
112
- parseDesignData(currentDesign?.data),
113
- id,
114
- );
115
-
116
- await tx.delete(schema.designFiles).where(eq(schema.designFiles.id, id));
117
-
118
- // Update the parent design's board metadata and updatedAt timestamp.
119
- await tx
120
- .update(schema.designs)
121
- .set({
122
- data: JSON.stringify({ ...nextData, updatedAt: now }),
123
- updatedAt: now,
124
- })
125
- .where(eq(schema.designs.id, file.designId));
126
- });
94
+ const pruneMetadata = () =>
95
+ mutateDesignData({
96
+ designId: file.designId,
97
+ mutate: (current, { updatedAt }) => ({
98
+ ...pruneDeletedFileMetadata(current, id),
99
+ updatedAt,
100
+ }),
101
+ isApplied: (current) =>
102
+ JSON.stringify(pruneDeletedFileMetadata(current, id)) ===
103
+ JSON.stringify(current),
104
+ });
105
+
106
+ // Prune before deletion so a retry never loses the parent design id, then
107
+ // prune once more after deletion to close the small window where another
108
+ // editor could have refreshed metadata for the still-existing file.
109
+ await pruneMetadata();
110
+ await db.delete(schema.designFiles).where(eq(schema.designFiles.id, id));
111
+ await pruneMetadata();
127
112
 
128
113
  return { id, deleted: true };
129
114
  },
@@ -32,17 +32,16 @@ import {
32
32
  } from "@agent-native/core/server";
33
33
  import { getRequestUserEmail } from "@agent-native/core/server/request-context";
34
34
  import { assertAccess, resolveAccess } from "@agent-native/core/sharing";
35
- import { eq } from "drizzle-orm";
36
35
  import { z } from "zod";
37
36
 
38
- import { getDb, schema } from "../server/db/index.js";
39
37
  import "../server/db/index.js"; // ensure registerShareableResource runs
38
+ import { mutateDesignData } from "../server/lib/design-data-mutation.js";
40
39
  import {
41
40
  resolveSourceCapabilities,
42
41
  resolveFusionCapabilities,
43
42
  } from "../shared/capability-resolver.js";
44
43
  import { hasCapability } from "../shared/design-source-capabilities.js";
45
- import { normalizeDesignSourceType } from "../shared/source-mode.js";
44
+ import { designSourceTypeFromData } from "../shared/source-mode.js";
46
45
 
47
46
  // ─── Helpers ──────────────────────────────────────────────────────────────────
48
47
 
@@ -126,8 +125,6 @@ export default defineAction({
126
125
  ),
127
126
  }),
128
127
  run: async ({ designId, branchName }) => {
129
- const db = getDb();
130
-
131
128
  // ── Access check (editor level required for deploys) ────────────────────
132
129
  await assertAccess("design", designId, "editor");
133
130
  const access = await resolveAccess("design", designId);
@@ -140,8 +137,7 @@ export default defineAction({
140
137
 
141
138
  // ── Source type + capability check ──────────────────────────────────────
142
139
  const designData = parseDesignData(resource.data);
143
- const sourceType =
144
- normalizeDesignSourceType(designData["sourceType"]) ?? "inline";
140
+ const sourceType = designSourceTypeFromData(designData);
145
141
 
146
142
  // For fusion sources, resolve the Builder connection status first so that
147
143
  // resolveFusionCapabilities returns the CONNECTED map (with deployPreview
@@ -228,28 +224,64 @@ export default defineAction({
228
224
 
229
225
  // ── Persist preview URL + deploy status into the branch entry ────────────
230
226
  const now = new Date().toISOString();
231
- const updatedBranches = branches.map((b) => {
232
- if (b.branchName?.toLowerCase() !== branch!.branchName!.toLowerCase()) {
233
- return b;
234
- }
235
- return {
236
- ...b,
237
- previewUrl: builderResult.url,
238
- deployStatus: builderResult.status,
239
- lastDeployedAt: now,
240
- };
241
- });
242
-
243
- const updatedData = JSON.stringify({
244
- ...designData,
245
- branches: updatedBranches,
227
+ const targetBranchName = branch.branchName;
228
+ await mutateDesignData({
229
+ designId,
230
+ mutate: (current) => {
231
+ const latestBranches = Array.isArray(current.branches)
232
+ ? current.branches
233
+ : [];
234
+ let found = false;
235
+ const updatedBranches = latestBranches.map((candidate) => {
236
+ if (
237
+ candidate === null ||
238
+ typeof candidate !== "object" ||
239
+ Array.isArray(candidate)
240
+ ) {
241
+ return candidate;
242
+ }
243
+ const stored = candidate as StoredBranchEntry;
244
+ if (
245
+ stored.branchName?.toLowerCase() !== targetBranchName.toLowerCase()
246
+ ) {
247
+ return candidate;
248
+ }
249
+ found = true;
250
+ return {
251
+ ...stored,
252
+ previewUrl: builderResult.url,
253
+ deployStatus: builderResult.status,
254
+ lastDeployedAt: now,
255
+ };
256
+ });
257
+ if (!found) {
258
+ throw new Error(
259
+ `Branch "${targetBranchName}" was removed while its preview was building. The preview was not attached to stale design data.`,
260
+ );
261
+ }
262
+ return { ...current, branches: updatedBranches };
263
+ },
264
+ isApplied: (current) =>
265
+ Array.isArray(current.branches) &&
266
+ current.branches.some((candidate) => {
267
+ if (
268
+ candidate === null ||
269
+ typeof candidate !== "object" ||
270
+ Array.isArray(candidate)
271
+ ) {
272
+ return false;
273
+ }
274
+ const stored = candidate as StoredBranchEntry;
275
+ return (
276
+ stored.branchName?.toLowerCase() ===
277
+ targetBranchName.toLowerCase() &&
278
+ stored.previewUrl === builderResult.url &&
279
+ stored.deployStatus === builderResult.status &&
280
+ stored.lastDeployedAt === now
281
+ );
282
+ }),
246
283
  });
247
284
 
248
- await db
249
- .update(schema.designs)
250
- .set({ data: updatedData, updatedAt: now })
251
- .where(eq(schema.designs.id, designId));
252
-
253
285
  return {
254
286
  designId,
255
287
  sourceType,
@@ -17,14 +17,13 @@ import {
17
17
  reserveFusionHostingSlug,
18
18
  } from "@agent-native/core/server";
19
19
  import { assertAccess } from "@agent-native/core/sharing";
20
- import { eq } from "drizzle-orm";
21
20
  import { z } from "zod";
22
21
 
23
- import { getDb, schema } from "../server/db/index.js";
22
+ import { schema } from "../server/db/index.js";
24
23
  import "../server/db/index.js"; // ensure registerShareableResource runs
24
+ import { mutateDesignData } from "../server/lib/design-data-mutation.js";
25
25
  import {
26
26
  FULL_APP_BUILDING_ENABLED,
27
- parseDesignDataBlob,
28
27
  readFusionApp,
29
28
  writeFusionApp,
30
29
  } from "../shared/full-app.js";
@@ -100,19 +99,27 @@ export default defineAction({
100
99
 
101
100
  const deployedUrl = getFusionHostingUrl(reservedSlug);
102
101
  const now = new Date().toISOString();
103
- const db = getDb();
104
- const nextData = writeFusionApp(parseDesignDataBlob(design.data), {
105
- ...fusionApp,
106
- hostingSlug: reservedSlug,
107
- deployedUrl,
108
- lastDeployId: deploy.deployId,
109
- lastDeployStatus: deploy.status,
110
- updatedAt: now,
102
+ await mutateDesignData({
103
+ designId,
104
+ mutate: (current) =>
105
+ writeFusionApp(current, {
106
+ ...(readFusionApp(current) ?? fusionApp),
107
+ hostingSlug: reservedSlug,
108
+ deployedUrl,
109
+ lastDeployId: deploy.deployId,
110
+ lastDeployStatus: deploy.status,
111
+ updatedAt: now,
112
+ }),
113
+ isApplied: (current) => {
114
+ const persisted = readFusionApp(current);
115
+ return (
116
+ persisted?.hostingSlug === reservedSlug &&
117
+ persisted.deployedUrl === deployedUrl &&
118
+ persisted.lastDeployId === deploy.deployId &&
119
+ persisted.lastDeployStatus === deploy.status
120
+ );
121
+ },
111
122
  });
112
- await db
113
- .update(schema.designs)
114
- .set({ data: JSON.stringify(nextData), updatedAt: now })
115
- .where(eq(schema.designs.id, designId));
116
123
 
117
124
  return {
118
125
  deployId: deploy.deployId,
@@ -4,6 +4,7 @@ import { eq } from "drizzle-orm";
4
4
  import { z } from "zod";
5
5
 
6
6
  import { getDb, schema } from "../server/db/index.js";
7
+ import { designDataForAccessRole } from "../server/lib/design-data-access.js";
7
8
  import { injectHiddenLayerExportStyle } from "../server/lib/design-export.js";
8
9
  import { isBoardFile } from "../shared/board-file.js";
9
10
  import "../server/db/index.js"; // ensure registerShareableResource runs
@@ -36,7 +37,7 @@ export default defineAction({
36
37
  title: row.title,
37
38
  description: row.description,
38
39
  projectType: row.projectType,
39
- data: row.data ?? null,
40
+ data: designDataForAccessRole(row.data ?? null, access.role),
40
41
  files: exportFiles.map((f) => ({
41
42
  id: f.id,
42
43
  filename: f.filename,
@@ -4,6 +4,7 @@ import { eq } from "drizzle-orm";
4
4
  import { z } from "zod";
5
5
 
6
6
  import { getDb, schema } from "../server/db/index.js";
7
+ import { designDataForAccessRole } from "../server/lib/design-data-access.js";
7
8
  import {
8
9
  exportFilename,
9
10
  injectHiddenLayerExportStyle,
@@ -83,9 +84,14 @@ export default defineAction({
83
84
  zip.file(filename, content);
84
85
  }
85
86
 
86
- // Add design data if present
87
- if (row.data) {
88
- zip.file(`${METADATA_ARCHIVE_DIR}/design-data.json`, row.data);
87
+ // Add design data if present. Public/viewer exports keep render metadata
88
+ // but must never serialize a localhost bridge token into the archive.
89
+ const exportDesignData = designDataForAccessRole(
90
+ row.data ?? null,
91
+ access.role,
92
+ );
93
+ if (typeof exportDesignData === "string") {
94
+ zip.file(`${METADATA_ARCHIVE_DIR}/design-data.json`, exportDesignData);
89
95
  }
90
96
 
91
97
  // Generate ZIP
@@ -16,6 +16,7 @@ import { nanoid } from "nanoid";
16
16
  import { z } from "zod";
17
17
 
18
18
  import { getDb, schema } from "../server/db/index.js";
19
+ import { mutateDesignData } from "../server/lib/design-data-mutation.js";
19
20
  import {
20
21
  readLiveSourceFile,
21
22
  writeInlineSourceFile,
@@ -23,6 +24,7 @@ import {
23
24
  } from "../server/source-workspace.js";
24
25
  import {
25
26
  mergeCanvasFramePlacements,
27
+ parseCanvasFrameGeometryById,
26
28
  type CanvasFramePlacement,
27
29
  } from "../shared/canvas-frames.js";
28
30
  import {
@@ -51,6 +53,10 @@ function isRenderableDesignFile(file: {
51
53
  );
52
54
  }
53
55
 
56
+ function jsonValuesEqual(left: unknown, right: unknown): boolean {
57
+ return JSON.stringify(left) === JSON.stringify(right);
58
+ }
59
+
54
60
  async function updateGenerationSessionForSavedFiles(
55
61
  designId: string,
56
62
  savedFilenames: string[],
@@ -292,6 +298,15 @@ const generateDesignAction = defineAction({
292
298
  );
293
299
  }
294
300
 
301
+ // Validate row existence and designs.data before writing files. The final
302
+ // mutation still re-reads the latest revision after file work; this
303
+ // preflight prevents malformed JSON from orphaning new files.
304
+ await mutateDesignData({
305
+ designId,
306
+ mutate: (current) => current,
307
+ isApplied: () => true,
308
+ });
309
+
295
310
  const existingByName = new Map(existingFiles.map((f) => [f.filename, f]));
296
311
 
297
312
  // Stamp missing data-agent-native-node-id attributes before persisting so
@@ -371,6 +386,9 @@ const generateDesignAction = defineAction({
371
386
  filename: file.filename,
372
387
  fileType: file.fileType ?? "html",
373
388
  content: file.content,
389
+ contentOperationSource: null,
390
+ contentOperationRevision: null,
391
+ contentOperationResultHash: null,
374
392
  createdAt: now,
375
393
  updatedAt: now,
376
394
  });
@@ -396,6 +414,9 @@ const generateDesignAction = defineAction({
396
414
  filename: file.filename,
397
415
  fileType: file.fileType ?? "html",
398
416
  content: file.content,
417
+ contentOperationSource: null,
418
+ contentOperationRevision: null,
419
+ contentOperationResultHash: null,
399
420
  createdAt: now,
400
421
  updatedAt: now,
401
422
  });
@@ -408,24 +429,9 @@ const generateDesignAction = defineAction({
408
429
  }
409
430
  }
410
431
 
411
- // Update design metadata
412
- const designUpdates: Record<string, unknown> = { updatedAt: now };
413
- if (designSystemId !== undefined) {
414
- designUpdates.designSystemId = designSystemId;
415
- }
416
- if (projectType !== undefined) {
417
- designUpdates.projectType = projectType;
418
- }
419
-
420
432
  // Merge with existing data so tweak definitions survive content updates.
421
433
  // The data column is a free-form JSON blob; we own these keys here and
422
434
  // leave anything else intact.
423
- //
424
- // Wrapped in a transaction so that concurrent generate-design calls for the
425
- // same design (e.g. the parallel fan-out from generate-screens) each read
426
- // the latest canvasFrames and merge their own placement on top, rather than
427
- // all reading the same stale snapshot and the last writer silently
428
- // discarding the others' frame coordinates.
429
435
  let placedFrames:
430
436
  | Array<{
431
437
  fileId: string;
@@ -433,68 +439,99 @@ const generateDesignAction = defineAction({
433
439
  frame: CanvasFramePlacement;
434
440
  }>
435
441
  | undefined;
436
- await db.transaction(async (tx) => {
437
- const [existingDesign] = await tx
438
- .select({ data: schema.designs.data })
439
- .from(schema.designs)
440
- .where(eq(schema.designs.id, designId));
441
- let prevData: Record<string, unknown> = {};
442
- if (existingDesign?.data) {
443
- try {
444
- const parsed = JSON.parse(existingDesign.data);
445
- if (parsed && typeof parsed === "object") prevData = parsed;
446
- } catch {
447
- // Stale or invalid JSON — start fresh.
442
+ const normalizedTweaks = tweaks?.map((tweak) => ({
443
+ ...tweak,
444
+ type: tweak.type === "color-swatches" ? "color-swatch" : tweak.type,
445
+ }));
446
+ await mutateDesignData({
447
+ designId,
448
+ mutate: (prevData) => {
449
+ const mergedData: Record<string, unknown> = {
450
+ ...prevData,
451
+ lastPrompt: prompt,
452
+ generatedAt: now,
453
+ fileCount: files.length,
454
+ };
455
+ if (normalizedTweaks !== undefined) {
456
+ mergedData.tweaks = normalizedTweaks;
448
457
  }
449
- }
450
- const mergedData: Record<string, unknown> = {
451
- ...prevData,
452
- lastPrompt: prompt,
453
- generatedAt: now,
454
- fileCount: files.length,
455
- };
456
- if (tweaks !== undefined) {
457
- mergedData.tweaks = tweaks.map((tweak) => ({
458
- ...tweak,
459
- type: tweak.type === "color-swatches" ? "color-swatch" : tweak.type,
460
- }));
461
- }
462
- if (canvasFrames !== undefined) {
463
- const savedByFileId = new Map(
464
- savedFiles.map((file) => [file.id, file]),
465
- );
466
- const savedByFilename = new Map(
467
- savedFiles.map((file) => [file.filename, file]),
458
+ if (canvasFrames !== undefined) {
459
+ const savedByFileId = new Map(
460
+ savedFiles.map((file) => [file.id, file]),
461
+ );
462
+ const savedByFilename = new Map(
463
+ savedFiles.map((file) => [file.filename, file]),
464
+ );
465
+ const existingByFileId = new Map(
466
+ existingFiles.map((file) => [file.id, file]),
467
+ );
468
+ const merged = mergeCanvasFramePlacements({
469
+ existing: prevData.canvasFrames,
470
+ placements: canvasFrames,
471
+ resolveFileId: (placement) => {
472
+ if (placement.fileId) {
473
+ return savedByFileId.has(placement.fileId) ||
474
+ existingByFileId.has(placement.fileId)
475
+ ? placement.fileId
476
+ : undefined;
477
+ }
478
+ return placement.filename
479
+ ? (savedByFilename.get(placement.filename)?.id ??
480
+ existingByName.get(placement.filename)?.id)
481
+ : undefined;
482
+ },
483
+ });
484
+ mergedData.canvasFrames = merged.canvasFrames;
485
+ placedFrames = merged.placedFrames;
486
+ }
487
+ return mergedData;
488
+ },
489
+ isApplied: (current) => {
490
+ if (
491
+ current.lastPrompt !== prompt ||
492
+ current.generatedAt !== now ||
493
+ current.fileCount !== files.length ||
494
+ (normalizedTweaks !== undefined &&
495
+ !jsonValuesEqual(current.tweaks, normalizedTweaks))
496
+ ) {
497
+ return false;
498
+ }
499
+ if (canvasFrames === undefined) return true;
500
+
501
+ const currentFrames = parseCanvasFrameGeometryById(
502
+ current.canvasFrames,
468
503
  );
469
- const existingByFileId = new Map(
470
- existingFiles.map((file) => [file.id, file]),
504
+ return Boolean(
505
+ placedFrames?.every(({ fileId, frame }) => {
506
+ const currentFrame = currentFrames[fileId];
507
+ return (
508
+ currentFrame !== undefined &&
509
+ Object.entries(frame).every(
510
+ ([key, value]) =>
511
+ currentFrame[key as keyof typeof currentFrame] === value,
512
+ )
513
+ );
514
+ }),
471
515
  );
472
- const merged = mergeCanvasFramePlacements({
473
- existing: prevData.canvasFrames,
474
- placements: canvasFrames,
475
- resolveFileId: (placement) => {
476
- if (placement.fileId) {
477
- return savedByFileId.has(placement.fileId) ||
478
- existingByFileId.has(placement.fileId)
479
- ? placement.fileId
480
- : undefined;
481
- }
482
- return placement.filename
483
- ? (savedByFilename.get(placement.filename)?.id ??
484
- existingByName.get(placement.filename)?.id)
485
- : undefined;
486
- },
487
- });
488
- mergedData.canvasFrames = merged.canvasFrames;
489
- placedFrames = merged.placedFrames;
490
- }
491
- designUpdates.data = JSON.stringify(mergedData);
516
+ },
517
+ });
492
518
 
493
- await tx
519
+ // designs.data/updatedAt are helper-owned. Keep the optional static column
520
+ // behavior without writing another whole data snapshot or regressing the
521
+ // helper's monotonic updatedAt revision.
522
+ const designUpdates: Record<string, unknown> = {};
523
+ if (designSystemId !== undefined) {
524
+ designUpdates.designSystemId = designSystemId;
525
+ }
526
+ if (projectType !== undefined) {
527
+ designUpdates.projectType = projectType;
528
+ }
529
+ if (Object.keys(designUpdates).length > 0) {
530
+ await db
494
531
  .update(schema.designs)
495
532
  .set(designUpdates)
496
533
  .where(eq(schema.designs.id, designId));
497
- });
534
+ }
498
535
 
499
536
  await updateGenerationSessionForSavedFiles(
500
537
  designId,
@@ -31,7 +31,7 @@ import {
31
31
  type ComponentInstance,
32
32
  } from "../shared/component-model.js";
33
33
  import { hasCapability } from "../shared/design-source-capabilities.js";
34
- import { normalizeDesignSourceType } from "../shared/source-mode.js";
34
+ import { designSourceTypeFromData } from "../shared/source-mode.js";
35
35
 
36
36
  function parseJson<T>(raw: string | null | undefined, fallback: T): T {
37
37
  if (!raw) return fallback;
@@ -74,24 +74,8 @@ export default defineAction({
74
74
  if (!access) throw new Error("Design not found");
75
75
 
76
76
  // ── Source type + capabilities ───────────────────────────────────────────
77
- let rawSourceType: unknown = "inline";
78
77
  const rawData = (access.resource as { data?: unknown }).data;
79
- if (typeof rawData === "string") {
80
- try {
81
- const parsed: unknown = JSON.parse(rawData);
82
- if (
83
- parsed !== null &&
84
- typeof parsed === "object" &&
85
- "sourceType" in (parsed as object)
86
- ) {
87
- rawSourceType = (parsed as { sourceType: unknown }).sourceType;
88
- }
89
- } catch {
90
- // Default to inline.
91
- }
92
- }
93
-
94
- const sourceType = normalizeDesignSourceType(rawSourceType) ?? "inline";
78
+ const sourceType = designSourceTypeFromData(rawData);
95
79
  const caps = resolveSourceCapabilities(sourceType);
96
80
  const canResolveToFile = hasCapability(caps, "resolveNodeToFile");
97
81
  const hasFullIndex = hasCapability(caps, "indexComponents");
@@ -33,7 +33,7 @@ import type {
33
33
  VisualDiffChangeKind,
34
34
  } from "../shared/design-review.js";
35
35
  import { hasCapability } from "../shared/design-source-capabilities.js";
36
- import { normalizeDesignSourceType } from "../shared/source-mode.js";
36
+ import { designSourceTypeFromData } from "../shared/source-mode.js";
37
37
 
38
38
  // ─── Types ────────────────────────────────────────────────────────────────────
39
39
 
@@ -209,8 +209,7 @@ export default defineAction({
209
209
 
210
210
  // ── Source type + capability check ──────────────────────────────────────
211
211
  const designData = parseDesignData(resource.data);
212
- const sourceType =
213
- normalizeDesignSourceType(designData["sourceType"]) ?? "inline";
212
+ const sourceType = designSourceTypeFromData(designData);
214
213
  const caps = resolveSourceCapabilities(sourceType);
215
214
 
216
215
  // For inline/localhost without branch capability, return a CTA.
@@ -25,7 +25,7 @@ import type {
25
25
  DesignBreakpoint,
26
26
  DesignStateKind,
27
27
  } from "../shared/design-surface-index.js";
28
- import { normalizeDesignSourceType } from "../shared/source-mode.js";
28
+ import { designSourceTypeFromData } from "../shared/source-mode.js";
29
29
 
30
30
  // ─── Helpers ──────────────────────────────────────────────────────────────────
31
31
 
@@ -449,24 +449,8 @@ export default defineAction({
449
449
  const db = getDb();
450
450
 
451
451
  // ── Resolve source type ──────────────────────────────────────────────────
452
- let rawSourceType: unknown = "inline";
453
452
  const rawData = (access.resource as { data?: unknown }).data;
454
- if (typeof rawData === "string") {
455
- try {
456
- const parsed: unknown = JSON.parse(rawData);
457
- if (
458
- parsed !== null &&
459
- typeof parsed === "object" &&
460
- !Array.isArray(parsed) &&
461
- "sourceType" in (parsed as object)
462
- ) {
463
- rawSourceType = (parsed as { sourceType: unknown }).sourceType;
464
- }
465
- } catch {
466
- // Stale/invalid JSON — default to "inline".
467
- }
468
- }
469
- const sourceType = normalizeDesignSourceType(rawSourceType) ?? "inline";
453
+ const sourceType = designSourceTypeFromData(rawData);
470
454
  const capabilities = resolveSourceCapabilities(sourceType);
471
455
  const availableCapabilities = Object.entries(capabilities)
472
456
  .filter(([, entry]) => entry.status === "available")
@@ -4,6 +4,7 @@ import { eq } from "drizzle-orm";
4
4
  import { z } from "zod";
5
5
 
6
6
  import { getDb, schema } from "../server/db/index.js";
7
+ import { designDataForAccessRole } from "../server/lib/design-data-access.js";
7
8
  import "../server/db/index.js"; // ensure registerShareableResource runs
8
9
 
9
10
  export default defineAction({
@@ -37,7 +38,7 @@ export default defineAction({
37
38
  description: row.description,
38
39
  projectType: row.projectType,
39
40
  designSystemId: row.designSystemId,
40
- data: row.data ?? null,
41
+ data: designDataForAccessRole(row.data ?? null, access.role),
41
42
  visibility: row.visibility,
42
43
  createdAt: row.createdAt,
43
44
  updatedAt: row.updatedAt,