@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
@@ -1,21 +1,32 @@
1
+ // i18n-raw-literal-disable-file — new Design Studio panel; UI strings are localized when this feature is finalized in the follow-up PR.
1
2
  import {
2
3
  PromptComposer,
3
4
  agentNativePath,
4
5
  sendToAgentChat,
6
+ useActionMutation,
5
7
  useChangeVersions,
6
8
  useT,
7
9
  type PromptComposerProps,
8
10
  type PromptComposerSubmitOptions,
9
11
  } from "@agent-native/core/client";
10
12
  import { EmbeddedExtension } from "@agent-native/core/client/extensions";
13
+ import {
14
+ EmbeddedApp,
15
+ type EmbeddedAppRef,
16
+ } from "@agent-native/core/embedding/react";
17
+ import type { ShaderDescriptor } from "@shared/shader-presets";
11
18
  import {
12
19
  IconExternalLink,
20
+ IconLock,
21
+ IconPalette,
22
+ IconPhoto,
23
+ IconPlayerPlay,
13
24
  IconPlus,
14
25
  IconPuzzle,
15
26
  IconSparkles,
16
27
  } from "@tabler/icons-react";
17
28
  import { useQuery, useQueryClient } from "@tanstack/react-query";
18
- import { useMemo, useState } from "react";
29
+ import { useCallback, useEffect, useMemo, useState } from "react";
19
30
  import { toast } from "sonner";
20
31
 
21
32
  import { Button } from "@/components/ui/button";
@@ -32,10 +43,13 @@ import {
32
43
  } from "@/components/ui/tooltip";
33
44
  import { cn } from "@/lib/utils";
34
45
 
46
+ import { ShaderFillsPanel } from "./inspector/ShaderFillsPanel";
35
47
  import type { ElementInfo } from "./types";
36
48
 
37
49
  export const DESIGN_EDITOR_EXTENSION_SLOT_ID = "design.editor.inspector";
38
50
 
51
+ // ─── Types ──────────────────────────────────────────────────────────────────
52
+
39
53
  interface SlotInstall {
40
54
  installId: string;
41
55
  extensionId: string;
@@ -81,6 +95,55 @@ interface DesignExtensionsPanelProps {
81
95
 
82
96
  type PromptComposerSubmitHandler = PromptComposerProps["onSubmit"];
83
97
 
98
+ // ─── First-party extension ids ───────────────────────────────────────────────
99
+
100
+ type FirstPartyExtId =
101
+ | "design.asset-library"
102
+ | "design.shader-fills"
103
+ | "design.token-auditor"
104
+ | "design.motion-presets";
105
+
106
+ // ─── Assets picker types (mirrors PromptDialog) ───────────────────────────
107
+
108
+ const DEFAULT_ASSETS_PICKER_URL = "https://assets.agent-native.com/picker";
109
+
110
+ interface PickedAssetPayload {
111
+ url?: unknown;
112
+ previewUrl?: unknown;
113
+ downloadUrl?: unknown;
114
+ embedUrl?: unknown;
115
+ altText?: unknown;
116
+ title?: unknown;
117
+ assetId?: unknown;
118
+ mimeType?: unknown;
119
+ }
120
+
121
+ function assetsPickerUrl(): string {
122
+ return (
123
+ (typeof import.meta !== "undefined" &&
124
+ (import.meta as { env?: Record<string, string> }).env
125
+ ?.VITE_AGENT_NATIVE_ASSETS_PICKER_URL) ||
126
+ DEFAULT_ASSETS_PICKER_URL
127
+ );
128
+ }
129
+
130
+ function pickedAssetString(value: unknown): string | null {
131
+ return typeof value === "string" && value.trim() ? value.trim() : null;
132
+ }
133
+
134
+ function pickedAssetImageSource(payload: unknown): string | null {
135
+ if (!payload || typeof payload !== "object") return null;
136
+ const p = payload as PickedAssetPayload;
137
+ return (
138
+ pickedAssetString(p.url) ??
139
+ pickedAssetString(p.previewUrl) ??
140
+ pickedAssetString(p.downloadUrl) ??
141
+ pickedAssetString(p.embedUrl)
142
+ );
143
+ }
144
+
145
+ // ─── Build extension create context ──────────────────────────────────────────
146
+
84
147
  function buildExtensionCreateContext(
85
148
  prompt: string,
86
149
  context: DesignExtensionSlotContext,
@@ -131,6 +194,8 @@ function buildExtensionCreateContext(
131
194
  ].join("\n");
132
195
  }
133
196
 
197
+ // ─── Hooks ───────────────────────────────────────────────────────────────────
198
+
134
199
  function useSlotInstalls(slotId: string) {
135
200
  const versions = useChangeVersions(["action"]);
136
201
  return useQuery<SlotInstall[]>({
@@ -165,6 +230,464 @@ function useAvailableExtensions(slotId: string) {
165
230
  });
166
231
  }
167
232
 
233
+ // ─── First-party extension rows ───────────────────────────────────────────────
234
+
235
+ interface FirstPartyRowProps {
236
+ id: FirstPartyExtId;
237
+ label: string;
238
+ description: string;
239
+ icon: React.ReactNode;
240
+ badge?: React.ReactNode;
241
+ isOpen: boolean;
242
+ onToggle: () => void;
243
+ children: React.ReactNode;
244
+ }
245
+
246
+ function FirstPartyExtRow({
247
+ label,
248
+ description,
249
+ icon,
250
+ badge,
251
+ isOpen,
252
+ onToggle,
253
+ children,
254
+ }: FirstPartyRowProps) {
255
+ return (
256
+ <div className="overflow-hidden rounded border border-border bg-background">
257
+ <button
258
+ type="button"
259
+ onClick={onToggle}
260
+ className="flex w-full cursor-pointer items-center gap-2 px-2.5 py-2 text-left transition-colors hover:bg-accent/50 active:bg-accent"
261
+ >
262
+ <span className="flex size-6 shrink-0 items-center justify-center rounded bg-muted text-muted-foreground">
263
+ {icon}
264
+ </span>
265
+ <span className="min-w-0 flex-1">
266
+ <span className="block truncate text-[11px] font-medium text-foreground">
267
+ {label}
268
+ </span>
269
+ <span className="block truncate text-[10px] leading-tight text-muted-foreground">
270
+ {description}
271
+ </span>
272
+ </span>
273
+ {badge}
274
+ </button>
275
+ {isOpen && <div className="border-t border-border/60">{children}</div>}
276
+ </div>
277
+ );
278
+ }
279
+
280
+ // ─── Asset Library panel ──────────────────────────────────────────────────────
281
+
282
+ interface AssetLibraryPanelProps {
283
+ context: DesignExtensionSlotContext;
284
+ }
285
+
286
+ function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
287
+ const t = useT();
288
+ const [pickerOpen, setPickerOpen] = useState(false);
289
+ const [pickerReady, setPickerReady] = useState(false);
290
+ const insertAsset = useActionMutation("insert-asset");
291
+
292
+ useEffect(() => {
293
+ if (pickerOpen) setPickerReady(false);
294
+ }, [pickerOpen]);
295
+
296
+ const handleReady = useCallback(
297
+ (_payload: unknown, _event: MessageEvent, ref: EmbeddedAppRef) => {
298
+ setPickerReady(true);
299
+ ref.postMessage("configure", {});
300
+ },
301
+ [],
302
+ );
303
+
304
+ const handleMessage = useCallback(
305
+ (name: string, payload: unknown) => {
306
+ if (name === "close") {
307
+ setPickerOpen(false);
308
+ return;
309
+ }
310
+ if (name !== "chooseImage" && name !== "chooseAsset") return;
311
+
312
+ const url = pickedAssetImageSource(payload);
313
+ if (!url) {
314
+ toast.error("No image URL returned from Assets picker.");
315
+ return;
316
+ }
317
+
318
+ const p = payload as PickedAssetPayload;
319
+ const title = pickedAssetString(p.title) ?? undefined;
320
+ const altText = pickedAssetString(p.altText) ?? undefined;
321
+ const assetId = pickedAssetString(p.assetId) ?? undefined;
322
+ const mimeType = pickedAssetString(p.mimeType) ?? "";
323
+ const mediaType = mimeType.startsWith("video/") ? "video" : "image";
324
+
325
+ insertAsset.mutate(
326
+ {
327
+ assetUrl: url,
328
+ assetId,
329
+ title,
330
+ altText,
331
+ mediaType: mediaType as "image" | "video",
332
+ designId: context.designId || undefined,
333
+ fileId: context.activeFileId || undefined,
334
+ },
335
+ {
336
+ onSuccess: () => {
337
+ toast.success("Asset inserted into design.");
338
+ },
339
+ onError: () => {
340
+ toast.error("Failed to insert asset.");
341
+ },
342
+ },
343
+ );
344
+
345
+ setPickerOpen(false);
346
+ },
347
+ [context.designId, context.activeFileId, insertAsset],
348
+ );
349
+
350
+ const handleAskAgent = () => {
351
+ sendToAgentChat({
352
+ message:
353
+ "Open the Assets picker so I can choose an image to insert into the design.",
354
+ context: [
355
+ `Design id: ${context.designId}`,
356
+ context.activeFileId ? `Active file id: ${context.activeFileId}` : null,
357
+ context.selectedElement?.selector
358
+ ? `Selected element selector: ${context.selectedElement.selector}`
359
+ : null,
360
+ "Call insert-asset with the chosen URL after the user picks from the Assets picker.",
361
+ ]
362
+ .filter(Boolean)
363
+ .join("\n"),
364
+ submit: true,
365
+ openSidebar: true,
366
+ });
367
+ };
368
+
369
+ return (
370
+ <div className="p-2.5">
371
+ <p className="mb-2 text-[10px] leading-snug text-muted-foreground">
372
+ Browse and insert generated or uploaded images into the active design
373
+ screen. Inserts near the selected element when one is active.
374
+ </p>
375
+ <div className="flex flex-wrap gap-1.5">
376
+ <Button
377
+ type="button"
378
+ size="sm"
379
+ className="h-6 cursor-pointer gap-1 px-2 text-[11px]"
380
+ disabled={insertAsset.isPending || !context.activeFileId}
381
+ onClick={() => setPickerOpen(true)}
382
+ >
383
+ <IconPhoto className="size-3" />
384
+ {insertAsset.isPending ? "Inserting…" : "Browse Assets"}
385
+ </Button>
386
+ <Button
387
+ type="button"
388
+ variant="outline"
389
+ size="sm"
390
+ className="h-6 cursor-pointer gap-1 px-2 text-[11px]"
391
+ onClick={handleAskAgent}
392
+ >
393
+ <IconSparkles className="size-3" />
394
+ {t("designEditor.askAgent") || "Ask agent"}
395
+ </Button>
396
+ </div>
397
+ {!context.activeFileId && (
398
+ <p className="mt-1.5 text-[10px] text-amber-600 dark:text-amber-400">
399
+ Open a design screen first to insert assets.
400
+ </p>
401
+ )}
402
+
403
+ {/* Assets picker overlay */}
404
+ {pickerOpen && (
405
+ <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
406
+ <div
407
+ data-assets-picker-overlay
408
+ className="relative flex h-[min(86vh,760px)] w-[min(96vw,1040px)] flex-col overflow-hidden rounded-xl border border-border bg-popover shadow-2xl"
409
+ >
410
+ <div className="flex h-10 shrink-0 items-center border-b border-border px-4">
411
+ <span className="flex-1 text-sm font-medium">Assets Library</span>
412
+ <button
413
+ type="button"
414
+ aria-label="Close picker"
415
+ onClick={() => setPickerOpen(false)}
416
+ className="flex size-7 cursor-pointer items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground"
417
+ >
418
+ ×
419
+ </button>
420
+ </div>
421
+ <div className="relative min-h-0 flex-1">
422
+ {!pickerReady && (
423
+ <div className="absolute inset-0 flex items-center justify-center">
424
+ <Skeleton className="h-full w-full rounded-none" />
425
+ </div>
426
+ )}
427
+ <EmbeddedApp
428
+ url={assetsPickerUrl()}
429
+ title="Assets picker"
430
+ onReady={handleReady}
431
+ onMessage={handleMessage}
432
+ className="h-full w-full"
433
+ />
434
+ </div>
435
+ </div>
436
+ </div>
437
+ )}
438
+ </div>
439
+ );
440
+ }
441
+
442
+ // ─── Shader Fills panel ───────────────────────────────────────────────────────
443
+
444
+ interface ShaderFillsExtPanelProps {
445
+ context: DesignExtensionSlotContext;
446
+ }
447
+
448
+ function ShaderFillsExtPanel({ context }: ShaderFillsExtPanelProps) {
449
+ const [showShaders, setShowShaders] = useState(false);
450
+ // The most recently previewed descriptor — Apply persists exactly this one,
451
+ // so the write is intentional (one atomic call) rather than firing on every
452
+ // slider tweak.
453
+ const [previewed, setPreviewed] = useState<ShaderDescriptor | null>(null);
454
+ const applyShaderFill = useActionMutation("apply-shader-fill");
455
+
456
+ // The persisting apply path needs an HTML file plus a target element. Without
457
+ // a selected element we can still preview, but we cannot write a fill.
458
+ const targetNodeId = context.selectedElement?.sourceId ?? undefined;
459
+ const targetSelector = context.selectedElement?.selector ?? undefined;
460
+ const canPersist = Boolean(
461
+ context.activeFileId && (targetNodeId || targetSelector),
462
+ );
463
+
464
+ const persistFill = (descriptor: ShaderDescriptor) => {
465
+ if (!canPersist) return;
466
+ applyShaderFill.mutate(
467
+ {
468
+ descriptor: {
469
+ preset: descriptor.preset,
470
+ params: descriptor.params,
471
+ colors: descriptor.colors,
472
+ speed: descriptor.speed,
473
+ frame: descriptor.frame,
474
+ fit: descriptor.fit,
475
+ scale: descriptor.scale,
476
+ rotation: descriptor.rotation,
477
+ offsetX: descriptor.offsetX,
478
+ offsetY: descriptor.offsetY,
479
+ },
480
+ target: { nodeId: targetNodeId, selector: targetSelector },
481
+ source: {
482
+ kind: "design-file" as const,
483
+ designId: context.designId || undefined,
484
+ fileId: context.activeFileId || undefined,
485
+ },
486
+ },
487
+ {
488
+ onSuccess: (res) => {
489
+ const r = res as { persisted?: boolean } | undefined;
490
+ if (r?.persisted) {
491
+ toast.success("Shader fill applied to the selected element.");
492
+ } else {
493
+ toast.message("Shader fill previewed — nothing was written.");
494
+ }
495
+ },
496
+ onError: () => {
497
+ toast.error("Failed to apply shader fill.");
498
+ },
499
+ },
500
+ );
501
+ };
502
+
503
+ if (!showShaders) {
504
+ return (
505
+ <div className="p-2.5">
506
+ <p className="mb-2 text-[10px] leading-snug text-muted-foreground">
507
+ GPU shader fill presets — MeshGradient, GrainGradient, Voronoi,
508
+ Metaballs, Warp, GodRays, Dithering, PaperTexture. Preview as a CSS
509
+ gradient, then apply it to the selected element as a CSS background.
510
+ </p>
511
+ {!canPersist && (
512
+ <div className="mb-2 flex items-start gap-1.5 rounded-md border border-amber-500/30 bg-amber-500/5 px-2 py-1.5">
513
+ <IconLock className="mt-0.5 size-3 shrink-0 text-amber-600 dark:text-amber-400" />
514
+ <p className="text-[10px] leading-snug text-amber-700 dark:text-amber-300">
515
+ Select an element on the canvas to apply a fill. Without a
516
+ selection you can still browse and preview presets.
517
+ </p>
518
+ </div>
519
+ )}
520
+ <div className="flex flex-wrap gap-1.5">
521
+ <Button
522
+ type="button"
523
+ size="sm"
524
+ className="h-6 cursor-pointer gap-1 px-2 text-[11px]"
525
+ onClick={() => setShowShaders(true)}
526
+ >
527
+ <IconSparkles className="size-3" />
528
+ Browse Shaders
529
+ </Button>
530
+ </div>
531
+ </div>
532
+ );
533
+ }
534
+
535
+ return (
536
+ <div className="flex flex-col">
537
+ <ShaderFillsPanel
538
+ onApply={(descriptor, _css) => {
539
+ // Preview only: ShaderFillsPanel fires apply-shader (planning/codegen)
540
+ // for agent context on every tune and the iframe shows the gradient.
541
+ // We just record the latest descriptor here; the explicit Apply
542
+ // button below performs the single intentional persist write.
543
+ setPreviewed(descriptor);
544
+ }}
545
+ onBack={() => setShowShaders(false)}
546
+ applyContext={{
547
+ designId: context.designId || undefined,
548
+ fileId: context.activeFileId || undefined,
549
+ nodeId: targetNodeId,
550
+ selector: targetSelector,
551
+ }}
552
+ />
553
+
554
+ {/* ── Apply bar: persists the previewed fill onto the selected element ── */}
555
+ <div className="flex items-center gap-2 border-t border-border/60 px-3 py-2">
556
+ {canPersist ? (
557
+ <Button
558
+ type="button"
559
+ size="sm"
560
+ className="h-6 cursor-pointer gap-1 px-2 text-[11px]"
561
+ disabled={!previewed || applyShaderFill.isPending}
562
+ onClick={() => {
563
+ if (previewed) persistFill(previewed);
564
+ }}
565
+ >
566
+ <IconSparkles className="size-3" />
567
+ {applyShaderFill.isPending
568
+ ? "Applying…"
569
+ : previewed
570
+ ? "Apply fill"
571
+ : "Pick a preset"}
572
+ </Button>
573
+ ) : (
574
+ <p className="flex items-start gap-1.5 text-[10px] leading-snug text-amber-700 dark:text-amber-300">
575
+ <IconLock className="mt-0.5 size-3 shrink-0 text-amber-600 dark:text-amber-400" />
576
+ Select an element on the canvas to apply this fill.
577
+ </p>
578
+ )}
579
+ </div>
580
+ </div>
581
+ );
582
+ }
583
+
584
+ // ─── Token Auditor panel ─────────────────────────────────────────────────────
585
+
586
+ interface TokenAuditorPanelProps {
587
+ context: DesignExtensionSlotContext;
588
+ }
589
+
590
+ function TokenAuditorPanel({ context }: TokenAuditorPanelProps) {
591
+ const t = useT();
592
+
593
+ const handleAskAgent = () => {
594
+ sendToAgentChat({
595
+ message:
596
+ "Run a token audit on the active design: index CSS custom properties, surface any hard-coded colours that should be tokens, flag clashes, and suggest fixes.",
597
+ context: [
598
+ `Design id: ${context.designId}`,
599
+ context.activeFileId ? `Active file id: ${context.activeFileId}` : null,
600
+ "Call index-design-tokens to parse CSS vars, then preview-design-token-edit for suggested changes.",
601
+ ]
602
+ .filter(Boolean)
603
+ .join("\n"),
604
+ submit: true,
605
+ openSidebar: true,
606
+ });
607
+ };
608
+
609
+ return (
610
+ <div className="p-2.5">
611
+ <p className="mb-2 text-[10px] leading-snug text-muted-foreground">
612
+ Index CSS custom property usage across the active design, surface
613
+ hard-coded colours that should be tokens, and flag clashes.
614
+ </p>
615
+ <div className="mb-1.5 text-[10px] text-muted-foreground">
616
+ Token reads and tweaks are available for all source types. Source
617
+ write-back (globals.css / tailwind.config) is gated on bridge hardening.
618
+ </div>
619
+ <div className="flex flex-wrap gap-1.5">
620
+ <Button
621
+ type="button"
622
+ size="sm"
623
+ className="h-6 cursor-pointer gap-1 px-2 text-[11px]"
624
+ onClick={handleAskAgent}
625
+ >
626
+ <IconSparkles className="size-3" />
627
+ {t("designEditor.askAgent") || "Ask agent"}
628
+ </Button>
629
+ </div>
630
+ </div>
631
+ );
632
+ }
633
+
634
+ // ─── Motion Presets panel ─────────────────────────────────────────────────────
635
+
636
+ interface MotionPresetsPanelProps {
637
+ context: DesignExtensionSlotContext;
638
+ }
639
+
640
+ function MotionPresetsPanel({ context }: MotionPresetsPanelProps) {
641
+ const t = useT();
642
+
643
+ const handleAskAgent = () => {
644
+ sendToAgentChat({
645
+ message:
646
+ "Apply a motion preset to the selected element. Suggest fade-in, slide-up, pulse, bounce, or spin, then call apply-motion-edit to write the keyframes atomically.",
647
+ context: [
648
+ `Design id: ${context.designId}`,
649
+ context.activeFileId ? `Active file id: ${context.activeFileId}` : null,
650
+ context.selectedElement
651
+ ? `Selected element: ${JSON.stringify({ selector: context.selectedElement.selector, sourceId: context.selectedElement.sourceId }, null, 2)}`
652
+ : "No element selected — ask the user to click an element first.",
653
+ "Call get-motion-timeline to check for an existing timeline, then preview-motion-frame first, then apply-motion-edit for the atomic write.",
654
+ ]
655
+ .filter(Boolean)
656
+ .join("\n"),
657
+ submit: true,
658
+ openSidebar: true,
659
+ });
660
+ };
661
+
662
+ return (
663
+ <div className="p-2.5">
664
+ <p className="mb-2 text-[10px] leading-snug text-muted-foreground">
665
+ One-click animation presets — fade-in, slide-up, pulse, bounce, spin —
666
+ applied to the selected element via the motion timeline.
667
+ </p>
668
+ {!context.selectedElement && (
669
+ <p className="mb-1.5 text-[10px] text-muted-foreground">
670
+ Select an element on the canvas first, then ask the agent to apply a
671
+ motion preset.
672
+ </p>
673
+ )}
674
+ <div className="flex flex-wrap gap-1.5">
675
+ <Button
676
+ type="button"
677
+ size="sm"
678
+ className="h-6 cursor-pointer gap-1 px-2 text-[11px]"
679
+ onClick={handleAskAgent}
680
+ >
681
+ <IconSparkles className="size-3" />
682
+ {t("designEditor.askAgent") || "Ask agent"}
683
+ </Button>
684
+ </div>
685
+ </div>
686
+ );
687
+ }
688
+
689
+ // ─── Main panel ──────────────────────────────────────────────────────────────
690
+
168
691
  export function DesignExtensionsPanel({
169
692
  context,
170
693
  className,
@@ -173,6 +696,9 @@ export function DesignExtensionsPanel({
173
696
  const queryClient = useQueryClient();
174
697
  const [createOpen, setCreateOpen] = useState(false);
175
698
  const [installingId, setInstallingId] = useState<string | null>(null);
699
+ const [openFirstParty, setOpenFirstParty] = useState<FirstPartyExtId | null>(
700
+ null,
701
+ );
176
702
  const slotId = DESIGN_EDITOR_EXTENSION_SLOT_ID;
177
703
  const { data: installs = [], isLoading } = useSlotInstalls(slotId);
178
704
  const { data: available = [] } = useAvailableExtensions(slotId);
@@ -184,6 +710,10 @@ export function DesignExtensionsPanel({
184
710
  (extension) => !installedIds.has(extension.extensionId),
185
711
  );
186
712
 
713
+ const toggleFirstParty = (id: FirstPartyExtId) => {
714
+ setOpenFirstParty((prev) => (prev === id ? null : id));
715
+ };
716
+
187
717
  const submitCreatePrompt: PromptComposerSubmitHandler = (
188
718
  text: string,
189
719
  _files,
@@ -232,6 +762,45 @@ export function DesignExtensionsPanel({
232
762
  }
233
763
  };
234
764
 
765
+ // First-party extension row config
766
+ const firstPartyRows: Array<{
767
+ id: FirstPartyExtId;
768
+ label: string;
769
+ description: string;
770
+ icon: React.ReactNode;
771
+ badge?: React.ReactNode;
772
+ panel: React.ReactNode;
773
+ }> = [
774
+ {
775
+ id: "design.asset-library",
776
+ label: "Asset Library",
777
+ description: "Browse & insert assets into the active screen",
778
+ icon: <IconPhoto className="size-3.5" />,
779
+ panel: <AssetLibraryPanel context={context} />,
780
+ },
781
+ {
782
+ id: "design.shader-fills",
783
+ label: "Shader Fills",
784
+ description: "GPU shader fill presets — preview & apply",
785
+ icon: <IconSparkles className="size-3.5" />,
786
+ panel: <ShaderFillsExtPanel context={context} />,
787
+ },
788
+ {
789
+ id: "design.token-auditor",
790
+ label: "Token Auditor",
791
+ description: "Audit CSS token usage, flag clashes",
792
+ icon: <IconPalette className="size-3.5" />,
793
+ panel: <TokenAuditorPanel context={context} />,
794
+ },
795
+ {
796
+ id: "design.motion-presets",
797
+ label: "Motion Presets",
798
+ description: "One-click animation presets for elements",
799
+ icon: <IconPlayerPlay className="size-3.5" />,
800
+ panel: <MotionPresetsPanel context={context} />,
801
+ },
802
+ ];
803
+
235
804
  return (
236
805
  <div className={cn("flex min-h-0 flex-1 flex-col", className)}>
237
806
  {/* Section header — 32 px tall, matches PanelSection / design inspector headers */}
@@ -261,54 +830,47 @@ export function DesignExtensionsPanel({
261
830
  </div>
262
831
 
263
832
  <div className="design-inspector-scroll min-h-0 flex-1 overflow-y-auto overscroll-contain px-3 pb-2 pt-1.5">
833
+ {/* ── First-party built-in extensions ──────────────────────────── */}
834
+ <div className="mb-3 space-y-1">
835
+ <p className="mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
836
+ Built-in
837
+ </p>
838
+ {firstPartyRows.map((row) => (
839
+ <FirstPartyExtRow
840
+ key={row.id}
841
+ id={row.id}
842
+ label={row.label}
843
+ description={row.description}
844
+ icon={row.icon}
845
+ badge={row.badge}
846
+ isOpen={openFirstParty === row.id}
847
+ onToggle={() => toggleFirstParty(row.id)}
848
+ >
849
+ {row.panel}
850
+ </FirstPartyExtRow>
851
+ ))}
852
+ </div>
853
+
854
+ {/* ── Agent help text ───────────────────────────────────────────── */}
855
+ <div className="mb-3 flex items-start gap-1.5 rounded-md bg-muted/40 px-2 py-1.5">
856
+ <IconSparkles className="mt-0.5 size-3 shrink-0 text-muted-foreground/70" />
857
+ <p className="text-[10px] leading-snug text-muted-foreground">
858
+ The agent can insert assets, apply shader fills, audit tokens, and
859
+ apply motion presets. Ask in the chat sidebar for help.
860
+ </p>
861
+ </div>
862
+
863
+ {/* ── User-installed extensions ──────────────────────────────────── */}
264
864
  {isLoading ? (
265
865
  <div className="space-y-1.5">
266
866
  <Skeleton className="h-24 rounded" />
267
867
  <Skeleton className="h-32 rounded" />
268
868
  </div>
269
- ) : installs.length === 0 ? (
270
- /* Empty state — compact, matches TweaksPanel empty style */
271
- <div className="flex flex-col items-center gap-2 py-6 text-center">
272
- <div className="flex size-8 items-center justify-center rounded-lg bg-muted/60">
273
- <IconPuzzle className="size-4 text-muted-foreground/70" />
274
- </div>
275
- <div>
276
- <p className="text-[11px] font-medium text-foreground">
277
- {t("designEditor.extensionsEmptyTitle")}
278
- </p>
279
- <p className="mt-0.5 text-[11px] leading-snug text-muted-foreground">
280
- {t("designEditor.extensionsEmptyDescription")}
281
- </p>
282
- </div>
283
- <div className="flex flex-wrap items-center justify-center gap-1.5">
284
- <Button
285
- type="button"
286
- size="sm"
287
- className="h-6 cursor-pointer px-2.5 text-[11px]"
288
- onClick={() => setCreateOpen(true)}
289
- >
290
- <IconPlus className="size-3" />
291
- {t("designEditor.addExtension")}
292
- </Button>
293
- <Button
294
- asChild
295
- type="button"
296
- variant="outline"
297
- size="sm"
298
- className="h-6 cursor-pointer px-2.5 text-[11px]"
299
- >
300
- <a
301
- href="https://www.agent-native.com/docs/extensions"
302
- target="_blank"
303
- rel="noreferrer"
304
- >
305
- {t("designEditor.extensionsDocs")}
306
- </a>
307
- </Button>
308
- </div>
309
- </div>
310
- ) : (
869
+ ) : installs.length > 0 ? (
311
870
  <div className="space-y-1.5">
871
+ <p className="mb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
872
+ Installed
873
+ </p>
312
874
  {installs.map((install) => (
313
875
  <EmbeddedExtension
314
876
  key={install.installId}
@@ -320,8 +882,33 @@ export function DesignExtensionsPanel({
320
882
  />
321
883
  ))}
322
884
  </div>
885
+ ) : (
886
+ /* Empty state for user extensions — compact */
887
+ <div className="flex flex-col items-center gap-2 py-4 text-center">
888
+ <div className="flex size-7 items-center justify-center rounded-lg bg-muted/60">
889
+ <IconPuzzle className="size-3.5 text-muted-foreground/70" />
890
+ </div>
891
+ <div>
892
+ <p className="text-[11px] font-medium text-foreground">
893
+ {t("designEditor.extensionsEmptyTitle")}
894
+ </p>
895
+ <p className="mt-0.5 text-[10px] leading-snug text-muted-foreground">
896
+ {t("designEditor.extensionsEmptyDescription")}
897
+ </p>
898
+ </div>
899
+ <Button
900
+ type="button"
901
+ size="sm"
902
+ className="h-6 cursor-pointer px-2.5 text-[11px]"
903
+ onClick={() => setCreateOpen(true)}
904
+ >
905
+ <IconPlus className="size-3" />
906
+ {t("designEditor.addExtension")}
907
+ </Button>
908
+ </div>
323
909
  )}
324
910
 
911
+ {/* ── Available (installable) extensions ────────────────────────── */}
325
912
  {installable.length > 0 ? (
326
913
  <div className="mt-3 border-t border-border/60 pt-1.5">
327
914
  <p className="mb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
@@ -358,6 +945,8 @@ export function DesignExtensionsPanel({
358
945
  );
359
946
  }
360
947
 
948
+ // ─── Create extension popover ─────────────────────────────────────────────────
949
+
361
950
  function CreateExtensionPopover({
362
951
  open,
363
952
  onOpenChange,