@agent-native/core 0.79.27 → 0.80.1

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 (497) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +34 -0
  3. package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +5 -0
  4. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +55 -1
  5. package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +5 -0
  6. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +66 -1
  7. package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +5 -0
  8. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +65 -1
  9. package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +5 -0
  10. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +64 -1
  11. package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +5 -0
  12. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +59 -1
  13. package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +5 -0
  14. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +62 -1
  15. package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +5 -0
  16. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +58 -1
  17. package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +5 -0
  18. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +62 -1
  19. package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +5 -0
  20. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +50 -1
  21. package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +5 -0
  22. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +52 -1
  23. package/corpus/core/docs/content/skills-guide.mdx +5 -0
  24. package/corpus/core/docs/content/template-design.mdx +59 -1
  25. package/corpus/core/package.json +2 -1
  26. package/corpus/core/src/agent/engine/index.ts +1 -0
  27. package/corpus/core/src/agent/engine/registry.ts +40 -0
  28. package/corpus/core/src/agent/production-agent.ts +6 -2
  29. package/corpus/core/src/application-state/handlers.ts +1 -1
  30. package/corpus/core/src/brand-kit/index.ts +1 -1
  31. package/corpus/core/src/cli/design-connect.ts +490 -0
  32. package/corpus/core/src/cli/index.ts +16 -0
  33. package/corpus/core/src/cli/skills.ts +144 -3
  34. package/corpus/core/src/client/AgentPanel.tsx +1 -1
  35. package/corpus/core/src/client/AssistantChat.tsx +43 -7
  36. package/corpus/core/src/client/MultiTabAssistantChat.tsx +1 -1
  37. package/corpus/core/src/client/agent-chat.ts +27 -3
  38. package/corpus/core/src/client/blocks/library/MermaidBlock.tsx +1 -1
  39. package/corpus/core/src/client/blocks/library/diagram.tsx +2 -2
  40. package/corpus/core/src/client/blocks/library/wireframe.tsx +1 -1
  41. package/corpus/core/src/client/chat/message-components.tsx +1 -1
  42. package/corpus/core/src/client/chat-model-groups.ts +1 -2
  43. package/corpus/core/src/client/components/LiveCursorOverlay.tsx +33 -66
  44. package/corpus/core/src/client/composer/TiptapComposer.tsx +99 -24
  45. package/corpus/core/src/client/composer/useVoiceDictation.ts +429 -260
  46. package/corpus/core/src/client/extensions/portable-extension.ts +1 -1
  47. package/corpus/core/src/client/frame-protocol.ts +17 -2
  48. package/corpus/core/src/client/rich-markdown-editor/RegistryBlockNode.tsx +2 -2
  49. package/corpus/core/src/client/sharing/ShareButton.tsx +20 -15
  50. package/corpus/core/src/client/use-agent-engine-configured.ts +80 -28
  51. package/corpus/core/src/code-agents/transcript-normalizer.ts +1 -1
  52. package/corpus/core/src/extensions/path.ts +1 -4
  53. package/corpus/core/src/integrations/a2a-continuation-processor.ts +1 -1
  54. package/corpus/core/src/mcp/build-server.ts +1 -1
  55. package/corpus/core/src/org/handlers.ts +5 -5
  56. package/corpus/core/src/org/plugin.ts +2 -2
  57. package/corpus/core/src/scripts/call-agent.ts +1 -1
  58. package/corpus/core/src/scripts/db/safety.ts +1 -1
  59. package/corpus/core/src/server/auth.ts +3 -0
  60. package/corpus/core/src/server/builder-design-systems.ts +308 -0
  61. package/corpus/core/src/server/core-routes-plugin.ts +29 -3
  62. package/corpus/core/src/server/index.ts +8 -0
  63. package/corpus/core/src/server/transcribe-voice.ts +57 -22
  64. package/corpus/core/src/shared/mcp-embed-headers.ts +23 -1
  65. package/corpus/core/src/styles/agent-native.css +60 -4
  66. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  67. package/corpus/core/src/usage/store.ts +2 -2
  68. package/corpus/core/src/vite/client.ts +2 -0
  69. package/corpus/core/src/voice/index.ts +18 -0
  70. package/corpus/core/src/voice/voice-cleanup-prompt.ts +38 -0
  71. package/corpus/core/src/voice/voice-context.ts +217 -0
  72. package/corpus/core/src/voice/voice-replacements.ts +75 -0
  73. package/corpus/templates/analytics/AGENTS.md +4 -3
  74. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +298 -15
  75. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +9 -4
  76. package/corpus/templates/analytics/actions/list-session-recordings.ts +6 -1
  77. package/corpus/templates/analytics/actions/mutate-dashboard.ts +18 -2
  78. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +12 -2
  79. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +557 -400
  80. package/corpus/templates/analytics/app/global.css +0 -4
  81. package/corpus/templates/analytics/app/hooks/use-replay-storage-status.ts +66 -0
  82. package/corpus/templates/analytics/app/i18n/zh-TW.ts +39 -0
  83. package/corpus/templates/analytics/app/i18n-data.ts +424 -0
  84. package/corpus/templates/analytics/app/pages/Settings.tsx +333 -0
  85. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +2 -1
  86. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +121 -3
  87. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +82 -34
  88. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +7 -0
  89. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +144 -36
  90. package/corpus/templates/analytics/changelog/2026-06-28-ask-tab-now-matches-the-darker-app-background.md +6 -0
  91. package/corpus/templates/analytics/changelog/2026-06-28-dashboard-email-reports-now-use-cleaner-light-mode-snapshots.md +6 -0
  92. package/corpus/templates/analytics/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  93. package/corpus/templates/analytics/changelog/2026-06-28-sessions-now-show-only-signed-in-recordings-with-playable-re.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-06-29-analytics-agents-can-now-place-new-charts-into-requested-das.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-06-29-analytics-queries-now-report-failed-source-query-errors-inst.md +6 -0
  96. package/corpus/templates/analytics/changelog/2026-06-29-charts-can-now-be-dropped-between-full-dashboard-rows-to-cre.md +6 -0
  97. package/corpus/templates/analytics/changelog/2026-06-29-dashboard-email-reports-include-the-full-dashboard-image-wit.md +6 -0
  98. package/corpus/templates/analytics/changelog/2026-06-29-main-surface-border-reaches-the-top.md +6 -0
  99. package/corpus/templates/analytics/changelog/2026-06-29-session-replay-now-records-playable-sessions-in-production-a.md +6 -0
  100. package/corpus/templates/analytics/changelog/2026-06-29-set-up-session-replay-storage-from-settings-connect-builder-.md +6 -0
  101. package/corpus/templates/analytics/scripts/cleanup-empty-session-recordings.ts +102 -0
  102. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +3 -3
  103. package/corpus/templates/analytics/server/lib/dashboard-report.ts +75 -30
  104. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +5 -2
  105. package/corpus/templates/analytics/server/lib/real-data-actions.ts +81 -20
  106. package/corpus/templates/analytics/server/lib/replay-storage.ts +79 -0
  107. package/corpus/templates/analytics/server/lib/s3-upload-provider.ts +255 -0
  108. package/corpus/templates/analytics/server/lib/session-replay.ts +53 -12
  109. package/corpus/templates/analytics/server/plugins/agent-chat.ts +11 -2
  110. package/corpus/templates/analytics/server/plugins/onboarding.ts +97 -0
  111. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +4 -4
  112. package/corpus/templates/assets/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  113. package/corpus/templates/brain/app/components/layout/Layout.tsx +29 -2
  114. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +131 -42
  115. package/corpus/templates/brain/app/i18n/zh-TW.ts +2 -0
  116. package/corpus/templates/brain/app/i18n-data.ts +20 -0
  117. package/corpus/templates/brain/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  118. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +29 -1
  119. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +417 -299
  120. package/corpus/templates/calendar/app/i18n/zh-TW.ts +2 -0
  121. package/corpus/templates/calendar/app/i18n-data.ts +20 -0
  122. package/corpus/templates/calendar/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  123. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +6 -19
  124. package/corpus/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  125. package/corpus/templates/clips/AGENTS.md +4 -0
  126. package/corpus/templates/clips/actions/cleanup-transcript.ts +39 -9
  127. package/corpus/templates/clips/actions/finalize-meeting.ts +81 -12
  128. package/corpus/templates/clips/actions/lib/agents-md-context.ts +4 -1
  129. package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -3
  130. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +1 -1
  131. package/corpus/templates/clips/app/components/player/share-dialog.tsx +2 -2
  132. package/corpus/templates/clips/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
  133. package/corpus/templates/clips/desktop/src/lib/personal-vocabulary.ts +13 -8
  134. package/corpus/templates/clips/desktop/src/lib/recorder.ts +24 -0
  135. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +105 -5
  136. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +60 -1
  137. package/corpus/templates/content/actions/set-image-alt-text.ts +1 -1
  138. package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +1 -1
  139. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +1 -1
  140. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +5 -5
  141. package/corpus/templates/content/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  142. package/corpus/templates/content/shared/document-export.ts +1 -1
  143. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -18
  144. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +154 -0
  145. package/corpus/templates/design/AGENTS.md +95 -5
  146. package/corpus/templates/design/DESIGN.md +82 -0
  147. package/corpus/templates/design/DEVELOPING.md +43 -0
  148. package/corpus/templates/design/actions/add-localhost-screens.ts +453 -0
  149. package/corpus/templates/design/actions/apply-shader.ts +277 -0
  150. package/corpus/templates/design/actions/apply-visual-edit.ts +303 -0
  151. package/corpus/templates/design/actions/connect-localhost.ts +183 -0
  152. package/corpus/templates/design/actions/edit-design.ts +195 -42
  153. package/corpus/templates/design/actions/generate-design.ts +71 -1
  154. package/corpus/templates/design/actions/generate-screens.ts +193 -0
  155. package/corpus/templates/design/actions/get-code-layer-projection.ts +191 -0
  156. package/corpus/templates/design/actions/get-shader.ts +119 -0
  157. package/corpus/templates/design/actions/index-design-system-with-builder.ts +259 -0
  158. package/corpus/templates/design/actions/list-localhost-connections.ts +95 -0
  159. package/corpus/templates/design/actions/navigate.ts +55 -2
  160. package/corpus/templates/design/actions/update-file.ts +9 -2
  161. package/corpus/templates/design/actions/view-screen.ts +68 -1
  162. package/corpus/templates/design/agent-native.app-skill.json +10 -0
  163. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +719 -0
  164. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +2120 -103
  165. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +74 -38
  166. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +401 -0
  167. package/corpus/templates/design/app/components/design/EditPanel.tsx +3966 -440
  168. package/corpus/templates/design/app/components/design/LayersPanel.tsx +1473 -0
  169. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +3940 -147
  170. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +700 -13
  171. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +105 -63
  172. package/corpus/templates/design/app/components/design/index.ts +0 -5
  173. package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +353 -0
  174. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +1589 -0
  175. package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +511 -0
  176. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +395 -0
  177. package/corpus/templates/design/app/components/design/inspector/FigmaColorPicker.tsx +2010 -0
  178. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +601 -0
  179. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +242 -0
  180. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +420 -0
  181. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +238 -0
  182. package/corpus/templates/design/app/components/design/inspector/ShaderControls.stories.tsx +71 -0
  183. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +575 -0
  184. package/corpus/templates/design/app/components/design/inspector/ShaderEffectRow.tsx +106 -0
  185. package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +423 -0
  186. package/corpus/templates/design/app/components/design/inspector/figma-icons.tsx +741 -0
  187. package/corpus/templates/design/app/components/design/inspector/index.ts +87 -0
  188. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +201 -0
  189. package/corpus/templates/design/app/components/design/types.ts +23 -0
  190. package/corpus/templates/design/app/components/layout/Layout.tsx +24 -13
  191. package/corpus/templates/design/app/components/layout/Sidebar.tsx +4 -4
  192. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +474 -36
  193. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +22 -5
  194. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +24 -11
  195. package/corpus/templates/design/app/global.css +149 -5
  196. package/corpus/templates/design/app/hooks/use-agent-generating.ts +4 -0
  197. package/corpus/templates/design/app/hooks/use-navigation-state.ts +130 -8
  198. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +329 -0
  199. package/corpus/templates/design/app/i18n/zh-TW.ts +277 -0
  200. package/corpus/templates/design/app/i18n-data.ts +3028 -1
  201. package/corpus/templates/design/app/pages/DesignEditor.tsx +5831 -904
  202. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +57 -221
  203. package/corpus/templates/design/changelog/2026-06-28-annotate-mode-now-combines-drawing-and-comment-pins-in-one-c.md +6 -0
  204. package/corpus/templates/design/changelog/2026-06-28-design-editor-panel-borders-are-cleaner-so-the-canvas-edge-s.md +6 -0
  205. package/corpus/templates/design/changelog/2026-06-28-drawing-prompts-now-reliably-open-and-submit-to-the-design-a.md +6 -0
  206. package/corpus/templates/design/changelog/2026-06-28-editor-app-menus-now-use-an-outline-agent-native-mark-with-b.md +6 -0
  207. package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +6 -0
  208. package/corpus/templates/design/changelog/2026-06-28-layer-selection-now-updates-chat-context-without-opening-the.md +6 -0
  209. package/corpus/templates/design/changelog/2026-06-28-layer-selections-now-preserve-hidden-and-locked-canvas-state.md +6 -0
  210. package/corpus/templates/design/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  211. package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +6 -0
  212. package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +6 -0
  213. package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-handles-zooming-drawing-opening-and-dele.md +6 -0
  214. package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-selects-screens-on-click-and-opens-them-.md +6 -0
  215. package/corpus/templates/design/changelog/2026-06-28-screen-overview-zooms-into-the-active-screen-with-smoother-e.md +6 -0
  216. package/corpus/templates/design/changelog/2026-06-28-selected-element-chips-in-chat-are-shorter-and-easier-to-sca.md +6 -0
  217. package/corpus/templates/design/changelog/2026-06-28-the-design-editor-toolbar-is-more-compact-and-the-app-menu-m.md +6 -0
  218. package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-at-the-top-of-the-design-sidebar-instead-of-.md +6 -0
  219. package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-in-the-right-inspector-beside-the-design-tab.md +6 -0
  220. package/corpus/templates/design/changelog/2026-06-29-active-sidebar-rows-use-soft-highlights.md +6 -0
  221. package/corpus/templates/design/changelog/2026-06-29-agents-can-now-open-screen-overview-focus-screens-and-add.md +6 -0
  222. package/corpus/templates/design/changelog/2026-06-29-canvas-selection-no-longer-flashes-broken-prototype-html-whe.md +6 -0
  223. package/corpus/templates/design/changelog/2026-06-29-command-menu-selections-are-clearer-in-dark-mode.md +6 -0
  224. package/corpus/templates/design/changelog/2026-06-29-design-agents-now-edit-broad-copy-changes-more-reliably.md +6 -0
  225. package/corpus/templates/design/changelog/2026-06-29-design-editor-extensions-now-run-inline-beside-the-artboard.md +6 -0
  226. package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +6 -0
  227. package/corpus/templates/design/changelog/2026-06-29-element-selection-now-stays-on-the-intended-layer-after-sele.md +6 -0
  228. package/corpus/templates/design/changelog/2026-06-29-screen-overview-full-view-controls-now-sit-above-frames-inst.md +6 -0
  229. package/corpus/templates/design/changelog/2026-06-29-screen-overview-tools-can-draw-shapes-create-screens-and-kee.md +6 -0
  230. package/corpus/templates/design/changelog/2026-06-29-sidebars-use-darker-chrome-and-chat-warns-immediately.md +6 -0
  231. package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-now-creates-anchor-based-bezier-vectors-with-ha.md +6 -0
  232. package/corpus/templates/design/changelog/2026-06-29-visual-edit-can-open-localhost-routes-as-url-backed-screens.md +6 -0
  233. package/corpus/templates/design/package.json +1 -0
  234. package/corpus/templates/design/server/db/schema.ts +26 -0
  235. package/corpus/templates/design/server/handlers/import-figma-system.ts +38 -85
  236. package/corpus/templates/design/server/lib/design-snapshot.ts +9 -1
  237. package/corpus/templates/design/server/plugins/agent-chat.ts +3 -0
  238. package/corpus/templates/design/shared/api.ts +27 -0
  239. package/corpus/templates/design/shared/canvas-frames.ts +103 -0
  240. package/corpus/templates/design/shared/canvas-math.ts +1058 -0
  241. package/corpus/templates/design/shared/code-layer.ts +2412 -0
  242. package/corpus/templates/design/shared/color-utils.ts +180 -0
  243. package/corpus/templates/design/shared/generation-session.ts +61 -0
  244. package/corpus/templates/design/shared/html-content.ts +21 -0
  245. package/corpus/templates/design/shared/pen-path.ts +207 -0
  246. package/corpus/templates/design/shared/shader-presets.ts +782 -0
  247. package/corpus/templates/design/shared/shader-safety.ts +137 -0
  248. package/corpus/templates/design/shared/source-mode.ts +237 -0
  249. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +149 -6
  250. package/corpus/templates/forms/app/i18n/ar-SA.ts +2 -0
  251. package/corpus/templates/forms/app/i18n/de-DE.ts +2 -0
  252. package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
  253. package/corpus/templates/forms/app/i18n/es-ES.ts +2 -0
  254. package/corpus/templates/forms/app/i18n/fr-FR.ts +2 -0
  255. package/corpus/templates/forms/app/i18n/hi-IN.ts +2 -0
  256. package/corpus/templates/forms/app/i18n/ja-JP.ts +2 -0
  257. package/corpus/templates/forms/app/i18n/ko-KR.ts +2 -0
  258. package/corpus/templates/forms/app/i18n/pt-BR.ts +2 -0
  259. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  260. package/corpus/templates/forms/app/i18n/zh-TW.ts +2 -0
  261. package/corpus/templates/forms/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  262. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +2 -2
  263. package/corpus/templates/macros/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
  264. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +408 -247
  265. package/corpus/templates/mail/app/i18n/ar-SA.ts +4 -0
  266. package/corpus/templates/mail/app/i18n/de-DE.ts +4 -0
  267. package/corpus/templates/mail/app/i18n/en-US.ts +4 -0
  268. package/corpus/templates/mail/app/i18n/es-ES.ts +4 -0
  269. package/corpus/templates/mail/app/i18n/fr-FR.ts +4 -0
  270. package/corpus/templates/mail/app/i18n/hi-IN.ts +4 -0
  271. package/corpus/templates/mail/app/i18n/ja-JP.ts +4 -0
  272. package/corpus/templates/mail/app/i18n/ko-KR.ts +4 -0
  273. package/corpus/templates/mail/app/i18n/pt-BR.ts +4 -0
  274. package/corpus/templates/mail/app/i18n/zh-CN.ts +4 -0
  275. package/corpus/templates/mail/app/i18n/zh-TW.ts +4 -0
  276. package/corpus/templates/mail/app/lib/utils.ts +2 -2
  277. package/corpus/templates/mail/changelog/2026-06-28-pinned-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  278. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +6 -8
  279. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +1 -1
  280. package/corpus/templates/plan/app/global.css +61 -78
  281. package/corpus/templates/plan/app/pages/PlansPage.tsx +8 -0
  282. package/corpus/templates/plan/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  283. package/corpus/templates/plan/changelog/2026-06-28-plans-use-the-shared-neutral-light-and-dark-theme.md +6 -0
  284. package/corpus/templates/plan/changelog/2026-06-28-sending-open-feedback-from-a-plan-now-opens-the-inline-plan-.md +6 -0
  285. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +9 -10
  286. package/corpus/templates/slides/AGENTS.md +3 -2
  287. package/corpus/templates/slides/actions/import-file.ts +26 -17
  288. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +259 -0
  289. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +35 -167
  290. package/corpus/templates/slides/app/components/design-system/fig-import-response.ts +9 -13
  291. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +5 -5
  292. package/corpus/templates/slides/app/context/DeckContext.tsx +1 -1
  293. package/corpus/templates/slides/app/i18n/ar-SA.ts +9 -37
  294. package/corpus/templates/slides/app/i18n/de-DE.ts +10 -25
  295. package/corpus/templates/slides/app/i18n/en-US.ts +9 -26
  296. package/corpus/templates/slides/app/i18n/es-ES.ts +10 -28
  297. package/corpus/templates/slides/app/i18n/fr-FR.ts +10 -28
  298. package/corpus/templates/slides/app/i18n/hi-IN.ts +9 -26
  299. package/corpus/templates/slides/app/i18n/ja-JP.ts +10 -22
  300. package/corpus/templates/slides/app/i18n/ko-KR.ts +9 -23
  301. package/corpus/templates/slides/app/i18n/pt-BR.ts +10 -28
  302. package/corpus/templates/slides/app/i18n/zh-CN.ts +9 -22
  303. package/corpus/templates/slides/app/i18n/zh-TW.ts +9 -22
  304. package/corpus/templates/slides/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  305. package/corpus/templates/slides/server/handlers/import-figma-system.ts +44 -12
  306. package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
  307. package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +1 -1
  308. package/corpus/templates/videos/app/components/Sidebar.tsx +2 -2
  309. package/corpus/templates/videos/app/components/layout/Layout.tsx +29 -2
  310. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +113 -30
  311. package/corpus/templates/videos/app/i18n/ar-SA.ts +2 -0
  312. package/corpus/templates/videos/app/i18n/de-DE.ts +2 -0
  313. package/corpus/templates/videos/app/i18n/en-US.ts +2 -0
  314. package/corpus/templates/videos/app/i18n/es-ES.ts +2 -0
  315. package/corpus/templates/videos/app/i18n/fr-FR.ts +2 -0
  316. package/corpus/templates/videos/app/i18n/hi-IN.ts +2 -0
  317. package/corpus/templates/videos/app/i18n/ja-JP.ts +2 -0
  318. package/corpus/templates/videos/app/i18n/ko-KR.ts +2 -0
  319. package/corpus/templates/videos/app/i18n/pt-BR.ts +2 -0
  320. package/corpus/templates/videos/app/i18n/zh-CN.ts +2 -0
  321. package/corpus/templates/videos/app/i18n/zh-TW.ts +2 -0
  322. package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  323. package/dist/agent/engine/index.d.ts +1 -1
  324. package/dist/agent/engine/index.d.ts.map +1 -1
  325. package/dist/agent/engine/index.js +1 -1
  326. package/dist/agent/engine/index.js.map +1 -1
  327. package/dist/agent/engine/registry.d.ts +9 -0
  328. package/dist/agent/engine/registry.d.ts.map +1 -1
  329. package/dist/agent/engine/registry.js +37 -0
  330. package/dist/agent/engine/registry.js.map +1 -1
  331. package/dist/agent/production-agent.d.ts.map +1 -1
  332. package/dist/agent/production-agent.js +4 -3
  333. package/dist/agent/production-agent.js.map +1 -1
  334. package/dist/application-state/handlers.js +1 -1
  335. package/dist/application-state/handlers.js.map +1 -1
  336. package/dist/brand-kit/index.d.ts +1 -1
  337. package/dist/brand-kit/index.js +1 -1
  338. package/dist/brand-kit/index.js.map +1 -1
  339. package/dist/cli/design-connect.d.ts +52 -0
  340. package/dist/cli/design-connect.d.ts.map +1 -0
  341. package/dist/cli/design-connect.js +409 -0
  342. package/dist/cli/design-connect.js.map +1 -0
  343. package/dist/cli/index.js +15 -0
  344. package/dist/cli/index.js.map +1 -1
  345. package/dist/cli/skills.d.ts +3 -0
  346. package/dist/cli/skills.d.ts.map +1 -1
  347. package/dist/cli/skills.js +139 -3
  348. package/dist/cli/skills.js.map +1 -1
  349. package/dist/client/AgentPanel.js +1 -1
  350. package/dist/client/AgentPanel.js.map +1 -1
  351. package/dist/client/AssistantChat.d.ts.map +1 -1
  352. package/dist/client/AssistantChat.js +38 -8
  353. package/dist/client/AssistantChat.js.map +1 -1
  354. package/dist/client/MultiTabAssistantChat.js +1 -1
  355. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  356. package/dist/client/agent-chat.d.ts +6 -0
  357. package/dist/client/agent-chat.d.ts.map +1 -1
  358. package/dist/client/agent-chat.js +17 -3
  359. package/dist/client/agent-chat.js.map +1 -1
  360. package/dist/client/blocks/library/MermaidBlock.js +1 -1
  361. package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
  362. package/dist/client/blocks/library/diagram.js +1 -1
  363. package/dist/client/blocks/library/diagram.js.map +1 -1
  364. package/dist/client/blocks/library/wireframe.js +1 -1
  365. package/dist/client/blocks/library/wireframe.js.map +1 -1
  366. package/dist/client/chat/message-components.js +1 -1
  367. package/dist/client/chat/message-components.js.map +1 -1
  368. package/dist/client/chat-model-groups.d.ts.map +1 -1
  369. package/dist/client/chat-model-groups.js +1 -2
  370. package/dist/client/chat-model-groups.js.map +1 -1
  371. package/dist/client/components/LiveCursorOverlay.d.ts +1 -2
  372. package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
  373. package/dist/client/components/LiveCursorOverlay.js +19 -40
  374. package/dist/client/components/LiveCursorOverlay.js.map +1 -1
  375. package/dist/client/composer/TiptapComposer.d.ts +3 -1
  376. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  377. package/dist/client/composer/TiptapComposer.js +86 -24
  378. package/dist/client/composer/TiptapComposer.js.map +1 -1
  379. package/dist/client/composer/useVoiceDictation.d.ts +9 -0
  380. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  381. package/dist/client/composer/useVoiceDictation.js +154 -32
  382. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  383. package/dist/client/extensions/portable-extension.d.ts +1 -1
  384. package/dist/client/extensions/portable-extension.d.ts.map +1 -1
  385. package/dist/client/extensions/portable-extension.js.map +1 -1
  386. package/dist/client/frame-protocol.d.ts +17 -2
  387. package/dist/client/frame-protocol.d.ts.map +1 -1
  388. package/dist/client/frame-protocol.js.map +1 -1
  389. package/dist/client/rich-markdown-editor/RegistryBlockNode.js +2 -2
  390. package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
  391. package/dist/client/sharing/ShareButton.d.ts +2 -0
  392. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  393. package/dist/client/sharing/ShareButton.js +7 -6
  394. package/dist/client/sharing/ShareButton.js.map +1 -1
  395. package/dist/client/use-agent-engine-configured.d.ts +5 -0
  396. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  397. package/dist/client/use-agent-engine-configured.js +51 -25
  398. package/dist/client/use-agent-engine-configured.js.map +1 -1
  399. package/dist/code-agents/transcript-normalizer.js +1 -1
  400. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  401. package/dist/collab/routes.d.ts +1 -1
  402. package/dist/extensions/path.d.ts +1 -1
  403. package/dist/extensions/path.d.ts.map +1 -1
  404. package/dist/extensions/path.js.map +1 -1
  405. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  406. package/dist/integrations/a2a-continuation-processor.js +1 -1
  407. package/dist/integrations/a2a-continuation-processor.js.map +1 -1
  408. package/dist/mcp/build-server.d.ts +1 -1
  409. package/dist/mcp/build-server.d.ts.map +1 -1
  410. package/dist/mcp/build-server.js.map +1 -1
  411. package/dist/notifications/routes.d.ts +3 -3
  412. package/dist/observability/routes.d.ts +5 -5
  413. package/dist/org/handlers.js +5 -5
  414. package/dist/org/handlers.js.map +1 -1
  415. package/dist/org/plugin.js +2 -2
  416. package/dist/org/plugin.js.map +1 -1
  417. package/dist/scripts/call-agent.js +1 -1
  418. package/dist/scripts/call-agent.js.map +1 -1
  419. package/dist/scripts/db/safety.js +1 -1
  420. package/dist/scripts/db/safety.js.map +1 -1
  421. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  422. package/dist/server/auth.d.ts.map +1 -1
  423. package/dist/server/auth.js +3 -0
  424. package/dist/server/auth.js.map +1 -1
  425. package/dist/server/builder-design-systems.d.ts +28 -0
  426. package/dist/server/builder-design-systems.d.ts.map +1 -0
  427. package/dist/server/builder-design-systems.js +217 -0
  428. package/dist/server/builder-design-systems.js.map +1 -0
  429. package/dist/server/core-routes-plugin.d.ts +1 -0
  430. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  431. package/dist/server/core-routes-plugin.js +20 -3
  432. package/dist/server/core-routes-plugin.js.map +1 -1
  433. package/dist/server/index.d.ts +1 -0
  434. package/dist/server/index.d.ts.map +1 -1
  435. package/dist/server/index.js +1 -0
  436. package/dist/server/index.js.map +1 -1
  437. package/dist/server/transcribe-voice.d.ts +1 -1
  438. package/dist/server/transcribe-voice.d.ts.map +1 -1
  439. package/dist/server/transcribe-voice.js +40 -24
  440. package/dist/server/transcribe-voice.js.map +1 -1
  441. package/dist/shared/mcp-embed-headers.d.ts +1 -0
  442. package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
  443. package/dist/shared/mcp-embed-headers.js +20 -1
  444. package/dist/shared/mcp-embed-headers.js.map +1 -1
  445. package/dist/styles/agent-native.css +60 -4
  446. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  447. package/dist/usage/store.js +2 -2
  448. package/dist/usage/store.js.map +1 -1
  449. package/dist/vite/client.d.ts.map +1 -1
  450. package/dist/vite/client.js +2 -0
  451. package/dist/vite/client.js.map +1 -1
  452. package/dist/voice/index.d.ts +5 -0
  453. package/dist/voice/index.d.ts.map +1 -0
  454. package/dist/voice/index.js +4 -0
  455. package/dist/voice/index.js.map +1 -0
  456. package/dist/voice/voice-cleanup-prompt.d.ts +6 -0
  457. package/dist/voice/voice-cleanup-prompt.d.ts.map +1 -0
  458. package/dist/voice/voice-cleanup-prompt.js +26 -0
  459. package/dist/voice/voice-cleanup-prompt.js.map +1 -0
  460. package/dist/voice/voice-context.d.ts +25 -0
  461. package/dist/voice/voice-context.d.ts.map +1 -0
  462. package/dist/voice/voice-context.js +156 -0
  463. package/dist/voice/voice-context.js.map +1 -0
  464. package/dist/voice/voice-replacements.d.ts +4 -0
  465. package/dist/voice/voice-replacements.d.ts.map +1 -0
  466. package/dist/voice/voice-replacements.js +52 -0
  467. package/dist/voice/voice-replacements.js.map +1 -0
  468. package/docs/content/locales/ar-SA/skills-guide.mdx +5 -0
  469. package/docs/content/locales/ar-SA/template-design.mdx +55 -1
  470. package/docs/content/locales/de-DE/skills-guide.mdx +5 -0
  471. package/docs/content/locales/de-DE/template-design.mdx +66 -1
  472. package/docs/content/locales/es-ES/skills-guide.mdx +5 -0
  473. package/docs/content/locales/es-ES/template-design.mdx +65 -1
  474. package/docs/content/locales/fr-FR/skills-guide.mdx +5 -0
  475. package/docs/content/locales/fr-FR/template-design.mdx +64 -1
  476. package/docs/content/locales/hi-IN/skills-guide.mdx +5 -0
  477. package/docs/content/locales/hi-IN/template-design.mdx +59 -1
  478. package/docs/content/locales/ja-JP/skills-guide.mdx +5 -0
  479. package/docs/content/locales/ja-JP/template-design.mdx +62 -1
  480. package/docs/content/locales/ko-KR/skills-guide.mdx +5 -0
  481. package/docs/content/locales/ko-KR/template-design.mdx +58 -1
  482. package/docs/content/locales/pt-BR/skills-guide.mdx +5 -0
  483. package/docs/content/locales/pt-BR/template-design.mdx +62 -1
  484. package/docs/content/locales/zh-CN/skills-guide.mdx +5 -0
  485. package/docs/content/locales/zh-CN/template-design.mdx +50 -1
  486. package/docs/content/locales/zh-TW/skills-guide.mdx +5 -0
  487. package/docs/content/locales/zh-TW/template-design.mdx +52 -1
  488. package/docs/content/skills-guide.mdx +5 -0
  489. package/docs/content/template-design.mdx +59 -1
  490. package/package.json +2 -1
  491. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  492. package/corpus/templates/design/actions/import-figma-file.ts +0 -166
  493. package/corpus/templates/design/app/components/design/DesignToolbar.tsx +0 -339
  494. package/corpus/templates/design/app/components/design/PresentMode.tsx +0 -68
  495. package/corpus/templates/design/app/components/design/ViewportTabs.tsx +0 -149
  496. package/corpus/templates/design/app/components/design/ZoomControls.tsx +0 -157
  497. package/corpus/templates/slides/server/lib/fig-design-system.ts +0 -110
@@ -0,0 +1,183 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import {
3
+ getRequestOrgId,
4
+ getRequestUserEmail,
5
+ } from "@agent-native/core/server/request-context";
6
+ import { and, eq } from "drizzle-orm";
7
+ import { nanoid } from "nanoid";
8
+ import { z } from "zod";
9
+
10
+ import { getDb, schema } from "../server/db/index.js";
11
+ import {
12
+ DESIGN_BRIDGE_OPERATIONS,
13
+ makeLocalhostRouteId,
14
+ titleFromRoutePath,
15
+ } from "../shared/source-mode.js";
16
+
17
+ const routeSchema = z.object({
18
+ id: z.string().optional(),
19
+ path: z.string().min(1),
20
+ title: z.string().optional(),
21
+ sourceFile: z.string().optional(),
22
+ sourceKind: z.enum(["react-router", "html", "manual"]).optional(),
23
+ screenshotUrl: z.string().optional(),
24
+ metadata: z.record(z.string(), z.unknown()).optional(),
25
+ });
26
+
27
+ const capabilitySchema = z.object({
28
+ operation: z.enum(DESIGN_BRIDGE_OPERATIONS),
29
+ status: z.enum(["available", "planned", "disabled"]),
30
+ reason: z.string().optional(),
31
+ });
32
+
33
+ function normalizeUrl(value: string, label: string): string {
34
+ const raw = value.trim();
35
+ const withProtocol = /^[a-z]+:\/\//i.test(raw) ? raw : `http://${raw}`;
36
+ const parsed = new URL(withProtocol);
37
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
38
+ throw new Error(`${label} must be an http(s) URL`);
39
+ }
40
+ parsed.hash = "";
41
+ return parsed.toString().replace(/\/$/, "");
42
+ }
43
+
44
+ export default defineAction({
45
+ description:
46
+ "Register or refresh a localhost Design source connection produced by `agent-native design connect`. Stores the dev server URL, bridge URL, route manifest, and operation capabilities so the UI can later list local-code artboards.",
47
+ schema: z.object({
48
+ id: z
49
+ .string()
50
+ .optional()
51
+ .describe("Optional existing connection ID. Omit to create one."),
52
+ name: z.string().optional().describe("Human-readable connection name."),
53
+ devServerUrl: z
54
+ .string()
55
+ .describe("Local app dev server URL, for example http://localhost:5173"),
56
+ bridgeUrl: z
57
+ .string()
58
+ .optional()
59
+ .describe("Local Design bridge URL printed by the CLI."),
60
+ rootPath: z.string().optional().describe("Repository root for the app."),
61
+ routes: z
62
+ .array(routeSchema)
63
+ .optional()
64
+ .describe("Discovered app routes/screens to become localhost artboards."),
65
+ routeManifest: z
66
+ .object({
67
+ version: z.literal(1).default(1),
68
+ sourceType: z.literal("localhost").default("localhost"),
69
+ devServerUrl: z.string().optional(),
70
+ rootPath: z.string().optional(),
71
+ routes: z.array(routeSchema),
72
+ generatedAt: z.string().optional(),
73
+ })
74
+ .optional()
75
+ .describe("Full route manifest emitted by the CLI."),
76
+ capabilities: z
77
+ .array(capabilitySchema)
78
+ .optional()
79
+ .describe("Bridge operation capabilities."),
80
+ status: z
81
+ .enum(["connected", "detected", "manual", "error"])
82
+ .optional()
83
+ .default("connected"),
84
+ }),
85
+ run: async (args) => {
86
+ const ownerEmail = getRequestUserEmail();
87
+ if (!ownerEmail) throw new Error("no authenticated user");
88
+
89
+ const now = new Date().toISOString();
90
+ const id = args.id ?? nanoid();
91
+ const db = getDb();
92
+ const devServerUrl = normalizeUrl(args.devServerUrl, "devServerUrl");
93
+ const bridgeUrl = args.bridgeUrl
94
+ ? normalizeUrl(args.bridgeUrl, "bridgeUrl")
95
+ : undefined;
96
+ const rawRoutes = args.routeManifest?.routes ?? args.routes ?? [];
97
+ const routes = rawRoutes.map((route) => ({
98
+ id: route.id ?? makeLocalhostRouteId(route.path),
99
+ path: route.path,
100
+ title: route.title ?? titleFromRoutePath(route.path),
101
+ sourceFile: route.sourceFile,
102
+ sourceKind: route.sourceKind ?? "manual",
103
+ screenshotUrl: route.screenshotUrl,
104
+ metadata: route.metadata,
105
+ }));
106
+ const routeManifest = {
107
+ version: 1 as const,
108
+ sourceType: "localhost" as const,
109
+ devServerUrl,
110
+ rootPath: args.routeManifest?.rootPath ?? args.rootPath,
111
+ routes,
112
+ generatedAt: args.routeManifest?.generatedAt ?? now,
113
+ };
114
+ const capabilities =
115
+ args.capabilities ??
116
+ DESIGN_BRIDGE_OPERATIONS.map((operation) => ({
117
+ operation,
118
+ status:
119
+ operation === "readFile" ||
120
+ operation === "applyEdit" ||
121
+ operation === "writeFile"
122
+ ? ("planned" as const)
123
+ : ("available" as const),
124
+ reason:
125
+ operation === "writeFile"
126
+ ? "Local file writes require the next bridge hardening pass."
127
+ : undefined,
128
+ }));
129
+
130
+ const values = {
131
+ id,
132
+ name: args.name ?? new URL(devServerUrl).host,
133
+ sourceType: "localhost" as const,
134
+ devServerUrl,
135
+ bridgeUrl: bridgeUrl ?? null,
136
+ rootPath: routeManifest.rootPath ?? null,
137
+ routeManifest: JSON.stringify(routeManifest),
138
+ capabilities: JSON.stringify(capabilities),
139
+ status: args.status,
140
+ lastSeenAt: now,
141
+ ownerEmail,
142
+ orgId: getRequestOrgId() ?? null,
143
+ updatedAt: now,
144
+ };
145
+
146
+ const existing = await db
147
+ .select({ id: schema.designLocalhostConnections.id })
148
+ .from(schema.designLocalhostConnections)
149
+ .where(
150
+ and(
151
+ eq(schema.designLocalhostConnections.id, id),
152
+ eq(schema.designLocalhostConnections.ownerEmail, ownerEmail),
153
+ ),
154
+ )
155
+ .limit(1);
156
+
157
+ if (existing[0]) {
158
+ await db
159
+ .update(schema.designLocalhostConnections)
160
+ .set(values)
161
+ .where(eq(schema.designLocalhostConnections.id, id));
162
+ } else {
163
+ await db.insert(schema.designLocalhostConnections).values({
164
+ ...values,
165
+ createdAt: now,
166
+ });
167
+ }
168
+
169
+ return {
170
+ id,
171
+ sourceType: "localhost",
172
+ name: values.name,
173
+ devServerUrl,
174
+ bridgeUrl: bridgeUrl ?? null,
175
+ rootPath: routeManifest.rootPath ?? null,
176
+ routeCount: routes.length,
177
+ routes,
178
+ capabilities,
179
+ status: args.status,
180
+ lastSeenAt: now,
181
+ };
182
+ },
183
+ });
@@ -13,53 +13,192 @@ import { and, eq } from "drizzle-orm";
13
13
  import { z } from "zod";
14
14
 
15
15
  import { getDb, schema } from "../server/db/index.js";
16
- import { applyEdits } from "../shared/apply-edits.js";
16
+ import {
17
+ applyOneEdit,
18
+ type ApplyEditsResult,
19
+ type DesignEdit,
20
+ } from "../shared/apply-edits.js";
21
+
22
+ const editBlocksSchema = z.preprocess(
23
+ (v) => {
24
+ if (typeof v !== "string") return v;
25
+ // Don't let malformed JSON throw an uncaught SyntaxError — return the
26
+ // raw value so Zod produces a clean validation error instead.
27
+ try {
28
+ return JSON.parse(v);
29
+ } catch {
30
+ return v;
31
+ }
32
+ },
33
+ z
34
+ .array(
35
+ z.object({
36
+ search: z
37
+ .string()
38
+ .min(1)
39
+ .describe(
40
+ "Exact text to find, with enough surrounding context to be unique",
41
+ ),
42
+ replace: z.string().describe("Replacement text"),
43
+ }),
44
+ )
45
+ .min(1),
46
+ );
47
+
48
+ function stripStableNodeIdAttributes(value: string): {
49
+ content: string;
50
+ indexMap: number[];
51
+ } {
52
+ const stableIdPattern =
53
+ /\sdata-agent-native-node-id\s*=\s*(?:"[^"]*"|'[^']*'|[^\s/>]+)/gi;
54
+ let content = "";
55
+ const indexMap: number[] = [];
56
+ let cursor = 0;
57
+ let match: RegExpExecArray | null;
58
+ while ((match = stableIdPattern.exec(value))) {
59
+ const chunk = value.slice(cursor, match.index);
60
+ for (let i = 0; i < chunk.length; i += 1) {
61
+ content += chunk[i];
62
+ indexMap.push(cursor + i);
63
+ }
64
+ cursor = match.index + match[0].length;
65
+ }
66
+ const tail = value.slice(cursor);
67
+ for (let i = 0; i < tail.length; i += 1) {
68
+ content += tail[i];
69
+ indexMap.push(cursor + i);
70
+ }
71
+ indexMap.push(value.length);
72
+ return { content, indexMap };
73
+ }
74
+
75
+ function findUniqueStableIdAgnosticSpan(
76
+ content: string,
77
+ search: string,
78
+ ): { start: number; end: number } | null {
79
+ const strippedContent = stripStableNodeIdAttributes(content);
80
+ const strippedSearch = stripStableNodeIdAttributes(search).content;
81
+ if (!strippedSearch) return null;
82
+
83
+ let count = 0;
84
+ let onlyIndex = -1;
85
+ let index = strippedContent.content.indexOf(strippedSearch);
86
+ while (index !== -1) {
87
+ count += 1;
88
+ onlyIndex = index;
89
+ if (count > 1) return null;
90
+ index = strippedContent.content.indexOf(strippedSearch, index + 1);
91
+ }
92
+ if (count !== 1) return null;
93
+
94
+ return {
95
+ start: strippedContent.indexMap[onlyIndex] ?? 0,
96
+ end:
97
+ strippedContent.indexMap[onlyIndex + strippedSearch.length] ??
98
+ content.length,
99
+ };
100
+ }
101
+
102
+ function applyOneEditWithStableIdFallback(
103
+ content: string,
104
+ edit: DesignEdit,
105
+ index: number,
106
+ ): string {
107
+ try {
108
+ return applyOneEdit(content, edit, index);
109
+ } catch (error) {
110
+ const span = findUniqueStableIdAgnosticSpan(content, edit.search);
111
+ if (!span) throw error;
112
+ return `${content.slice(0, span.start)}${edit.replace}${content.slice(span.end)}`;
113
+ }
114
+ }
115
+
116
+ export function applySearchReplaceEdits(
117
+ content: string,
118
+ edits: DesignEdit[],
119
+ ): ApplyEditsResult {
120
+ let next = content;
121
+ edits.forEach((edit, index) => {
122
+ next = applyOneEditWithStableIdFallback(next, edit, index);
123
+ });
124
+ return { content: next, applied: edits.length };
125
+ }
17
126
 
18
127
  export default defineAction({
19
128
  description:
20
- "Apply small, surgical search/replace edits to ONE file in a design the " +
129
+ "Edit ONE file in a design after reading it with get-design-snapshot. " +
130
+ "For small localized refinements, apply surgical search/replace edits — the " +
21
131
  "preferred way to refine an existing design without regenerating the whole " +
22
132
  "file (cheaper, faster, and it preserves everything you don't touch). Each " +
23
133
  "edit's `search` must match the current file exactly and uniquely, so " +
24
134
  "include enough surrounding context. Read the file first with " +
25
135
  "`get-design-snapshot`. Wrapping an element is just a search/replace whose " +
26
- "`replace` adds the wrapper around the original text. Use `generate-design` " +
136
+ "`replace` adds the wrapper around the original text. For broad copy-only " +
137
+ 'changes such as translating all visible text, use `mode: "replace-file"` ' +
138
+ "with `replacementContent`: the complete updated file content copied from " +
139
+ "the snapshot with only the requested copy changed. Use `generate-design` " +
27
140
  "instead only for brand-new files or large structural rewrites.",
28
- schema: z.object({
29
- designId: z.string().describe("Design project ID"),
30
- filename: z
31
- .string()
32
- .default("index.html")
33
- .describe("File to edit (e.g. 'index.html')"),
34
- edits: z
35
- .preprocess(
36
- (v) => {
37
- if (typeof v !== "string") return v;
38
- // Don't let malformed JSON throw an uncaught SyntaxError — return the
39
- // raw value so Zod produces a clean validation error instead.
40
- try {
41
- return JSON.parse(v);
42
- } catch {
43
- return v;
44
- }
45
- },
46
- z
47
- .array(
48
- z.object({
49
- search: z
50
- .string()
51
- .min(1)
52
- .describe(
53
- "Exact text to find, with enough surrounding context to be unique",
54
- ),
55
- replace: z.string().describe("Replacement text"),
56
- }),
57
- )
58
- .min(1),
59
- )
60
- .describe("Search/replace blocks, applied in order"),
61
- }),
62
- run: async ({ designId, filename, edits }) => {
141
+ schema: z
142
+ .object({
143
+ designId: z.string().describe("Design project ID"),
144
+ filename: z
145
+ .string()
146
+ .default("index.html")
147
+ .describe("File to edit (e.g. 'index.html')"),
148
+ mode: z
149
+ .enum(["search-replace", "replace-file"])
150
+ .optional()
151
+ .describe(
152
+ "Defaults to search-replace. Use replace-file for broad copy-only edits like translating the whole page after reading get-design-snapshot.",
153
+ ),
154
+ edits: editBlocksSchema
155
+ .optional()
156
+ .describe(
157
+ "Search/replace blocks, applied in order. Use for small localized edits.",
158
+ ),
159
+ replacementContent: z
160
+ .string()
161
+ .min(1)
162
+ .optional()
163
+ .describe(
164
+ "Complete updated file content. Use only with mode=replace-file for broad copy-only changes; preserve all HTML structure, CSS, scripts, and tweaks from get-design-snapshot.",
165
+ ),
166
+ })
167
+ .superRefine((value, ctx) => {
168
+ const mode =
169
+ value.mode ??
170
+ (value.replacementContent !== undefined
171
+ ? "replace-file"
172
+ : "search-replace");
173
+
174
+ if (value.edits && value.replacementContent !== undefined) {
175
+ ctx.addIssue({
176
+ code: z.ZodIssueCode.custom,
177
+ message:
178
+ "Use either edits or replacementContent in one edit-design call, not both.",
179
+ path: ["replacementContent"],
180
+ });
181
+ }
182
+
183
+ if (mode === "search-replace" && !value.edits) {
184
+ ctx.addIssue({
185
+ code: z.ZodIssueCode.custom,
186
+ message:
187
+ "search-replace mode requires at least one edit block in edits.",
188
+ path: ["edits"],
189
+ });
190
+ }
191
+
192
+ if (mode === "replace-file" && value.replacementContent === undefined) {
193
+ ctx.addIssue({
194
+ code: z.ZodIssueCode.custom,
195
+ message:
196
+ "replace-file mode requires replacementContent with the complete updated file.",
197
+ path: ["replacementContent"],
198
+ });
199
+ }
200
+ }),
201
+ run: async ({ designId, filename, edits, mode, replacementContent }) => {
63
202
  await assertAccess("design", designId, "editor");
64
203
 
65
204
  const db = getDb();
@@ -104,21 +243,34 @@ export default defineAction({
104
243
  // Collab read is best-effort; fall back to stored content.
105
244
  }
106
245
 
107
- const { content: nextContent, applied } = applyEdits(base, edits);
246
+ const resolvedMode =
247
+ mode ??
248
+ (replacementContent !== undefined ? "replace-file" : "search-replace");
249
+ const { content: nextContent, applied } =
250
+ resolvedMode === "replace-file"
251
+ ? { content: replacementContent ?? "", applied: 0 }
252
+ : applySearchReplaceEdits(base, edits ?? []);
108
253
  const changed = nextContent !== base;
109
254
 
110
255
  if (changed) {
111
256
  // Mark agent presence + selection so live viewers can see where the
112
257
  // agent is working before the update arrives via collab.
113
258
  agentEnterDocument(file.id);
114
- if (applied > 0) {
259
+ if (resolvedMode === "search-replace" && applied > 0) {
260
+ const firstSearch = edits?.[0]?.search;
115
261
  agentUpdateSelection(file.id, {
116
- selection: edits[0]?.search
117
- ? `[data-edit-target="${edits[0].search.slice(0, 40)}"]`
262
+ selection: firstSearch
263
+ ? `[data-edit-target="${firstSearch.slice(0, 40)}"]`
118
264
  : null,
119
265
  editingFile: filename,
120
266
  designId,
121
267
  });
268
+ } else {
269
+ agentUpdateSelection(file.id, {
270
+ selection: null,
271
+ editingFile: filename,
272
+ designId,
273
+ });
122
274
  }
123
275
 
124
276
  try {
@@ -148,6 +300,7 @@ export default defineAction({
148
300
  designId,
149
301
  filename,
150
302
  fileId: file.id,
303
+ mode: resolvedMode,
151
304
  editsApplied: applied,
152
305
  changed,
153
306
  bytesBefore: base.length,
@@ -14,6 +14,10 @@ import { nanoid } from "nanoid";
14
14
  import { z } from "zod";
15
15
 
16
16
  import { getDb, schema } from "../server/db/index.js";
17
+ import {
18
+ mergeCanvasFramePlacements,
19
+ type CanvasFramePlacement,
20
+ } from "../shared/canvas-frames.js";
17
21
 
18
22
  /** Editor deep link so external agents can surface "Open design". */
19
23
  function designDeepLink(designId: string): string {
@@ -34,7 +38,9 @@ export default defineAction({
34
38
  "version then refine individual files with `edit-design` (search/replace) rather " +
35
39
  "than resending a big multi-file payload — a single oversized payload can get cut " +
36
40
  "off mid-stream and stall the turn. " +
37
- "Do not report a design as ready until this action succeeds.",
41
+ "Do not report a design as ready until this action succeeds. " +
42
+ "When adding multiple screens or states, pass canvasFrames with filenames " +
43
+ "and x/y/width/height so the new screens appear placed on the overview canvas.",
38
44
  schema: z.object({
39
45
  designId: z.string().describe("Design project ID to save content to"),
40
46
  prompt: z.string().describe("The generation prompt (stored for reference)"),
@@ -106,6 +112,34 @@ export default defineAction({
106
112
  "radius, dark mode, font choice). Each must reference a CSS var " +
107
113
  "the design's `:root` block actually uses.",
108
114
  ),
115
+ canvasFrames: z
116
+ .preprocess(
117
+ (v) => (typeof v === "string" ? JSON.parse(v) : v),
118
+ z
119
+ .array(
120
+ z
121
+ .object({
122
+ fileId: z.string().optional(),
123
+ filename: z.string().optional(),
124
+ x: z.number().optional(),
125
+ y: z.number().optional(),
126
+ width: z.number().optional(),
127
+ height: z.number().optional(),
128
+ rotation: z.number().optional(),
129
+ z: z.number().optional(),
130
+ })
131
+ .refine((frame) => frame.fileId || frame.filename, {
132
+ message: "canvasFrames entries require fileId or filename",
133
+ }),
134
+ )
135
+ .optional(),
136
+ )
137
+ .optional()
138
+ .describe(
139
+ "Optional overview-canvas placements for generated screens. " +
140
+ "Reference each screen by filename or fileId and include x/y/width/height " +
141
+ "from generate-screens regions or your planned canvas layout.",
142
+ ),
109
143
  }),
110
144
  mcpApp: {
111
145
  compactCatalog: true,
@@ -124,6 +158,7 @@ export default defineAction({
124
158
  designSystemId,
125
159
  projectType,
126
160
  tweaks,
161
+ canvasFrames,
127
162
  }) => {
128
163
  await assertAccess("design", designId, "editor");
129
164
  if (designSystemId) {
@@ -280,6 +315,40 @@ export default defineAction({
280
315
  type: tweak.type === "color-swatches" ? "color-swatch" : tweak.type,
281
316
  }));
282
317
  }
318
+ let placedFrames:
319
+ | Array<{
320
+ fileId: string;
321
+ filename?: string;
322
+ frame: CanvasFramePlacement;
323
+ }>
324
+ | undefined;
325
+ if (canvasFrames !== undefined) {
326
+ const savedByFileId = new Map(savedFiles.map((file) => [file.id, file]));
327
+ const savedByFilename = new Map(
328
+ savedFiles.map((file) => [file.filename, file]),
329
+ );
330
+ const existingByFileId = new Map(
331
+ existingFiles.map((file) => [file.id, file]),
332
+ );
333
+ const merged = mergeCanvasFramePlacements({
334
+ existing: prevData.canvasFrames,
335
+ placements: canvasFrames,
336
+ resolveFileId: (placement) => {
337
+ if (placement.fileId) {
338
+ return savedByFileId.has(placement.fileId) ||
339
+ existingByFileId.has(placement.fileId)
340
+ ? placement.fileId
341
+ : undefined;
342
+ }
343
+ return placement.filename
344
+ ? (savedByFilename.get(placement.filename)?.id ??
345
+ existingByName.get(placement.filename)?.id)
346
+ : undefined;
347
+ },
348
+ });
349
+ mergedData.canvasFrames = merged.canvasFrames;
350
+ placedFrames = merged.placedFrames;
351
+ }
283
352
  designUpdates.data = JSON.stringify(mergedData);
284
353
 
285
354
  await db
@@ -292,6 +361,7 @@ export default defineAction({
292
361
  urlPath: `/design/${designId}`,
293
362
  renderable: true,
294
363
  savedFiles,
364
+ placedFrames,
295
365
  fileCount: savedFiles.length,
296
366
  };
297
367
  },