@agent-native/core 0.80.8 → 0.80.10

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 (359) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +19 -0
  3. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +6 -0
  4. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +8 -0
  5. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +10 -2
  6. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +10 -2
  7. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +7 -0
  8. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +7 -0
  9. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +7 -0
  10. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +9 -2
  11. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +6 -0
  12. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +6 -0
  13. package/corpus/core/docs/content/template-design.mdx +9 -2
  14. package/corpus/core/package.json +1 -1
  15. package/corpus/core/src/cli/design-connect.ts +28 -2
  16. package/corpus/core/src/cli/mcp.ts +10 -0
  17. package/corpus/core/src/cli/skills.ts +103 -36
  18. package/corpus/core/src/client/error-format.ts +25 -0
  19. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +13 -11
  20. package/corpus/core/src/client/guided-questions.tsx +32 -4
  21. package/corpus/core/src/client/onboarding/OnboardingPanel.tsx +33 -1
  22. package/corpus/core/src/client/resources/BuiltinCapabilityDetail.tsx +8 -0
  23. package/corpus/core/src/client/resources/use-builtin-capabilities.ts +4 -2
  24. package/corpus/core/src/client/session-replay.ts +34 -0
  25. package/corpus/core/src/client/sharing/ShareButton.tsx +106 -21
  26. package/corpus/core/src/coding-tools/index.ts +1 -1
  27. package/corpus/core/src/mcp/index.ts +2 -0
  28. package/corpus/core/src/mcp/screen-memory-stdio.ts +290 -0
  29. package/corpus/core/src/mcp-client/builtin-capabilities.ts +13 -1
  30. package/corpus/core/src/mcp-client/index.ts +9 -0
  31. package/corpus/core/src/mcp-client/screen-memory-local.ts +461 -0
  32. package/corpus/core/src/onboarding/types.ts +7 -0
  33. package/corpus/core/src/server/agent-chat-plugin.ts +25 -0
  34. package/corpus/core/src/server/agents-bundle.ts +35 -7
  35. package/corpus/core/src/styles/agent-native.css +5 -0
  36. package/corpus/core/src/templates/default/app/global.css +35 -35
  37. package/corpus/templates/analytics/AGENTS.md +6 -0
  38. package/corpus/templates/analytics/actions/github-repo-files.ts +9 -0
  39. package/corpus/templates/analytics/app/components/layout/Layout.tsx +4 -4
  40. package/corpus/templates/analytics/app/global.css +144 -40
  41. package/corpus/templates/analytics/app/pages/adhoc/explorer/index.tsx +1 -1
  42. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +1 -1
  43. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +1 -1
  44. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +4 -4
  45. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -9
  46. package/corpus/templates/analytics/changelog/2026-06-29-agents-can-search-and-read-connected-github-repositories-whe.md +6 -0
  47. package/corpus/templates/analytics/changelog/2026-06-29-sessions-and-explorer-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
  48. package/corpus/templates/assets/app/components/layout/Layout.tsx +3 -1
  49. package/corpus/templates/assets/app/components/library/LibraryPresetGrid.tsx +1 -1
  50. package/corpus/templates/assets/app/global.css +99 -35
  51. package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -2
  52. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +4 -4
  53. package/corpus/templates/assets/app/routes/library.tsx +4 -4
  54. package/corpus/templates/assets/changelog/2026-06-29-asset-library-and-detail-layouts-adapt-when-the-agent-sidebar.md +6 -0
  55. package/corpus/templates/brain/app/components/layout/Layout.tsx +1 -1
  56. package/corpus/templates/brain/app/global.css +63 -35
  57. package/corpus/templates/brain/app/routes/search.tsx +1 -1
  58. package/corpus/templates/brain/app/routes/settings.tsx +1 -1
  59. package/corpus/templates/brain/app/routes/sources.tsx +2 -2
  60. package/corpus/templates/brain/changelog/2026-06-29-search-settings-and-source-layouts-adapt-when-the-agent-sidebar.md +6 -0
  61. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +4 -4
  62. package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +3 -2
  63. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +4 -2
  64. package/corpus/templates/calendar/app/global.css +69 -35
  65. package/corpus/templates/calendar/changelog/2026-06-29-event-and-find-time-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
  66. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
  67. package/corpus/templates/chat/app/global.css +35 -35
  68. package/corpus/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  69. package/corpus/templates/clips/AGENTS.md +13 -0
  70. package/corpus/templates/clips/actions/get-screen-memory-status.ts +12 -0
  71. package/corpus/templates/clips/actions/query-screen-memory-context.ts +29 -0
  72. package/corpus/templates/clips/actions/view-screen.ts +2 -2
  73. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  74. package/corpus/templates/clips/app/global.css +47 -35
  75. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +3 -3
  76. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +45 -18
  77. package/corpus/templates/clips/changelog/2026-06-29-meeting-detail-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-06-29-screen-memory-keeps-a-local-rolling-screen-buffer-for-agent-context.md +5 -0
  79. package/corpus/templates/clips/changelog/2026-06-29-video-chat-is-easier-to-find-on-recording-pages-and-s3-setup.md +6 -0
  80. package/corpus/templates/clips/chrome-extension/src/styles.css +39 -39
  81. package/corpus/templates/clips/desktop/src/app.tsx +290 -1
  82. package/corpus/templates/clips/desktop/src/shared/config.ts +83 -0
  83. package/corpus/templates/clips/desktop/src/styles.css +67 -52
  84. package/corpus/templates/clips/desktop/src-tauri/src/config.rs +50 -0
  85. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +17 -0
  86. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +13 -13
  87. package/corpus/templates/clips/desktop/src-tauri/src/screen_memory.rs +990 -0
  88. package/corpus/templates/clips/server/plugins/onboarding.ts +2 -0
  89. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +3 -3
  90. package/corpus/templates/content/app/components/layout/Layout.tsx +1 -1
  91. package/corpus/templates/content/app/global.css +29 -15
  92. package/corpus/templates/content/changelog/2026-06-29-database-gallery-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  93. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +25 -20
  94. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
  95. package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +8 -0
  96. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +13 -0
  97. package/corpus/templates/design/AGENTS.md +20 -12
  98. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1054 -0
  99. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +717 -0
  100. package/corpus/templates/design/actions/add-breakpoint.ts +143 -0
  101. package/corpus/templates/design/actions/add-localhost-screens.ts +5 -0
  102. package/corpus/templates/design/actions/apply-a11y-fix.ts +317 -0
  103. package/corpus/templates/design/actions/apply-component-prop-edit.ts +433 -0
  104. package/corpus/templates/design/actions/apply-design-state.ts +200 -0
  105. package/corpus/templates/design/actions/apply-design-token-edit.ts +202 -0
  106. package/corpus/templates/design/actions/apply-motion-edit.ts +450 -0
  107. package/corpus/templates/design/actions/apply-shader-fill.ts +404 -0
  108. package/corpus/templates/design/actions/apply-visual-edit.ts +214 -8
  109. package/corpus/templates/design/actions/capture-design-state.ts +224 -0
  110. package/corpus/templates/design/actions/connect-builder-app.ts +162 -0
  111. package/corpus/templates/design/actions/create-component.ts +447 -0
  112. package/corpus/templates/design/actions/create-design-branch.ts +263 -0
  113. package/corpus/templates/design/actions/create-design-state.ts +162 -0
  114. package/corpus/templates/design/actions/delete-design-state.ts +55 -0
  115. package/corpus/templates/design/actions/deploy-design-preview.ts +275 -0
  116. package/corpus/templates/design/actions/export-coding-handoff.ts +12 -4
  117. package/corpus/templates/design/actions/generate-design.ts +6 -21
  118. package/corpus/templates/design/actions/generate-screens.ts +43 -2
  119. package/corpus/templates/design/actions/get-component-details.ts +242 -0
  120. package/corpus/templates/design/actions/get-design-branch-diff.ts +362 -0
  121. package/corpus/templates/design/actions/get-design-review.ts +314 -0
  122. package/corpus/templates/design/actions/get-design-surface-index.ts +582 -0
  123. package/corpus/templates/design/actions/get-design.ts +1 -0
  124. package/corpus/templates/design/actions/get-motion-timeline.ts +99 -0
  125. package/corpus/templates/design/actions/index-components.ts +258 -0
  126. package/corpus/templates/design/actions/index-design-tokens.ts +273 -0
  127. package/corpus/templates/design/actions/list-design-extensions.ts +309 -0
  128. package/corpus/templates/design/actions/list-design-source-capabilities.ts +153 -0
  129. package/corpus/templates/design/actions/list-design-states.ts +72 -0
  130. package/corpus/templates/design/actions/migrate-inline-design-to-app.ts +298 -0
  131. package/corpus/templates/design/actions/open-component-source.ts +237 -0
  132. package/corpus/templates/design/actions/present-design-variants.ts +355 -30
  133. package/corpus/templates/design/actions/preview-component-prop-edit.ts +254 -0
  134. package/corpus/templates/design/actions/preview-design-token-edit.ts +113 -0
  135. package/corpus/templates/design/actions/preview-shader-fill.ts +189 -0
  136. package/corpus/templates/design/actions/remove-breakpoint.ts +103 -0
  137. package/corpus/templates/design/actions/remove-motion-timeline.ts +196 -0
  138. package/corpus/templates/design/actions/run-design-audit.ts +421 -0
  139. package/corpus/templates/design/actions/run-design-extension-action.ts +284 -0
  140. package/corpus/templates/design/actions/set-active-breakpoint.ts +39 -0
  141. package/corpus/templates/design/actions/view-screen.ts +75 -31
  142. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +1738 -135
  143. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +1 -1
  144. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +632 -43
  145. package/corpus/templates/design/app/components/design/DrawOverlay.tsx +1 -1
  146. package/corpus/templates/design/app/components/design/EditPanel.tsx +1873 -132
  147. package/corpus/templates/design/app/components/design/LayersPanel.tsx +384 -219
  148. package/corpus/templates/design/app/components/design/LocalSourceEditBanner.tsx +157 -0
  149. package/corpus/templates/design/app/components/design/MotionDock.tsx +1062 -0
  150. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +2103 -295
  151. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +83 -206
  152. package/corpus/templates/design/app/components/design/ReviewPanel.tsx +759 -0
  153. package/corpus/templates/design/app/components/design/StatesPanel.tsx +579 -0
  154. package/corpus/templates/design/app/components/design/TokensPanel.tsx +573 -0
  155. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +1 -1
  156. package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +241 -0
  157. package/corpus/templates/design/app/components/design/index.ts +16 -1
  158. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +238 -137
  159. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +188 -14
  160. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +24 -5
  161. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -1
  162. package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +145 -0
  163. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +42 -12
  164. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +37 -12
  165. package/corpus/templates/design/app/components/design/inspector/index.ts +1 -0
  166. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +12 -5
  167. package/corpus/templates/design/app/components/design/types.ts +9 -0
  168. package/corpus/templates/design/app/components/layout/Layout.tsx +23 -5
  169. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +1 -1
  170. package/corpus/templates/design/app/global.css +77 -49
  171. package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
  172. package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +131 -0
  173. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -2
  174. package/corpus/templates/design/app/i18n/zh-TW.ts +34 -0
  175. package/corpus/templates/design/app/i18n-data.ts +314 -3
  176. package/corpus/templates/design/app/pages/DesignEditor.tsx +4929 -892
  177. package/corpus/templates/design/app/root.tsx +1 -1
  178. package/corpus/templates/design/changelog/2026-06-29-added-a-review-panel-in-the-design-editor-s-inspector-with-a.md +6 -0
  179. package/corpus/templates/design/changelog/2026-06-29-containers-no-longer-block-selecting-nested-elements-and-nor.md +6 -0
  180. package/corpus/templates/design/changelog/2026-06-29-copying-and-pasting-layers-no-longer-shows-success-notificat.md +6 -0
  181. package/corpus/templates/design/changelog/2026-06-29-design-agents-now-generate-and-refine-variants-from-stronger.md +6 -0
  182. package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +6 -0
  183. package/corpus/templates/design/changelog/2026-06-29-design-questions-now-appear-as-a-cleaner-canvas-intake-with-.md +6 -0
  184. package/corpus/templates/design/changelog/2026-06-29-design-variant-directions-now-appear-as-board-screens-with-chat-buttons.md +5 -0
  185. package/corpus/templates/design/changelog/2026-06-29-device-presets-in-all-screens-view-resize-the-selected-previ.md +6 -0
  186. package/corpus/templates/design/changelog/2026-06-29-element-selection-no-longer-snaps-back-to-the-previous-layer.md +6 -0
  187. package/corpus/templates/design/changelog/2026-06-29-frame-resize-measurements-now-stay-beside-the-cursor-while-d.md +6 -0
  188. package/corpus/templates/design/changelog/2026-06-29-inspector-number-fields-have-cleaner-tooltips-and-draggable-.md +6 -0
  189. package/corpus/templates/design/changelog/2026-06-29-layer-and-canvas-drags-keep-the-layer-list-stable-while-chan.md +6 -0
  190. package/corpus/templates/design/changelog/2026-06-29-layer-locking-layer-nesting-generated-question-intake-and-im.md +6 -0
  191. package/corpus/templates/design/changelog/2026-06-29-layer-moves-can-be-undone-and-redone-without-flashing-the-ca.md +6 -0
  192. package/corpus/templates/design/changelog/2026-06-29-layer-names-in-the-sidebar-can-scroll-horizontally-instead-o.md +6 -0
  193. package/corpus/templates/design/changelog/2026-06-29-layer-nesting-in-the-sidebar-now-uses-tighter-spacing-so-nam.md +6 -0
  194. package/corpus/templates/design/changelog/2026-06-29-layers-no-longer-repeat-document-wrapper-rows-when-a-screen-.md +6 -0
  195. package/corpus/templates/design/changelog/2026-06-29-overview-previews-now-keep-element-hover-and-selection-tied-.md +6 -0
  196. package/corpus/templates/design/changelog/2026-06-29-pressing-escape-now-cancels-a-stuck-screen-drag-in-the-overv.md +6 -0
  197. package/corpus/templates/design/changelog/2026-06-29-screen-overview-is-easier-to-find-and-named-screens-open-dir.md +6 -0
  198. package/corpus/templates/design/changelog/2026-06-29-screen-overview-only-highlights-screens-when-the-frame-or-ti.md +6 -0
  199. package/corpus/templates/design/changelog/2026-06-29-screen-overview-previews-now-resize-to-match-the-selected-de.md +6 -0
  200. package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-now-uses-a-pointer-cursor-instead-.md +6 -0
  201. package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-outlines-now-stay-locked-to-the-se.md +6 -0
  202. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zoom-now-reports-real-screen-scale-separatel.md +6 -0
  203. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-feels-smoother-and-selection-outline.md +6 -0
  204. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-now-stays-on-the-overview-canvas-ins.md +6 -0
  205. package/corpus/templates/design/changelog/2026-06-29-screen-previews-use-a-single-blue-hover-border-in-all-screen.md +6 -0
  206. package/corpus/templates/design/changelog/2026-06-29-selected-containers-show-draggable-padding-and-gap-guides-on.md +6 -0
  207. package/corpus/templates/design/changelog/2026-06-29-selecting-a-nested-layer-from-all-screens-now-keeps-you-in-a.md +6 -0
  208. package/corpus/templates/design/changelog/2026-06-29-share-now-groups-link-sharing-exports-and-agent-handoff.md +6 -0
  209. package/corpus/templates/design/changelog/2026-06-29-the-design-editor-adds-a-studio-layer-with-tokens-respon.md +6 -0
  210. package/corpus/templates/design/changelog/2026-06-29-the-design-editor-loading-skeleton-now-uses-a-softer-charcoa.md +6 -0
  211. package/corpus/templates/design/changelog/2026-06-29-the-device-preview-menu-now-sits-next-to-the-preview-button-.md +6 -0
  212. package/corpus/templates/design/changelog/2026-06-29-the-inspector-stays-read-only-while-an-empty-design-is-still.md +6 -0
  213. package/corpus/templates/design/changelog/2026-06-29-the-missing-design-view-now-matches-the-rest-of-the-editor-c.md +6 -0
  214. package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-icon-and-tool-option-menus-better-match-the-edi.md +6 -0
  215. package/corpus/templates/design/changelog/2026-06-29-typography-controls-now-keep-the-font-name-visible-and-move-.md +6 -0
  216. package/corpus/templates/design/changelog/2026-06-30-accessibility-findings-now-offer-a-one-click-fix.md +6 -0
  217. package/corpus/templates/design/changelog/2026-06-30-component-instances-now-have-editable-props-in-the-inspe.md +6 -0
  218. package/corpus/templates/design/changelog/2026-06-30-inspect-code-now-shows-the-elements-opening-tag-at-a-gla.md +6 -0
  219. package/corpus/templates/design/changelog/2026-06-30-shader-fill-presets-can-now-be-applied-to-an-element.md +6 -0
  220. package/corpus/templates/design/changelog/2026-06-30-the-motion-timeline-can-now-add-a-track-to-any-element-a.md +6 -0
  221. package/corpus/templates/design/changelog/2026-06-30-visual-editor-selection-layer-paint-and-drawing-controls-are-more-reliable.md +6 -0
  222. package/corpus/templates/design/e2e/README.md +3 -3
  223. package/corpus/templates/design/e2e/global-setup.ts +11 -22
  224. package/corpus/templates/design/e2e/helpers.ts +128 -11
  225. package/corpus/templates/design/playwright.config.ts +9 -3
  226. package/corpus/templates/design/server/db/schema.ts +123 -0
  227. package/corpus/templates/design/server/lib/coding-handoff.ts +126 -2
  228. package/corpus/templates/design/server/plugins/core-routes.ts +1 -2
  229. package/corpus/templates/design/server/plugins/db.ts +90 -0
  230. package/corpus/templates/design/server/routes/api/design-handoff/[id].zip.get.ts +86 -0
  231. package/corpus/templates/design/shared/builder-app.ts +297 -0
  232. package/corpus/templates/design/shared/capability-resolver.ts +123 -0
  233. package/corpus/templates/design/shared/capture-sanitize.ts +70 -0
  234. package/corpus/templates/design/shared/code-layer.ts +1141 -93
  235. package/corpus/templates/design/shared/component-model.ts +239 -0
  236. package/corpus/templates/design/shared/design-review.ts +275 -0
  237. package/corpus/templates/design/shared/design-source-capabilities.ts +286 -0
  238. package/corpus/templates/design/shared/design-state.ts +112 -0
  239. package/corpus/templates/design/shared/design-surface-index.ts +258 -0
  240. package/corpus/templates/design/shared/generation-session.ts +41 -0
  241. package/corpus/templates/design/shared/motion-compiler.ts +278 -0
  242. package/corpus/templates/design/shared/motion-timeline.ts +193 -0
  243. package/corpus/templates/design/shared/responsive-classes.ts +452 -0
  244. package/corpus/templates/design/shared/shader-fill.ts +323 -0
  245. package/corpus/templates/design/shared/source-mode.ts +245 -0
  246. package/corpus/templates/dispatch/app/global.css +79 -35
  247. package/corpus/templates/dispatch/app/routes/integrations.tsx +8 -7
  248. package/corpus/templates/dispatch/changelog/2026-06-29-integration-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  249. package/corpus/templates/forms/app/components/layout/Layout.tsx +6 -2
  250. package/corpus/templates/forms/app/global.css +64 -35
  251. package/corpus/templates/forms/app/pages/FormsListPage.tsx +2 -2
  252. package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +3 -3
  253. package/corpus/templates/forms/changelog/2026-06-29-form-list-and-insight-layouts-adapt-when-the-agent-sidebar.md +6 -0
  254. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +3 -1
  255. package/corpus/templates/macros/app/global.css +25 -9
  256. package/corpus/templates/macros/changelog/2026-06-29-macro-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  257. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -2
  258. package/corpus/templates/mail/app/global.css +42 -36
  259. package/corpus/templates/mail/app/pages/InboxPage.tsx +1 -1
  260. package/corpus/templates/mail/changelog/2026-06-29-the-contact-panel-now-adapts-to-the-available-mail-pane-width.md +6 -0
  261. package/corpus/templates/plan/app/components/layout/Layout.tsx +3 -1
  262. package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +6 -2
  263. package/corpus/templates/plan/app/components/plan/DocumentArea.tsx +6 -7
  264. package/corpus/templates/plan/app/global.css +74 -42
  265. package/corpus/templates/plan/changelog/2026-06-29-plan-canvases-open-without-an-initial-pan-and-zoom-flicker.md +6 -0
  266. package/corpus/templates/plan/changelog/2026-06-29-plan-document-blocks-adapt-to-the-available-document-width.md +6 -0
  267. package/corpus/templates/plan/changelog/2026-06-29-plan-titles-and-summaries-can-be-edited-inline-without-focus.md +6 -0
  268. package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -1
  269. package/corpus/templates/slides/app/global.css +49 -33
  270. package/corpus/templates/slides/changelog/2026-06-29-slide-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  271. package/corpus/templates/videos/app/components/layout/Layout.tsx +3 -1
  272. package/corpus/templates/videos/app/global.css +35 -35
  273. package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  274. package/dist/cli/design-connect.d.ts.map +1 -1
  275. package/dist/cli/design-connect.js +28 -2
  276. package/dist/cli/design-connect.js.map +1 -1
  277. package/dist/cli/mcp.d.ts.map +1 -1
  278. package/dist/cli/mcp.js +10 -0
  279. package/dist/cli/mcp.js.map +1 -1
  280. package/dist/cli/skills.d.ts.map +1 -1
  281. package/dist/cli/skills.js +95 -33
  282. package/dist/cli/skills.js.map +1 -1
  283. package/dist/client/error-format.d.ts.map +1 -1
  284. package/dist/client/error-format.js +17 -0
  285. package/dist/client/error-format.js.map +1 -1
  286. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  287. package/dist/client/extensions/ExtensionViewer.js +3 -4
  288. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  289. package/dist/client/guided-questions.d.ts +4 -0
  290. package/dist/client/guided-questions.d.ts.map +1 -1
  291. package/dist/client/guided-questions.js +16 -7
  292. package/dist/client/guided-questions.js.map +1 -1
  293. package/dist/client/onboarding/OnboardingPanel.js +26 -1
  294. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  295. package/dist/client/resources/BuiltinCapabilityDetail.d.ts.map +1 -1
  296. package/dist/client/resources/BuiltinCapabilityDetail.js +1 -1
  297. package/dist/client/resources/BuiltinCapabilityDetail.js.map +1 -1
  298. package/dist/client/resources/use-builtin-capabilities.d.ts +1 -1
  299. package/dist/client/resources/use-builtin-capabilities.d.ts.map +1 -1
  300. package/dist/client/resources/use-builtin-capabilities.js +2 -1
  301. package/dist/client/resources/use-builtin-capabilities.js.map +1 -1
  302. package/dist/client/session-replay.d.ts.map +1 -1
  303. package/dist/client/session-replay.js +31 -0
  304. package/dist/client/session-replay.js.map +1 -1
  305. package/dist/client/sharing/ShareButton.d.ts +14 -0
  306. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  307. package/dist/client/sharing/ShareButton.js +36 -7
  308. package/dist/client/sharing/ShareButton.js.map +1 -1
  309. package/dist/coding-tools/index.js +1 -1
  310. package/dist/coding-tools/index.js.map +1 -1
  311. package/dist/mcp/index.d.ts +2 -0
  312. package/dist/mcp/index.d.ts.map +1 -1
  313. package/dist/mcp/index.js +1 -0
  314. package/dist/mcp/index.js.map +1 -1
  315. package/dist/mcp/screen-memory-stdio.d.ts +6 -0
  316. package/dist/mcp/screen-memory-stdio.d.ts.map +1 -0
  317. package/dist/mcp/screen-memory-stdio.js +213 -0
  318. package/dist/mcp/screen-memory-stdio.js.map +1 -0
  319. package/dist/mcp-client/builtin-capabilities.d.ts +1 -1
  320. package/dist/mcp-client/builtin-capabilities.d.ts.map +1 -1
  321. package/dist/mcp-client/builtin-capabilities.js +10 -0
  322. package/dist/mcp-client/builtin-capabilities.js.map +1 -1
  323. package/dist/mcp-client/index.d.ts +1 -0
  324. package/dist/mcp-client/index.d.ts.map +1 -1
  325. package/dist/mcp-client/index.js +1 -0
  326. package/dist/mcp-client/index.js.map +1 -1
  327. package/dist/mcp-client/screen-memory-local.d.ts +61 -0
  328. package/dist/mcp-client/screen-memory-local.d.ts.map +1 -0
  329. package/dist/mcp-client/screen-memory-local.js +336 -0
  330. package/dist/mcp-client/screen-memory-local.js.map +1 -0
  331. package/dist/observability/routes.d.ts +3 -3
  332. package/dist/onboarding/types.d.ts +7 -0
  333. package/dist/onboarding/types.d.ts.map +1 -1
  334. package/dist/onboarding/types.js.map +1 -1
  335. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  336. package/dist/server/agent-chat-plugin.js +26 -0
  337. package/dist/server/agent-chat-plugin.js.map +1 -1
  338. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  339. package/dist/server/agents-bundle.d.ts.map +1 -1
  340. package/dist/server/agents-bundle.js +22 -7
  341. package/dist/server/agents-bundle.js.map +1 -1
  342. package/dist/styles/agent-native.css +5 -0
  343. package/dist/templates/default/app/global.css +35 -35
  344. package/docs/content/locales/ar-SA/template-design.mdx +6 -0
  345. package/docs/content/locales/de-DE/template-design.mdx +8 -0
  346. package/docs/content/locales/es-ES/template-design.mdx +10 -2
  347. package/docs/content/locales/fr-FR/template-design.mdx +10 -2
  348. package/docs/content/locales/hi-IN/template-design.mdx +7 -0
  349. package/docs/content/locales/ja-JP/template-design.mdx +7 -0
  350. package/docs/content/locales/ko-KR/template-design.mdx +7 -0
  351. package/docs/content/locales/pt-BR/template-design.mdx +9 -2
  352. package/docs/content/locales/zh-CN/template-design.mdx +6 -0
  353. package/docs/content/locales/zh-TW/template-design.mdx +6 -0
  354. package/docs/content/template-design.mdx +9 -2
  355. package/package.json +1 -1
  356. package/src/templates/default/app/global.css +35 -35
  357. package/corpus/templates/design/app/components/design/VariantGrid.tsx +0 -189
  358. package/corpus/templates/design/app/components/design/VariantHandoffCard.tsx +0 -115
  359. package/corpus/templates/design/app/hooks/use-variant-flow.ts +0 -342
@@ -0,0 +1,275 @@
1
+ /**
2
+ * deploy-design-preview — trigger a preview deploy when the source supports it
3
+ * (§6.6 of DESIGN-STUDIO-PLAN.md).
4
+ *
5
+ * Behaviour:
6
+ * - **Capability gate (server-side):** re-checks `deployPreview` capability.
7
+ * When `unavailable` (inline/localhost), returns a `ctaRequired` response with a
8
+ * "Make it real" CTA — never fakes a deploy call.
9
+ * - **Builder gate:** if `resolveIsBuilderBranchingEnabled()` returns false,
10
+ * returns a `connectRequired` CTA.
11
+ * - **Branch requirement:** a branch must already exist on the design (created
12
+ * via `create-design-branch`). If no branch is found, returns a clear
13
+ * `branchRequired` message rather than silently failing.
14
+ * - **Deploy trigger:** calls `runBuilderAgent()` with a scoped "deploy preview"
15
+ * prompt asking the Builder cloud agent to build and publish a preview URL for
16
+ * the named branch. Builder returns `{ branchName, url, status }`.
17
+ * - **Persistence:** updates the matching branch entry in the design's `data`
18
+ * JSON blob with `previewUrl` and `deployStatus`.
19
+ *
20
+ * The preview URL is the Builder-hosted ephemeral preview (not a permanent
21
+ * production deploy — use the Builder Visual Editor's Publish flow for that).
22
+ *
23
+ * Per DESIGN-STUDIO-PLAN.md §5, `deploy` (production) is the separate step;
24
+ * `deployPreview` is the lighter "preview build" step exposed here.
25
+ */
26
+
27
+ import { defineAction } from "@agent-native/core";
28
+ import {
29
+ runBuilderAgent,
30
+ resolveBuilderBranchProjectId,
31
+ resolveIsBuilderBranchingEnabled,
32
+ } from "@agent-native/core/server";
33
+ import { getRequestUserEmail } from "@agent-native/core/server/request-context";
34
+ import { assertAccess, resolveAccess } from "@agent-native/core/sharing";
35
+ import { eq } from "drizzle-orm";
36
+ import { z } from "zod";
37
+
38
+ import { getDb, schema } from "../server/db/index.js";
39
+ import "../server/db/index.js"; // ensure registerShareableResource runs
40
+ import {
41
+ resolveSourceCapabilities,
42
+ resolveFusionCapabilities,
43
+ } from "../shared/capability-resolver.js";
44
+ import { hasCapability } from "../shared/design-source-capabilities.js";
45
+ import { normalizeDesignSourceType } from "../shared/source-mode.js";
46
+
47
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
48
+
49
+ function parseDesignData(raw: unknown): Record<string, unknown> {
50
+ if (typeof raw !== "string") return {};
51
+ try {
52
+ const parsed: unknown = JSON.parse(raw);
53
+ if (
54
+ parsed !== null &&
55
+ typeof parsed === "object" &&
56
+ !Array.isArray(parsed)
57
+ ) {
58
+ return parsed as Record<string, unknown>;
59
+ }
60
+ } catch {
61
+ // Stale JSON — return empty.
62
+ }
63
+ return {};
64
+ }
65
+
66
+ interface StoredBranchEntry {
67
+ branchName?: string;
68
+ projectId?: string;
69
+ url?: string;
70
+ status?: string;
71
+ purpose?: string | null;
72
+ preSnapshotVersionId?: string | null;
73
+ previewUrl?: string | null;
74
+ deployStatus?: string | null;
75
+ createdAt?: string;
76
+ [key: string]: unknown;
77
+ }
78
+
79
+ function parseBranches(
80
+ designData: Record<string, unknown>,
81
+ ): StoredBranchEntry[] {
82
+ const raw = designData["branches"];
83
+ if (!Array.isArray(raw)) return [];
84
+ return raw.filter(
85
+ (b): b is StoredBranchEntry =>
86
+ b !== null && typeof b === "object" && !Array.isArray(b),
87
+ );
88
+ }
89
+
90
+ /** Build a concise deploy-preview prompt for the Builder cloud agent. */
91
+ function buildDeployPrompt(
92
+ designTitle: string,
93
+ branchName: string,
94
+ projectId: string,
95
+ ): string {
96
+ return [
97
+ `Deploy a preview build for branch "${branchName}" of project "${projectId}".`,
98
+ `Design: "${designTitle}".`,
99
+ "Build the branch and publish a preview URL so the design can be reviewed",
100
+ "in a real browser before merging to production.",
101
+ ].join("\n");
102
+ }
103
+
104
+ // ─── Action ───────────────────────────────────────────────────────────────────
105
+
106
+ export default defineAction({
107
+ description:
108
+ "Trigger a preview deploy for a fusion-backed design branch. " +
109
+ "Requires the design's source to advertise the 'deployPreview' capability " +
110
+ "(fusion tier) AND Builder.io to be connected. " +
111
+ "For inline/localhost designs, returns ctaRequired=true with a Make-it-real " +
112
+ "CTA — never fakes a deploy call. " +
113
+ "A branch must already exist (created via create-design-branch). " +
114
+ "On success, persists previewUrl and deployStatus into the design's branch " +
115
+ "metadata and returns the preview URL. " +
116
+ "Note: this triggers a *preview* deploy, not a production publish. " +
117
+ "Use the Builder Visual Editor's Publish flow for production deploys.",
118
+ schema: z.object({
119
+ designId: z.string().describe("Design project ID to deploy a preview for"),
120
+ branchName: z
121
+ .string()
122
+ .optional()
123
+ .describe(
124
+ "Branch name to deploy. Defaults to the most recently created branch " +
125
+ "when omitted.",
126
+ ),
127
+ }),
128
+ run: async ({ designId, branchName }) => {
129
+ const db = getDb();
130
+
131
+ // ── Access check (editor level required for deploys) ────────────────────
132
+ await assertAccess("design", designId, "editor");
133
+ const access = await resolveAccess("design", designId);
134
+ if (!access) throw new Error("Design not found");
135
+
136
+ const resource = access.resource as {
137
+ title?: string;
138
+ data?: unknown;
139
+ };
140
+
141
+ // ── Source type + capability check ──────────────────────────────────────
142
+ const designData = parseDesignData(resource.data);
143
+ const sourceType =
144
+ normalizeDesignSourceType(designData["sourceType"]) ?? "inline";
145
+
146
+ // For fusion sources, resolve the Builder connection status first so that
147
+ // resolveFusionCapabilities returns the CONNECTED map (with deployPreview
148
+ // available) when Builder is actually wired up. For inline/localhost the
149
+ // generic resolver is sufficient — those sources never have deployPreview.
150
+ const builderEnabled =
151
+ sourceType === "fusion"
152
+ ? await resolveIsBuilderBranchingEnabled()
153
+ : false;
154
+ const caps =
155
+ sourceType === "fusion"
156
+ ? resolveFusionCapabilities(builderEnabled)
157
+ : resolveSourceCapabilities(sourceType);
158
+
159
+ if (!hasCapability(caps, "deployPreview")) {
160
+ // For a disconnected fusion source the connect-builder CTA applies.
161
+ const isFusion = sourceType === "fusion";
162
+ return {
163
+ designId,
164
+ sourceType,
165
+ ctaRequired: true,
166
+ ctaKind: isFusion
167
+ ? ("connect-builder" as const)
168
+ : ("make-it-real" as const),
169
+ ctaMessage: isFusion
170
+ ? "Builder is not yet connected. Connect Builder.io to trigger preview deploys."
171
+ : "Preview deploys require a Builder-hosted app. Use 'Make it real' to upgrade " +
172
+ "this inline design to a real-app source, then deploy previews.",
173
+ previewUrl: null,
174
+ deployStatus: null,
175
+ branch: null,
176
+ };
177
+ }
178
+
179
+ // At this point sourceType === "fusion" and builderEnabled === true,
180
+ // so no separate Builder gate is needed — the capability check above
181
+ // already required a connected Builder to set deployPreview=available.
182
+
183
+ // ── Resolve branch entry ─────────────────────────────────────────────────
184
+ const branches = parseBranches(designData);
185
+
186
+ let branch: StoredBranchEntry | null = null;
187
+ if (branchName) {
188
+ branch =
189
+ branches.find(
190
+ (b) => b.branchName?.toLowerCase() === branchName.toLowerCase(),
191
+ ) ?? null;
192
+ } else {
193
+ branch = branches.length > 0 ? branches[branches.length - 1]! : null;
194
+ }
195
+
196
+ if (!branch || !branch.branchName) {
197
+ return {
198
+ designId,
199
+ sourceType,
200
+ ctaRequired: false,
201
+ ctaKind: null,
202
+ ctaMessage: null,
203
+ note:
204
+ "No branch found for this design. Use create-design-branch to create " +
205
+ "a branch first, then trigger a preview deploy.",
206
+ previewUrl: null,
207
+ deployStatus: null,
208
+ branch: null,
209
+ };
210
+ }
211
+
212
+ // ── Trigger the preview deploy via the Builder cloud agent ───────────────
213
+ const projectId = await resolveBuilderBranchProjectId();
214
+ const userEmail = getRequestUserEmail();
215
+ if (!userEmail) throw new Error("No authenticated user");
216
+
217
+ const designTitle =
218
+ typeof resource.title === "string" && resource.title.trim()
219
+ ? resource.title.trim()
220
+ : "Design";
221
+
222
+ const builderResult = await runBuilderAgent({
223
+ prompt: buildDeployPrompt(designTitle, branch.branchName, projectId),
224
+ projectId,
225
+ branchName: branch.branchName,
226
+ userEmail,
227
+ });
228
+
229
+ // ── Persist preview URL + deploy status into the branch entry ────────────
230
+ 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,
246
+ });
247
+
248
+ await db
249
+ .update(schema.designs)
250
+ .set({ data: updatedData, updatedAt: now })
251
+ .where(eq(schema.designs.id, designId));
252
+
253
+ return {
254
+ designId,
255
+ sourceType,
256
+ ctaRequired: false,
257
+ ctaKind: null,
258
+ ctaMessage: null,
259
+ previewUrl: builderResult.url,
260
+ deployStatus: builderResult.status,
261
+ branch: {
262
+ branchName: branch.branchName,
263
+ projectId: builderResult.projectId,
264
+ url: branch.url ?? null,
265
+ previewUrl: builderResult.url,
266
+ deployStatus: builderResult.status,
267
+ lastDeployedAt: now,
268
+ },
269
+ note:
270
+ "Preview deploy triggered. The Builder cloud agent is building the branch. " +
271
+ "Visit the previewUrl once status is 'ready' to review the deployed design. " +
272
+ "For production deploys, use the Builder Visual Editor's Publish flow.",
273
+ };
274
+ },
275
+ });
@@ -11,6 +11,7 @@ import { z } from "zod";
11
11
  import { schema } from "../server/db/index.js";
12
12
  import {
13
13
  buildCodingHandoffPrompt,
14
+ buildHandoffZipUrl,
14
15
  buildRawHandoffUrl,
15
16
  normalizeHandoffFormat,
16
17
  } from "../server/lib/coding-handoff.js";
@@ -30,9 +31,9 @@ function designDeepLink(designId: string): string {
30
31
 
31
32
  export default defineAction({
32
33
  description:
33
- "Turn a design into code: create a coding-tool handoff for a design " +
34
- "project. Returns a tokenized raw-code URL external agents can fetch, " +
35
- "plus a ready-to-copy prompt. The bundle reflects the design's CURRENT " +
34
+ "Turn a design into code: create an agent handoff for a design project. " +
35
+ "Returns tokenized raw and ZIP URLs external agents can fetch, plus a " +
36
+ "ready-to-copy prompt. The bundle reflects the design's CURRENT " +
36
37
  "state — live editor (collab) content plus the user's applied visual " +
37
38
  "tweaks resolved into the HTML :root — so the generated code matches the " +
38
39
  "tuned design, not the original generated tokens. This is the canonical " +
@@ -56,7 +57,7 @@ export default defineAction({
56
57
  mcpApp: {
57
58
  compactCatalog: true,
58
59
  resource: embedApp({
59
- title: "Design coding handoff",
60
+ title: "Design agent handoff",
60
61
  description: "Open the design in the real Design editor.",
61
62
  iframeTitle: "Agent-Native Design",
62
63
  openLabel: "Open design",
@@ -97,8 +98,14 @@ export default defineAction({
97
98
  origin: resolvedOrigin,
98
99
  format: handoffFormat,
99
100
  });
101
+ const zipUrl = buildHandoffZipUrl({
102
+ id,
103
+ token,
104
+ origin: resolvedOrigin,
105
+ });
100
106
  const prompt = buildCodingHandoffPrompt({
101
107
  rawUrl,
108
+ zipUrl,
102
109
  title: design.title,
103
110
  fileCount: snapshot.files.length,
104
111
  });
@@ -106,6 +113,7 @@ export default defineAction({
106
113
  return {
107
114
  designId: id,
108
115
  rawUrl,
116
+ zipUrl,
109
117
  prompt,
110
118
  clipboardText: prompt,
111
119
  format: handoffFormat,
@@ -1,6 +1,5 @@
1
1
  import { defineAction, embedApp } from "@agent-native/core";
2
2
  import {
3
- deleteAppState,
4
3
  readAppState,
5
4
  writeAppState,
6
5
  } from "@agent-native/core/application-state";
@@ -26,6 +25,7 @@ import {
26
25
  import {
27
26
  designGenerationSessionKey,
28
27
  type DesignGenerationSession,
28
+ updateGenerationSessionWithSavedFiles,
29
29
  } from "../shared/generation-session.js";
30
30
 
31
31
  /** Editor deep link so external agents can surface "Open design". */
@@ -57,28 +57,13 @@ async function updateGenerationSessionForSavedFiles(
57
57
  const session = rawSession as unknown as DesignGenerationSession;
58
58
  if (session.designId !== designId || !Array.isArray(session.frames)) return;
59
59
 
60
- const saved = new Set(savedFilenames);
61
- const frames = session.frames.map((frame) =>
62
- frame.filename && saved.has(frame.filename)
63
- ? {
64
- ...frame,
65
- status: "done" as const,
66
- step: "Saved",
67
- progress: 1,
68
- }
69
- : frame,
60
+ const nextSession = updateGenerationSessionWithSavedFiles(
61
+ session,
62
+ savedFilenames,
70
63
  );
71
- const allDone = frames.every((frame) => frame.status === "done");
72
- if (allDone) {
73
- await deleteAppState(key);
74
- return;
75
- }
64
+ if (nextSession === session) return;
76
65
 
77
- await writeAppState(key, {
78
- ...session,
79
- status: "generating",
80
- frames,
81
- } as unknown as Record<string, unknown>);
66
+ await writeAppState(key, nextSession as unknown as Record<string, unknown>);
82
67
  }
83
68
 
84
69
  export default defineAction({
@@ -51,7 +51,7 @@ const requestedScreenSchema = z
51
51
  .optional()
52
52
  .describe("Target filename for this screen, such as onboarding.html"),
53
53
  role: z.enum(["screen", "variant"]).optional().default("screen"),
54
- variantOf: z.string().optional(),
54
+ variantOf: z.string().trim().min(1).optional(),
55
55
  })
56
56
  .superRefine((screen, ctx) => {
57
57
  if (screen.role === "variant" && !screen.variantOf) {
@@ -80,7 +80,48 @@ export default defineAction({
80
80
  screens: z
81
81
  .preprocess(
82
82
  (value) => (typeof value === "string" ? JSON.parse(value) : value),
83
- z.array(requestedScreenSchema).min(1).max(8),
83
+ z
84
+ .array(requestedScreenSchema)
85
+ .min(1)
86
+ .max(8)
87
+ .superRefine((screens, ctx) => {
88
+ const requestAnchors = new Map<
89
+ string,
90
+ { index: number; role: DesignGenerationFrame["role"] }
91
+ >();
92
+ screens.forEach((screen, index) => {
93
+ const anchors = [screen.frameId, screen.filename, screen.title];
94
+ for (const anchor of anchors) {
95
+ if (!anchor || requestAnchors.has(anchor)) continue;
96
+ requestAnchors.set(anchor, {
97
+ index,
98
+ role: screen.role,
99
+ });
100
+ }
101
+ });
102
+
103
+ screens.forEach((screen, index) => {
104
+ if (screen.role !== "variant" || !screen.variantOf) return;
105
+ const anchor = requestAnchors.get(screen.variantOf);
106
+ if (!anchor) return;
107
+ if (anchor.index === index) {
108
+ ctx.addIssue({
109
+ code: z.ZodIssueCode.custom,
110
+ path: [index, "variantOf"],
111
+ message: "variant screens cannot point to themselves",
112
+ });
113
+ return;
114
+ }
115
+ if (anchor.role === "variant") {
116
+ ctx.addIssue({
117
+ code: z.ZodIssueCode.custom,
118
+ path: [index, "variantOf"],
119
+ message:
120
+ "variant screens must anchor to a base screen, not another variant",
121
+ });
122
+ }
123
+ });
124
+ }),
84
125
  )
85
126
  .describe("Screens or variants that should be generated on the canvas"),
86
127
  designSystemId: z
@@ -0,0 +1,242 @@
1
+ /**
2
+ * get-component-details — read action.
3
+ *
4
+ * For a selected component instance, returns the component name, source file
5
+ * (via resolveNodeToFile when the capability is available), props / variants,
6
+ * and the persistent component_index row when one exists.
7
+ *
8
+ * Works across both tiers:
9
+ * - **Alpine / inline** — returns name + observed props from attributes, plus
10
+ * a CTA flag for features that require a real-app source.
11
+ * - **Real app (localhost / fusion)** — returns the full component_index row
12
+ * including parsed TS prop types, cva variants, Storybook stories, and the
13
+ * source file path. The `resolveNodeToFile` capability unlocks the source
14
+ * deep-link returned in `sourceLocation`.
15
+ */
16
+
17
+ import { defineAction } from "@agent-native/core";
18
+ import { getText, hasCollabState } from "@agent-native/core/collab";
19
+ import { accessFilter, resolveAccess } from "@agent-native/core/sharing";
20
+ import { and, eq } from "drizzle-orm";
21
+ import { z } from "zod";
22
+
23
+ import { getDb, schema } from "../server/db/index.js";
24
+ import "../server/db/index.js"; // ensure registerShareableResource runs
25
+ import { resolveSourceCapabilities } from "../shared/capability-resolver.js";
26
+ import { buildCodeLayerProjection } from "../shared/code-layer.js";
27
+ import type { CodeLayerSource } from "../shared/code-layer.js";
28
+ import {
29
+ componentNameFor,
30
+ extractProps,
31
+ type ComponentInstance,
32
+ } from "../shared/component-model.js";
33
+ import { hasCapability } from "../shared/design-source-capabilities.js";
34
+ import { normalizeDesignSourceType } from "../shared/source-mode.js";
35
+
36
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
37
+
38
+ async function liveContent(
39
+ fileId: string,
40
+ storedContent: string,
41
+ ): Promise<string> {
42
+ try {
43
+ if (await hasCollabState(fileId)) {
44
+ const live = await getText(fileId, "content");
45
+ if (typeof live === "string") return live;
46
+ }
47
+ } catch {
48
+ // Collab reads are best-effort; SQL content is the fallback.
49
+ }
50
+ return storedContent;
51
+ }
52
+
53
+ function parseJson<T>(raw: string | null | undefined, fallback: T): T {
54
+ if (!raw) return fallback;
55
+ try {
56
+ return JSON.parse(raw) as T;
57
+ } catch {
58
+ return fallback;
59
+ }
60
+ }
61
+
62
+ // ─── Action ───────────────────────────────────────────────────────────────────
63
+
64
+ export default defineAction({
65
+ description:
66
+ "Return details for a selected component instance: component name, " +
67
+ "source file (when resolveNodeToFile capability is available), props, " +
68
+ "variants, and the persisted component_index row. " +
69
+ "Provide the design id and node id (data-agent-native-node-id) of the " +
70
+ "selected component root. For Alpine designs the response includes " +
71
+ "lightweight attribute-based props and a CTA flag for full prop controls.",
72
+ schema: z.object({
73
+ designId: z.string().describe("Design project ID"),
74
+ nodeId: z
75
+ .string()
76
+ .describe(
77
+ "The data-agent-native-node-id of the selected component instance root element.",
78
+ ),
79
+ fileId: z
80
+ .string()
81
+ .optional()
82
+ .describe("Design file id. Defaults to index.html."),
83
+ }),
84
+ readOnly: true,
85
+ http: { method: "GET" },
86
+ run: async ({ designId, nodeId, fileId }) => {
87
+ const db = getDb();
88
+
89
+ // ── Access check ────────────────────────────────────────────────────────
90
+ const access = await resolveAccess("design", designId);
91
+ if (!access) throw new Error("Design not found");
92
+
93
+ // ── Source type + capabilities ───────────────────────────────────────────
94
+ let rawSourceType: unknown = "inline";
95
+ const rawData = (access.resource as { data?: unknown }).data;
96
+ if (typeof rawData === "string") {
97
+ try {
98
+ const parsed: unknown = JSON.parse(rawData);
99
+ if (
100
+ parsed !== null &&
101
+ typeof parsed === "object" &&
102
+ "sourceType" in (parsed as object)
103
+ ) {
104
+ rawSourceType = (parsed as { sourceType: unknown }).sourceType;
105
+ }
106
+ } catch {
107
+ // Default to inline.
108
+ }
109
+ }
110
+
111
+ const sourceType = normalizeDesignSourceType(rawSourceType) ?? "inline";
112
+ const caps = resolveSourceCapabilities(sourceType);
113
+ const canResolveToFile = hasCapability(caps, "resolveNodeToFile");
114
+ const hasFullIndex = hasCapability(caps, "indexComponents");
115
+
116
+ // ── Fetch design file ────────────────────────────────────────────────────
117
+ const conditions = [
118
+ accessFilter(schema.designs, schema.designShares),
119
+ eq(schema.designFiles.designId, designId),
120
+ fileId
121
+ ? eq(schema.designFiles.id, fileId)
122
+ : eq(schema.designFiles.filename, "index.html"),
123
+ ];
124
+
125
+ const [file] = await db
126
+ .select({
127
+ id: schema.designFiles.id,
128
+ designId: schema.designFiles.designId,
129
+ filename: schema.designFiles.filename,
130
+ content: schema.designFiles.content,
131
+ })
132
+ .from(schema.designFiles)
133
+ .innerJoin(
134
+ schema.designs,
135
+ eq(schema.designFiles.designId, schema.designs.id),
136
+ )
137
+ .where(and(...conditions))
138
+ .limit(1);
139
+
140
+ if (!file) throw new Error("Design HTML file not found.");
141
+
142
+ const html = await liveContent(file.id, file.content ?? "");
143
+
144
+ // ── Projection lookup ────────────────────────────────────────────────────
145
+ const codeLayerSource: CodeLayerSource = {
146
+ kind: "design-file",
147
+ designId: file.designId,
148
+ fileId: file.id,
149
+ filename: file.filename,
150
+ };
151
+
152
+ const projection = buildCodeLayerProjection(html, {
153
+ source: codeLayerSource,
154
+ });
155
+
156
+ const node = projection.nodes.find((n) => n.id === nodeId);
157
+ if (!node) {
158
+ throw new Error(
159
+ `Node "${nodeId}" not found in projection. Run get-code-layer-projection to list current node ids.`,
160
+ );
161
+ }
162
+
163
+ const name = componentNameFor(node);
164
+ if (!name) {
165
+ throw new Error(
166
+ `Node "${nodeId}" does not carry a data-agent-native-component attribute and is not a component root.`,
167
+ );
168
+ }
169
+
170
+ // ── Simple props from attributes ─────────────────────────────────────────
171
+ const observedProps = extractProps(node);
172
+ const alpineData =
173
+ typeof node.attributes["x-data"] === "string"
174
+ ? node.attributes["x-data"]
175
+ : undefined;
176
+
177
+ const instance: ComponentInstance = {
178
+ instanceId: node.id,
179
+ name,
180
+ props: observedProps,
181
+ alpineData,
182
+ selector: node.selector,
183
+ nodeId: node.id,
184
+ };
185
+
186
+ // ── Lookup persisted component_index row ─────────────────────────────────
187
+ const [indexRow] = await db
188
+ .select()
189
+ .from(schema.componentIndex)
190
+ .where(
191
+ and(
192
+ eq(schema.componentIndex.designId, designId),
193
+ eq(schema.componentIndex.name, name),
194
+ ),
195
+ )
196
+ .limit(1);
197
+
198
+ const persistedProps = parseJson<unknown[]>(indexRow?.props, []);
199
+ const persistedVariants = parseJson<Record<string, string[]>>(
200
+ indexRow?.variants,
201
+ {},
202
+ );
203
+ const persistedStories = parseJson<unknown[]>(indexRow?.stories, []);
204
+
205
+ // ── Source location (real-app only) ──────────────────────────────────────
206
+ // The bridge `resolveNodeToFile` op maps a node id to a source file + span.
207
+ // For inline designs the capability is `available` but resolves to the
208
+ // design file itself (no external source file). We surface whatever we
209
+ // have from the index row.
210
+ const sourceLocation =
211
+ canResolveToFile && indexRow?.filePath
212
+ ? {
213
+ filePath: indexRow.filePath,
214
+ exportName: indexRow.exportName ?? undefined,
215
+ }
216
+ : undefined;
217
+
218
+ return {
219
+ designId,
220
+ nodeId,
221
+ sourceType,
222
+ instance,
223
+ name,
224
+ // Props: merge observed attribute props with richer persisted prop types
225
+ // when available. Real-app callers get the full TS/cva prop table.
226
+ observedProps,
227
+ persistedProps,
228
+ persistedVariants,
229
+ persistedStories,
230
+ sourceLocation,
231
+ capabilities: {
232
+ canResolveToFile,
233
+ hasFullIndex,
234
+ canEditProps: true, // preview-only on inline; persists on real-app
235
+ ctaRequired: !hasFullIndex,
236
+ ctaMessage: !hasFullIndex
237
+ ? "Full prop controls (TypeScript prop types, cva variants, Storybook stories) require a connected Builder app. Connect Builder to unlock."
238
+ : undefined,
239
+ },
240
+ };
241
+ },
242
+ });