@agent-native/core 0.79.27 → 0.80.0

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 (346) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +26 -0
  3. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +41 -0
  4. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +51 -0
  5. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +50 -0
  6. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +49 -0
  7. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +44 -0
  8. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +46 -0
  9. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +44 -0
  10. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +48 -0
  11. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +36 -0
  12. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +38 -0
  13. package/corpus/core/docs/content/template-design.mdx +45 -0
  14. package/corpus/core/package.json +2 -1
  15. package/corpus/core/src/agent/engine/index.ts +1 -0
  16. package/corpus/core/src/agent/engine/registry.ts +40 -0
  17. package/corpus/core/src/agent/production-agent.ts +6 -2
  18. package/corpus/core/src/cli/design-connect.ts +490 -0
  19. package/corpus/core/src/cli/index.ts +16 -0
  20. package/corpus/core/src/cli/skills.ts +126 -3
  21. package/corpus/core/src/client/AssistantChat.tsx +43 -7
  22. package/corpus/core/src/client/agent-chat.ts +27 -3
  23. package/corpus/core/src/client/blocks/library/MermaidBlock.tsx +1 -1
  24. package/corpus/core/src/client/blocks/library/diagram.tsx +2 -2
  25. package/corpus/core/src/client/blocks/library/wireframe.tsx +1 -1
  26. package/corpus/core/src/client/chat/message-components.tsx +1 -1
  27. package/corpus/core/src/client/chat-model-groups.ts +1 -2
  28. package/corpus/core/src/client/components/LiveCursorOverlay.tsx +33 -66
  29. package/corpus/core/src/client/composer/TiptapComposer.tsx +99 -24
  30. package/corpus/core/src/client/composer/useVoiceDictation.ts +429 -260
  31. package/corpus/core/src/client/frame-protocol.ts +17 -2
  32. package/corpus/core/src/client/rich-markdown-editor/RegistryBlockNode.tsx +2 -2
  33. package/corpus/core/src/client/sharing/ShareButton.tsx +20 -15
  34. package/corpus/core/src/client/use-agent-engine-configured.ts +80 -28
  35. package/corpus/core/src/server/transcribe-voice.ts +57 -22
  36. package/corpus/core/src/shared/mcp-embed-headers.ts +23 -1
  37. package/corpus/core/src/styles/agent-native.css +56 -7
  38. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  39. package/corpus/core/src/vite/client.ts +2 -0
  40. package/corpus/core/src/voice/index.ts +18 -0
  41. package/corpus/core/src/voice/voice-cleanup-prompt.ts +38 -0
  42. package/corpus/core/src/voice/voice-context.ts +217 -0
  43. package/corpus/core/src/voice/voice-replacements.ts +75 -0
  44. package/corpus/templates/analytics/AGENTS.md +4 -3
  45. package/corpus/templates/analytics/actions/list-session-recordings.ts +6 -1
  46. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +557 -400
  47. package/corpus/templates/analytics/app/global.css +0 -4
  48. package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
  49. package/corpus/templates/analytics/app/i18n-data.ts +20 -0
  50. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +33 -8
  51. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +7 -0
  52. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +7 -0
  53. package/corpus/templates/analytics/changelog/2026-06-28-ask-tab-now-matches-the-darker-app-background.md +6 -0
  54. package/corpus/templates/analytics/changelog/2026-06-28-dashboard-email-reports-now-use-cleaner-light-mode-snapshots.md +6 -0
  55. package/corpus/templates/analytics/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  56. package/corpus/templates/analytics/changelog/2026-06-28-sessions-now-show-only-signed-in-recordings-with-playable-re.md +6 -0
  57. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +3 -3
  58. package/corpus/templates/analytics/server/lib/dashboard-report.ts +29 -7
  59. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +5 -2
  60. package/corpus/templates/analytics/server/lib/session-replay.ts +24 -4
  61. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +4 -4
  62. package/corpus/templates/assets/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  63. package/corpus/templates/brain/app/components/layout/Layout.tsx +29 -2
  64. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +131 -42
  65. package/corpus/templates/brain/app/i18n/zh-TW.ts +2 -0
  66. package/corpus/templates/brain/app/i18n-data.ts +20 -0
  67. package/corpus/templates/brain/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  68. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +29 -1
  69. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +417 -299
  70. package/corpus/templates/calendar/app/i18n/zh-TW.ts +2 -0
  71. package/corpus/templates/calendar/app/i18n-data.ts +20 -0
  72. package/corpus/templates/calendar/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  73. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +6 -19
  74. package/corpus/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  75. package/corpus/templates/clips/AGENTS.md +4 -0
  76. package/corpus/templates/clips/actions/cleanup-transcript.ts +39 -9
  77. package/corpus/templates/clips/actions/finalize-meeting.ts +81 -12
  78. package/corpus/templates/clips/actions/lib/agents-md-context.ts +4 -1
  79. package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -3
  80. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +1 -1
  81. package/corpus/templates/clips/app/components/player/share-dialog.tsx +2 -2
  82. package/corpus/templates/clips/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
  83. package/corpus/templates/clips/desktop/src/lib/personal-vocabulary.ts +13 -8
  84. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +60 -1
  85. package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +1 -1
  86. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +1 -1
  87. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +5 -5
  88. package/corpus/templates/content/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  89. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +137 -0
  90. package/corpus/templates/design/AGENTS.md +95 -5
  91. package/corpus/templates/design/DESIGN.md +82 -0
  92. package/corpus/templates/design/DEVELOPING.md +43 -0
  93. package/corpus/templates/design/actions/add-localhost-screens.ts +426 -0
  94. package/corpus/templates/design/actions/apply-shader.ts +277 -0
  95. package/corpus/templates/design/actions/apply-visual-edit.ts +303 -0
  96. package/corpus/templates/design/actions/connect-localhost.ts +183 -0
  97. package/corpus/templates/design/actions/edit-design.ts +195 -42
  98. package/corpus/templates/design/actions/generate-design.ts +71 -1
  99. package/corpus/templates/design/actions/generate-screens.ts +193 -0
  100. package/corpus/templates/design/actions/get-code-layer-projection.ts +191 -0
  101. package/corpus/templates/design/actions/get-shader.ts +119 -0
  102. package/corpus/templates/design/actions/list-localhost-connections.ts +95 -0
  103. package/corpus/templates/design/actions/navigate.ts +55 -2
  104. package/corpus/templates/design/actions/view-screen.ts +68 -1
  105. package/corpus/templates/design/agent-native.app-skill.json +10 -0
  106. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +761 -0
  107. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +2057 -103
  108. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +74 -38
  109. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +399 -0
  110. package/corpus/templates/design/app/components/design/EditPanel.tsx +3185 -439
  111. package/corpus/templates/design/app/components/design/LayersPanel.tsx +1124 -0
  112. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +3116 -147
  113. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +700 -13
  114. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +107 -63
  115. package/corpus/templates/design/app/components/design/index.ts +0 -5
  116. package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +286 -0
  117. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +699 -0
  118. package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +461 -0
  119. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +166 -0
  120. package/corpus/templates/design/app/components/design/inspector/FigmaColorPicker.tsx +1420 -0
  121. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +420 -0
  122. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +215 -0
  123. package/corpus/templates/design/app/components/design/inspector/ShaderControls.stories.tsx +71 -0
  124. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +518 -0
  125. package/corpus/templates/design/app/components/design/inspector/ShaderEffectRow.tsx +106 -0
  126. package/corpus/templates/design/app/components/design/inspector/figma-icons.tsx +361 -0
  127. package/corpus/templates/design/app/components/design/inspector/index.ts +60 -0
  128. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +201 -0
  129. package/corpus/templates/design/app/components/design/types.ts +23 -0
  130. package/corpus/templates/design/app/components/layout/Layout.tsx +24 -13
  131. package/corpus/templates/design/app/components/layout/Sidebar.tsx +4 -4
  132. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +474 -36
  133. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +22 -5
  134. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +24 -11
  135. package/corpus/templates/design/app/global.css +121 -3
  136. package/corpus/templates/design/app/hooks/use-agent-generating.ts +4 -0
  137. package/corpus/templates/design/app/hooks/use-navigation-state.ts +130 -8
  138. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +329 -0
  139. package/corpus/templates/design/app/i18n/zh-TW.ts +264 -0
  140. package/corpus/templates/design/app/i18n-data.ts +2790 -1
  141. package/corpus/templates/design/app/pages/DesignEditor.tsx +5108 -851
  142. package/corpus/templates/design/changelog/2026-06-28-annotate-mode-now-combines-drawing-and-comment-pins-in-one-c.md +6 -0
  143. package/corpus/templates/design/changelog/2026-06-28-design-editor-panel-borders-are-cleaner-so-the-canvas-edge-s.md +6 -0
  144. package/corpus/templates/design/changelog/2026-06-28-drawing-prompts-now-reliably-open-and-submit-to-the-design-a.md +6 -0
  145. package/corpus/templates/design/changelog/2026-06-28-editor-app-menus-now-use-an-outline-agent-native-mark-with-b.md +6 -0
  146. package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +6 -0
  147. package/corpus/templates/design/changelog/2026-06-28-layer-selection-now-updates-chat-context-without-opening-the.md +6 -0
  148. package/corpus/templates/design/changelog/2026-06-28-layer-selections-now-preserve-hidden-and-locked-canvas-state.md +6 -0
  149. package/corpus/templates/design/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  150. package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +6 -0
  151. package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +6 -0
  152. package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-handles-zooming-drawing-opening-and-dele.md +6 -0
  153. package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-selects-screens-on-click-and-opens-them-.md +6 -0
  154. package/corpus/templates/design/changelog/2026-06-28-screen-overview-zooms-into-the-active-screen-with-smoother-e.md +6 -0
  155. package/corpus/templates/design/changelog/2026-06-28-selected-element-chips-in-chat-are-shorter-and-easier-to-sca.md +6 -0
  156. package/corpus/templates/design/changelog/2026-06-28-the-design-editor-toolbar-is-more-compact-and-the-app-menu-m.md +6 -0
  157. package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-at-the-top-of-the-design-sidebar-instead-of-.md +6 -0
  158. package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-in-the-right-inspector-beside-the-design-tab.md +6 -0
  159. package/corpus/templates/design/changelog/2026-06-29-active-sidebar-rows-use-soft-highlights.md +6 -0
  160. package/corpus/templates/design/changelog/2026-06-29-agents-can-now-open-screen-overview-focus-screens-and-add.md +6 -0
  161. package/corpus/templates/design/changelog/2026-06-29-design-agents-now-edit-broad-copy-changes-more-reliably.md +6 -0
  162. package/corpus/templates/design/changelog/2026-06-29-design-editor-extensions-now-run-inline-beside-the-artboard.md +6 -0
  163. package/corpus/templates/design/changelog/2026-06-29-sidebars-use-darker-chrome-and-chat-warns-immediately.md +6 -0
  164. package/corpus/templates/design/changelog/2026-06-29-visual-edit-can-open-localhost-routes-as-url-backed-screens.md +6 -0
  165. package/corpus/templates/design/package.json +1 -0
  166. package/corpus/templates/design/server/db/schema.ts +26 -0
  167. package/corpus/templates/design/server/lib/design-snapshot.ts +1 -1
  168. package/corpus/templates/design/server/plugins/agent-chat.ts +3 -0
  169. package/corpus/templates/design/shared/api.ts +27 -0
  170. package/corpus/templates/design/shared/canvas-frames.ts +103 -0
  171. package/corpus/templates/design/shared/canvas-math.ts +1058 -0
  172. package/corpus/templates/design/shared/code-layer.ts +2212 -0
  173. package/corpus/templates/design/shared/color-utils.ts +180 -0
  174. package/corpus/templates/design/shared/generation-session.ts +61 -0
  175. package/corpus/templates/design/shared/shader-presets.ts +782 -0
  176. package/corpus/templates/design/shared/shader-safety.ts +137 -0
  177. package/corpus/templates/design/shared/source-mode.ts +237 -0
  178. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +149 -6
  179. package/corpus/templates/forms/app/i18n/ar-SA.ts +2 -0
  180. package/corpus/templates/forms/app/i18n/de-DE.ts +2 -0
  181. package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
  182. package/corpus/templates/forms/app/i18n/es-ES.ts +2 -0
  183. package/corpus/templates/forms/app/i18n/fr-FR.ts +2 -0
  184. package/corpus/templates/forms/app/i18n/hi-IN.ts +2 -0
  185. package/corpus/templates/forms/app/i18n/ja-JP.ts +2 -0
  186. package/corpus/templates/forms/app/i18n/ko-KR.ts +2 -0
  187. package/corpus/templates/forms/app/i18n/pt-BR.ts +2 -0
  188. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  189. package/corpus/templates/forms/app/i18n/zh-TW.ts +2 -0
  190. package/corpus/templates/forms/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  191. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +2 -2
  192. package/corpus/templates/macros/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
  193. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +408 -247
  194. package/corpus/templates/mail/app/i18n/ar-SA.ts +4 -0
  195. package/corpus/templates/mail/app/i18n/de-DE.ts +4 -0
  196. package/corpus/templates/mail/app/i18n/en-US.ts +4 -0
  197. package/corpus/templates/mail/app/i18n/es-ES.ts +4 -0
  198. package/corpus/templates/mail/app/i18n/fr-FR.ts +4 -0
  199. package/corpus/templates/mail/app/i18n/hi-IN.ts +4 -0
  200. package/corpus/templates/mail/app/i18n/ja-JP.ts +4 -0
  201. package/corpus/templates/mail/app/i18n/ko-KR.ts +4 -0
  202. package/corpus/templates/mail/app/i18n/pt-BR.ts +4 -0
  203. package/corpus/templates/mail/app/i18n/zh-CN.ts +4 -0
  204. package/corpus/templates/mail/app/i18n/zh-TW.ts +4 -0
  205. package/corpus/templates/mail/changelog/2026-06-28-pinned-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  206. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +6 -8
  207. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +1 -1
  208. package/corpus/templates/plan/app/global.css +61 -78
  209. package/corpus/templates/plan/app/pages/PlansPage.tsx +8 -0
  210. package/corpus/templates/plan/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  211. package/corpus/templates/plan/changelog/2026-06-28-plans-use-the-shared-neutral-light-and-dark-theme.md +6 -0
  212. package/corpus/templates/plan/changelog/2026-06-28-sending-open-feedback-from-a-plan-now-opens-the-inline-plan-.md +6 -0
  213. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +5 -5
  214. package/corpus/templates/slides/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  215. package/corpus/templates/videos/app/components/Sidebar.tsx +2 -2
  216. package/corpus/templates/videos/app/components/layout/Layout.tsx +29 -2
  217. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +113 -30
  218. package/corpus/templates/videos/app/i18n/ar-SA.ts +2 -0
  219. package/corpus/templates/videos/app/i18n/de-DE.ts +2 -0
  220. package/corpus/templates/videos/app/i18n/en-US.ts +2 -0
  221. package/corpus/templates/videos/app/i18n/es-ES.ts +2 -0
  222. package/corpus/templates/videos/app/i18n/fr-FR.ts +2 -0
  223. package/corpus/templates/videos/app/i18n/hi-IN.ts +2 -0
  224. package/corpus/templates/videos/app/i18n/ja-JP.ts +2 -0
  225. package/corpus/templates/videos/app/i18n/ko-KR.ts +2 -0
  226. package/corpus/templates/videos/app/i18n/pt-BR.ts +2 -0
  227. package/corpus/templates/videos/app/i18n/zh-CN.ts +2 -0
  228. package/corpus/templates/videos/app/i18n/zh-TW.ts +2 -0
  229. package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  230. package/dist/agent/engine/index.d.ts +1 -1
  231. package/dist/agent/engine/index.d.ts.map +1 -1
  232. package/dist/agent/engine/index.js +1 -1
  233. package/dist/agent/engine/index.js.map +1 -1
  234. package/dist/agent/engine/registry.d.ts +9 -0
  235. package/dist/agent/engine/registry.d.ts.map +1 -1
  236. package/dist/agent/engine/registry.js +37 -0
  237. package/dist/agent/engine/registry.js.map +1 -1
  238. package/dist/agent/production-agent.d.ts.map +1 -1
  239. package/dist/agent/production-agent.js +4 -3
  240. package/dist/agent/production-agent.js.map +1 -1
  241. package/dist/cli/design-connect.d.ts +52 -0
  242. package/dist/cli/design-connect.d.ts.map +1 -0
  243. package/dist/cli/design-connect.js +409 -0
  244. package/dist/cli/design-connect.js.map +1 -0
  245. package/dist/cli/index.js +15 -0
  246. package/dist/cli/index.js.map +1 -1
  247. package/dist/cli/skills.d.ts +3 -0
  248. package/dist/cli/skills.d.ts.map +1 -1
  249. package/dist/cli/skills.js +121 -3
  250. package/dist/cli/skills.js.map +1 -1
  251. package/dist/client/AssistantChat.d.ts.map +1 -1
  252. package/dist/client/AssistantChat.js +38 -8
  253. package/dist/client/AssistantChat.js.map +1 -1
  254. package/dist/client/agent-chat.d.ts +6 -0
  255. package/dist/client/agent-chat.d.ts.map +1 -1
  256. package/dist/client/agent-chat.js +17 -3
  257. package/dist/client/agent-chat.js.map +1 -1
  258. package/dist/client/blocks/library/MermaidBlock.js +1 -1
  259. package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
  260. package/dist/client/blocks/library/diagram.js +1 -1
  261. package/dist/client/blocks/library/diagram.js.map +1 -1
  262. package/dist/client/blocks/library/wireframe.js +1 -1
  263. package/dist/client/blocks/library/wireframe.js.map +1 -1
  264. package/dist/client/chat/message-components.js +1 -1
  265. package/dist/client/chat/message-components.js.map +1 -1
  266. package/dist/client/chat-model-groups.d.ts.map +1 -1
  267. package/dist/client/chat-model-groups.js +1 -2
  268. package/dist/client/chat-model-groups.js.map +1 -1
  269. package/dist/client/components/LiveCursorOverlay.d.ts +1 -2
  270. package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
  271. package/dist/client/components/LiveCursorOverlay.js +19 -40
  272. package/dist/client/components/LiveCursorOverlay.js.map +1 -1
  273. package/dist/client/composer/TiptapComposer.d.ts +3 -1
  274. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  275. package/dist/client/composer/TiptapComposer.js +86 -24
  276. package/dist/client/composer/TiptapComposer.js.map +1 -1
  277. package/dist/client/composer/useVoiceDictation.d.ts +9 -0
  278. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  279. package/dist/client/composer/useVoiceDictation.js +154 -32
  280. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  281. package/dist/client/frame-protocol.d.ts +17 -2
  282. package/dist/client/frame-protocol.d.ts.map +1 -1
  283. package/dist/client/frame-protocol.js.map +1 -1
  284. package/dist/client/rich-markdown-editor/RegistryBlockNode.js +2 -2
  285. package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
  286. package/dist/client/sharing/ShareButton.d.ts +2 -0
  287. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  288. package/dist/client/sharing/ShareButton.js +7 -6
  289. package/dist/client/sharing/ShareButton.js.map +1 -1
  290. package/dist/client/use-agent-engine-configured.d.ts +5 -0
  291. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  292. package/dist/client/use-agent-engine-configured.js +51 -25
  293. package/dist/client/use-agent-engine-configured.js.map +1 -1
  294. package/dist/collab/awareness.d.ts +2 -2
  295. package/dist/collab/awareness.d.ts.map +1 -1
  296. package/dist/collab/routes.d.ts +1 -1
  297. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  298. package/dist/notifications/routes.d.ts +3 -3
  299. package/dist/observability/routes.d.ts +8 -8
  300. package/dist/progress/routes.d.ts +1 -1
  301. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  302. package/dist/server/transcribe-voice.d.ts.map +1 -1
  303. package/dist/server/transcribe-voice.js +40 -24
  304. package/dist/server/transcribe-voice.js.map +1 -1
  305. package/dist/shared/mcp-embed-headers.d.ts +1 -0
  306. package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
  307. package/dist/shared/mcp-embed-headers.js +20 -1
  308. package/dist/shared/mcp-embed-headers.js.map +1 -1
  309. package/dist/styles/agent-native.css +56 -7
  310. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  311. package/dist/vite/client.d.ts.map +1 -1
  312. package/dist/vite/client.js +2 -0
  313. package/dist/vite/client.js.map +1 -1
  314. package/dist/voice/index.d.ts +5 -0
  315. package/dist/voice/index.d.ts.map +1 -0
  316. package/dist/voice/index.js +4 -0
  317. package/dist/voice/index.js.map +1 -0
  318. package/dist/voice/voice-cleanup-prompt.d.ts +6 -0
  319. package/dist/voice/voice-cleanup-prompt.d.ts.map +1 -0
  320. package/dist/voice/voice-cleanup-prompt.js +26 -0
  321. package/dist/voice/voice-cleanup-prompt.js.map +1 -0
  322. package/dist/voice/voice-context.d.ts +25 -0
  323. package/dist/voice/voice-context.d.ts.map +1 -0
  324. package/dist/voice/voice-context.js +156 -0
  325. package/dist/voice/voice-context.js.map +1 -0
  326. package/dist/voice/voice-replacements.d.ts +4 -0
  327. package/dist/voice/voice-replacements.d.ts.map +1 -0
  328. package/dist/voice/voice-replacements.js +52 -0
  329. package/dist/voice/voice-replacements.js.map +1 -0
  330. package/docs/content/locales/ar-SA/template-design.mdx +41 -0
  331. package/docs/content/locales/de-DE/template-design.mdx +51 -0
  332. package/docs/content/locales/es-ES/template-design.mdx +50 -0
  333. package/docs/content/locales/fr-FR/template-design.mdx +49 -0
  334. package/docs/content/locales/hi-IN/template-design.mdx +44 -0
  335. package/docs/content/locales/ja-JP/template-design.mdx +46 -0
  336. package/docs/content/locales/ko-KR/template-design.mdx +44 -0
  337. package/docs/content/locales/pt-BR/template-design.mdx +48 -0
  338. package/docs/content/locales/zh-CN/template-design.mdx +36 -0
  339. package/docs/content/locales/zh-TW/template-design.mdx +38 -0
  340. package/docs/content/template-design.mdx +45 -0
  341. package/package.json +2 -1
  342. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  343. package/corpus/templates/design/app/components/design/DesignToolbar.tsx +0 -339
  344. package/corpus/templates/design/app/components/design/PresentMode.tsx +0 -68
  345. package/corpus/templates/design/app/components/design/ViewportTabs.tsx +0 -149
  346. package/corpus/templates/design/app/components/design/ZoomControls.tsx +0 -157
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.79.27",
3
+ "version": "0.80.0",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -89,6 +89,7 @@
89
89
  "./embedding/react": "./dist/embedding/react.js",
90
90
  "./onboarding": "./dist/onboarding/index.js",
91
91
  "./shared": "./dist/shared/index.js",
92
+ "./voice": "./dist/voice/index.js",
92
93
  "./scripts": "./dist/scripts/index.js",
93
94
  "./application-state": "./dist/application-state/index.js",
94
95
  "./settings": "./dist/settings/index.js",
@@ -30,6 +30,7 @@ export {
30
30
  isAgentEnginePackageInstalled,
31
31
  isStoredEngineUsable,
32
32
  isStoredEngineUsableForRequest,
33
+ isResolvedEngineUsableForRequest,
33
34
  type AgentEngineEntry,
34
35
  type ResolveEngineConfig,
35
36
  } from "./registry.js";
@@ -412,6 +412,46 @@ export async function isStoredEngineUsableForRequest(
412
412
  return true;
413
413
  }
414
414
 
415
+ /**
416
+ * Request-aware credential preflight for an already-resolved engine instance.
417
+ * `resolveEngine()` may still return a default or explicitly requested engine
418
+ * object before credentials are actually usable; call this before starting a
419
+ * user-visible run so missing providers fail immediately.
420
+ */
421
+ export async function isResolvedEngineUsableForRequest(
422
+ engine: AgentEngine,
423
+ options: { apiKey?: string } = {},
424
+ ): Promise<boolean> {
425
+ const entry = _registry.get(engine.name);
426
+ // Custom engines may have their own credential contract outside the core
427
+ // registry metadata, so do not block them speculatively.
428
+ if (!entry) return true;
429
+ if (!isAgentEnginePackageInstalled(entry)) return false;
430
+ if (entry.requiredEnvVars.length === 0) return true;
431
+
432
+ if (entry.name === "builder") {
433
+ const creds = await resolveBuilderCredentials();
434
+ return Boolean(creds.privateKey && creds.publicKey);
435
+ }
436
+
437
+ if (options.apiKey?.trim()) return true;
438
+
439
+ for (const key of entry.requiredEnvVars) {
440
+ try {
441
+ if (await resolveSecret(key)) continue;
442
+ } catch {
443
+ // Fall through to deployment-level fallback when allowed.
444
+ }
445
+ if (
446
+ !canUseDeployCredentialFallbackForRequest() ||
447
+ !readDeployCredentialEnv(key)
448
+ ) {
449
+ return false;
450
+ }
451
+ }
452
+ return true;
453
+ }
454
+
415
455
  export interface ResolveEngineConfig {
416
456
  /** Explicit engine name or instance from createAgentChatPlugin options */
417
457
  engineOption?:
@@ -67,6 +67,7 @@ import {
67
67
  registerBuiltinEngines,
68
68
  getStoredModelForEngine,
69
69
  normalizeModelForEngine,
70
+ isResolvedEngineUsableForRequest,
70
71
  } from "./engine/index.js";
71
72
  import { resolveMaxOutputTokensForEngine } from "./engine/output-tokens.js";
72
73
  import { PROVIDER_TO_ENV } from "./engine/provider-env-vars.js";
@@ -4206,8 +4207,11 @@ export function createProductionAgentHandler(
4206
4207
  `[agent-chat] resolved engine=${engine.name} model=${model} requestEngine=${requestEngine ?? "(none)"}`,
4207
4208
  );
4208
4209
 
4209
- // Check for API key before starting a run (only for anthropic engine)
4210
- if (engine.name === "anthropic" && !effectiveApiKey) {
4210
+ if (
4211
+ !(await isResolvedEngineUsableForRequest(engine, {
4212
+ apiKey: effectiveApiKey,
4213
+ }))
4214
+ ) {
4211
4215
  setResponseHeader(event, "Content-Type", "text/event-stream");
4212
4216
  setResponseHeader(event, "Cache-Control", "no-cache");
4213
4217
  setResponseHeader(event, "Connection", "keep-alive");
@@ -0,0 +1,490 @@
1
+ import fsSync from "node:fs";
2
+ import fs from "node:fs/promises";
3
+ import http, {
4
+ type IncomingMessage,
5
+ type Server,
6
+ type ServerResponse,
7
+ } from "node:http";
8
+ import path from "node:path";
9
+
10
+ const DEFAULT_BRIDGE_PORT = 7331;
11
+ const ROUTE_MANIFEST_FILE = path.join(".agent-native", "design-routes.json");
12
+ const DEFAULT_DEV_SERVER_CANDIDATES = [
13
+ "http://127.0.0.1:5173",
14
+ "http://localhost:5173",
15
+ "http://127.0.0.1:3000",
16
+ "http://localhost:3000",
17
+ "http://127.0.0.1:8080",
18
+ "http://localhost:8080",
19
+ ];
20
+
21
+ const BRIDGE_OPERATIONS = [
22
+ "select",
23
+ "resolveNodeToFile",
24
+ "readFile",
25
+ "applyEdit",
26
+ "writeFile",
27
+ "captureSnapshot",
28
+ "captureState",
29
+ ] as const;
30
+
31
+ type BridgeOperation = (typeof BRIDGE_OPERATIONS)[number];
32
+
33
+ export interface DesignConnectArgs {
34
+ url?: string;
35
+ port: number;
36
+ root: string;
37
+ routeManifest?: string;
38
+ json: boolean;
39
+ once: boolean;
40
+ dryRun: boolean;
41
+ help: boolean;
42
+ }
43
+
44
+ export interface DesignConnectRoute {
45
+ id: string;
46
+ path: string;
47
+ title: string;
48
+ sourceFile?: string;
49
+ sourceKind: "react-router" | "html" | "manual";
50
+ }
51
+
52
+ export interface DesignConnectManifest {
53
+ version: 1;
54
+ source: "agent-native-design-connect";
55
+ sourceType: "localhost";
56
+ localOnly: true;
57
+ devServerUrl: string;
58
+ bridgeUrl: string;
59
+ rootPath: string;
60
+ routeManifestPath: string;
61
+ routeManifestCreated: boolean;
62
+ routes: DesignConnectRoute[];
63
+ routeCount: number;
64
+ generatedAt: string;
65
+ capabilities: Array<{
66
+ operation: BridgeOperation;
67
+ status: "available" | "planned" | "disabled";
68
+ reason?: string;
69
+ }>;
70
+ }
71
+
72
+ export interface DesignConnectBridge {
73
+ server: Server;
74
+ manifest: DesignConnectManifest;
75
+ }
76
+
77
+ function stringFlagValue(argv: string[], index: number, flag: string) {
78
+ const value = argv[index + 1];
79
+ if (!value || value.startsWith("-")) {
80
+ throw new Error(`${flag} requires a value`);
81
+ }
82
+ return value;
83
+ }
84
+
85
+ function normalizeSlash(value: string) {
86
+ return value.replace(/\\/g, "/");
87
+ }
88
+
89
+ function normalizeHttpUrl(value: string): string {
90
+ const raw = value.trim();
91
+ const withProtocol = /^[a-z]+:\/\//i.test(raw) ? raw : `http://${raw}`;
92
+ const parsed = new URL(withProtocol);
93
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
94
+ throw new Error("--url must be an http(s) URL");
95
+ }
96
+ parsed.hash = "";
97
+ return parsed.toString().replace(/\/$/, "");
98
+ }
99
+
100
+ export function parseDesignConnectArgs(argv: string[]): DesignConnectArgs {
101
+ const args = argv[0] === "connect" ? argv.slice(1) : argv;
102
+ const parsed: DesignConnectArgs = {
103
+ port: DEFAULT_BRIDGE_PORT,
104
+ root: process.cwd(),
105
+ json: false,
106
+ once: false,
107
+ dryRun: false,
108
+ help: false,
109
+ };
110
+
111
+ for (let index = 0; index < args.length; index += 1) {
112
+ const arg = args[index]!;
113
+ if (arg === "help" || arg === "--help" || arg === "-h") {
114
+ parsed.help = true;
115
+ } else if (arg === "--url") {
116
+ parsed.url = stringFlagValue(args, index, arg);
117
+ index += 1;
118
+ } else if (arg.startsWith("--url=")) {
119
+ parsed.url = arg.slice("--url=".length);
120
+ } else if (arg === "--port") {
121
+ parsed.port = Number.parseInt(stringFlagValue(args, index, arg), 10);
122
+ index += 1;
123
+ } else if (arg.startsWith("--port=")) {
124
+ parsed.port = Number.parseInt(arg.slice("--port=".length), 10);
125
+ } else if (arg === "--root") {
126
+ parsed.root = stringFlagValue(args, index, arg);
127
+ index += 1;
128
+ } else if (arg.startsWith("--root=")) {
129
+ parsed.root = arg.slice("--root=".length);
130
+ } else if (arg === "--route-manifest") {
131
+ parsed.routeManifest = stringFlagValue(args, index, arg);
132
+ index += 1;
133
+ } else if (arg.startsWith("--route-manifest=")) {
134
+ parsed.routeManifest = arg.slice("--route-manifest=".length);
135
+ } else if (arg === "--json") {
136
+ parsed.json = true;
137
+ parsed.once = true;
138
+ } else if (arg === "--once") {
139
+ parsed.once = true;
140
+ } else if (arg === "--dry-run") {
141
+ parsed.dryRun = true;
142
+ parsed.once = true;
143
+ } else if (arg.startsWith("-")) {
144
+ throw new Error(`Unknown option: ${arg}`);
145
+ } else {
146
+ throw new Error(`Unexpected argument: ${arg}`);
147
+ }
148
+ }
149
+
150
+ if (!Number.isInteger(parsed.port) || parsed.port <= 0) {
151
+ throw new Error("--port must be a positive integer");
152
+ }
153
+ parsed.root = path.resolve(parsed.root);
154
+ parsed.url = parsed.url ? normalizeHttpUrl(parsed.url) : undefined;
155
+ return parsed;
156
+ }
157
+
158
+ function routeId(routePath: string): string {
159
+ if (routePath === "/") return "route-root";
160
+ const slug = routePath
161
+ .replace(/^\/+/, "")
162
+ .replace(/[^a-zA-Z0-9]+/g, "-")
163
+ .replace(/^-+|-+$/g, "")
164
+ .toLowerCase();
165
+ return slug ? `route-${slug}` : "route-wildcard";
166
+ }
167
+
168
+ function titleFromRoutePath(routePath: string): string {
169
+ if (routePath === "/") return "Home";
170
+ if (routePath === "/*" || routePath === "*") return "Wildcard";
171
+ return (
172
+ routePath
173
+ .replace(/^\/+/, "")
174
+ .replace(/[:$]/g, "")
175
+ .replace(/[-_/]+/g, " ")
176
+ .replace(/\s+/g, " ")
177
+ .trim()
178
+ .replace(/\b\w/g, (char) => char.toUpperCase()) || "Screen"
179
+ );
180
+ }
181
+
182
+ function walkFiles(dir: string, files: string[] = []): string[] {
183
+ if (!fsSync.existsSync(dir)) return files;
184
+ for (const entry of fsSync.readdirSync(dir, { withFileTypes: true })) {
185
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
186
+ const absolute = path.join(dir, entry.name);
187
+ if (entry.isDirectory()) {
188
+ walkFiles(absolute, files);
189
+ } else {
190
+ files.push(absolute);
191
+ }
192
+ }
193
+ return files;
194
+ }
195
+
196
+ function routePathFromReactRouterFile(filePath: string, routesDir: string) {
197
+ const withoutExt = normalizeSlash(path.relative(routesDir, filePath)).replace(
198
+ /\.[cm]?[jt]sx?$/,
199
+ "",
200
+ );
201
+ const parts: string[] = [];
202
+ for (const segment of withoutExt.split("/")) {
203
+ for (const token of segment.split(".")) {
204
+ if (!token || token === "route" || token === "index") continue;
205
+ if (token === "_index") continue;
206
+ if (token.startsWith("_")) continue;
207
+ const pathToken = token.endsWith("_") ? token.slice(0, -1) : token;
208
+ if (pathToken === "$") {
209
+ parts.push("*");
210
+ } else if (pathToken.startsWith("$")) {
211
+ const param = pathToken.slice(1) || "param";
212
+ parts.push(`:${param}`);
213
+ } else {
214
+ parts.push(pathToken);
215
+ }
216
+ }
217
+ }
218
+ return `/${parts.join("/")}`.replace(/\/+/g, "/");
219
+ }
220
+
221
+ export function discoverDesignRoutes(root: string): DesignConnectRoute[] {
222
+ const absoluteRoot = path.resolve(root);
223
+ const routeDirs = [
224
+ path.join(absoluteRoot, "app", "routes"),
225
+ path.join(absoluteRoot, "src", "routes"),
226
+ path.join(absoluteRoot, "pages"),
227
+ ].filter((dir) => fsSync.existsSync(dir));
228
+ const routes = new Map<string, DesignConnectRoute>();
229
+
230
+ for (const routeDir of routeDirs) {
231
+ for (const file of walkFiles(routeDir)) {
232
+ if (!/\.[cm]?[jt]sx?$/.test(file)) continue;
233
+ if (/\.test\.|\.spec\./.test(file)) continue;
234
+ const pathName = routePathFromReactRouterFile(file, routeDir);
235
+ routes.set(pathName, {
236
+ id: routeId(pathName),
237
+ path: pathName,
238
+ title: titleFromRoutePath(pathName),
239
+ sourceFile: normalizeSlash(path.relative(absoluteRoot, file)),
240
+ sourceKind: "react-router",
241
+ });
242
+ }
243
+ }
244
+
245
+ if (routes.size === 0) {
246
+ for (const dir of [absoluteRoot, path.join(absoluteRoot, "public")]) {
247
+ for (const file of walkFiles(dir)) {
248
+ if (!file.endsWith(".html")) continue;
249
+ const rel = normalizeSlash(path.relative(dir, file));
250
+ const pathName =
251
+ rel === "index.html" ? "/" : `/${rel.replace(/\.html$/, "")}`;
252
+ routes.set(pathName, {
253
+ id: routeId(pathName),
254
+ path: pathName,
255
+ title: titleFromRoutePath(pathName),
256
+ sourceFile: normalizeSlash(path.relative(absoluteRoot, file)),
257
+ sourceKind: "html",
258
+ });
259
+ }
260
+ }
261
+ }
262
+
263
+ return [...routes.values()].sort((a, b) => {
264
+ if (a.path === "/") return -1;
265
+ if (b.path === "/") return 1;
266
+ return a.path.localeCompare(b.path);
267
+ });
268
+ }
269
+
270
+ async function probeDevServer(url: string): Promise<boolean> {
271
+ const controller = new AbortController();
272
+ const timeout = setTimeout(() => controller.abort(), 800);
273
+ try {
274
+ const response = await fetch(url, {
275
+ method: "GET",
276
+ signal: controller.signal,
277
+ });
278
+ return response.status < 500;
279
+ } catch {
280
+ return false;
281
+ } finally {
282
+ clearTimeout(timeout);
283
+ }
284
+ }
285
+
286
+ async function resolveDevServerUrl(url?: string): Promise<string> {
287
+ if (url) return normalizeHttpUrl(url);
288
+ for (const candidate of DEFAULT_DEV_SERVER_CANDIDATES) {
289
+ if (await probeDevServer(candidate)) return candidate;
290
+ }
291
+ return DEFAULT_DEV_SERVER_CANDIDATES[0]!;
292
+ }
293
+
294
+ async function ensureRouteManifest(options: {
295
+ root: string;
296
+ routeManifestPath: string;
297
+ routes: DesignConnectRoute[];
298
+ devServerUrl: string;
299
+ dryRun: boolean;
300
+ }): Promise<{ path: string; created: boolean }> {
301
+ const manifestPath = path.isAbsolute(options.routeManifestPath)
302
+ ? options.routeManifestPath
303
+ : path.join(options.root, options.routeManifestPath);
304
+ if (fsSync.existsSync(manifestPath)) {
305
+ return { path: manifestPath, created: false };
306
+ }
307
+ if (!options.dryRun) {
308
+ await fs.mkdir(path.dirname(manifestPath), { recursive: true });
309
+ await fs.writeFile(
310
+ manifestPath,
311
+ `${JSON.stringify(
312
+ {
313
+ version: 1,
314
+ sourceType: "localhost",
315
+ devServerUrl: options.devServerUrl,
316
+ rootPath: options.root,
317
+ routes: options.routes,
318
+ generatedAt: new Date().toISOString(),
319
+ },
320
+ null,
321
+ 2,
322
+ )}\n`,
323
+ "utf8",
324
+ );
325
+ }
326
+ return { path: manifestPath, created: !options.dryRun };
327
+ }
328
+
329
+ export async function prepareDesignConnectManifest(
330
+ options: Partial<DesignConnectArgs> & { root?: string } = {},
331
+ ): Promise<DesignConnectManifest> {
332
+ const root = path.resolve(options.root ?? process.cwd());
333
+ const port = options.port ?? DEFAULT_BRIDGE_PORT;
334
+ const devServerUrl = await resolveDevServerUrl(options.url);
335
+ const bridgeUrl = `http://127.0.0.1:${port}`;
336
+ const routes = discoverDesignRoutes(root);
337
+ const routeManifest = await ensureRouteManifest({
338
+ root,
339
+ routeManifestPath: options.routeManifest ?? ROUTE_MANIFEST_FILE,
340
+ routes,
341
+ devServerUrl,
342
+ dryRun: Boolean(options.dryRun),
343
+ });
344
+ const generatedAt = new Date().toISOString();
345
+
346
+ return {
347
+ version: 1,
348
+ source: "agent-native-design-connect",
349
+ sourceType: "localhost",
350
+ localOnly: true,
351
+ devServerUrl,
352
+ bridgeUrl,
353
+ rootPath: root,
354
+ routeManifestPath: routeManifest.path,
355
+ routeManifestCreated: routeManifest.created,
356
+ routes,
357
+ routeCount: routes.length,
358
+ generatedAt,
359
+ capabilities: BRIDGE_OPERATIONS.map((operation) => ({
360
+ operation,
361
+ status:
362
+ operation === "readFile" ||
363
+ operation === "applyEdit" ||
364
+ operation === "writeFile"
365
+ ? "planned"
366
+ : "available",
367
+ reason:
368
+ operation === "writeFile"
369
+ ? "The bridge advertises the contract before enabling local file writes."
370
+ : undefined,
371
+ })),
372
+ };
373
+ }
374
+
375
+ function sendJson(
376
+ res: ServerResponse,
377
+ statusCode: number,
378
+ body: Record<string, unknown>,
379
+ ) {
380
+ res.writeHead(statusCode, {
381
+ "content-type": "application/json; charset=utf-8",
382
+ "access-control-allow-origin": "*",
383
+ "access-control-allow-methods": "GET, OPTIONS",
384
+ "access-control-allow-headers": "content-type",
385
+ "access-control-allow-private-network": "true",
386
+ });
387
+ res.end(`${JSON.stringify(body, null, 2)}\n`);
388
+ }
389
+
390
+ export async function startDesignConnectBridge(
391
+ manifest: DesignConnectManifest,
392
+ ): Promise<DesignConnectBridge> {
393
+ const server = http.createServer(
394
+ (req: IncomingMessage, res: ServerResponse) => {
395
+ if (req.method === "OPTIONS") {
396
+ sendJson(res, 204, {});
397
+ return;
398
+ }
399
+ const pathname = new URL(req.url ?? "/", manifest.bridgeUrl).pathname;
400
+ if (pathname === "/" || pathname === "/manifest.json") {
401
+ sendJson(res, 200, manifest as unknown as Record<string, unknown>);
402
+ return;
403
+ }
404
+ if (pathname === "/routes.json") {
405
+ sendJson(res, 200, {
406
+ version: 1,
407
+ sourceType: "localhost",
408
+ devServerUrl: manifest.devServerUrl,
409
+ rootPath: manifest.rootPath,
410
+ routes: manifest.routes,
411
+ generatedAt: manifest.generatedAt,
412
+ });
413
+ return;
414
+ }
415
+ if (pathname === "/health") {
416
+ sendJson(res, 200, { ok: true, source: manifest.source });
417
+ return;
418
+ }
419
+ sendJson(res, 404, { ok: false, error: "not found" });
420
+ },
421
+ );
422
+
423
+ await new Promise<void>((resolve, reject) => {
424
+ server.once("error", reject);
425
+ server.listen(new URL(manifest.bridgeUrl).port, "127.0.0.1", () => {
426
+ server.off("error", reject);
427
+ resolve();
428
+ });
429
+ });
430
+
431
+ return { server, manifest };
432
+ }
433
+
434
+ function printHelp() {
435
+ console.log(`Usage:
436
+ agent-native design connect [options]
437
+
438
+ Options:
439
+ --url <url> Dev server URL to inspect (auto-detected if omitted)
440
+ --port <number> Local bridge port (default ${DEFAULT_BRIDGE_PORT})
441
+ --root <path> App/repo root for route discovery (default cwd)
442
+ --route-manifest <path> Non-destructive route manifest output path
443
+ --json Print the manifest JSON and exit
444
+ --once Prepare/scaffold the manifest and exit
445
+ --dry-run Print what would be exposed without writing files`);
446
+ }
447
+
448
+ export async function runDesign(argv: string[]) {
449
+ const subcommand = argv[0];
450
+ if (subcommand !== "connect") {
451
+ if (
452
+ subcommand === "help" ||
453
+ subcommand === "--help" ||
454
+ subcommand === "-h"
455
+ ) {
456
+ printHelp();
457
+ return 0;
458
+ }
459
+ console.error("Usage: agent-native design connect [options]");
460
+ return 1;
461
+ }
462
+
463
+ const parsed = parseDesignConnectArgs(argv);
464
+ if (parsed.help) {
465
+ printHelp();
466
+ return 0;
467
+ }
468
+
469
+ const manifest = await prepareDesignConnectManifest(parsed);
470
+ if (parsed.json || parsed.once || parsed.dryRun) {
471
+ console.log(JSON.stringify(manifest, null, 2));
472
+ return 0;
473
+ }
474
+
475
+ const bridge = await startDesignConnectBridge(manifest);
476
+ console.error("Design localhost bridge running");
477
+ console.error(`Bridge: ${manifest.bridgeUrl}`);
478
+ console.error(`Manifest: ${manifest.bridgeUrl}/manifest.json`);
479
+ console.error(`Routes: ${manifest.routeCount}`);
480
+ console.error(`Dev URL: ${manifest.devServerUrl}`);
481
+
482
+ return await new Promise<number>((resolve) => {
483
+ const stop = () => {
484
+ bridge.server.close(() => resolve(0));
485
+ };
486
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"] as const) {
487
+ process.once(signal, stop);
488
+ }
489
+ });
490
+ }
@@ -737,6 +737,19 @@ switch (command) {
737
737
  break;
738
738
  }
739
739
 
740
+ case "design": {
741
+ import("./design-connect.js")
742
+ .then(async (m) => {
743
+ const code = await m.runDesign(args);
744
+ process.exit(code);
745
+ })
746
+ .catch((err) => {
747
+ console.error(err?.message ?? err);
748
+ process.exit(1);
749
+ });
750
+ break;
751
+ }
752
+
740
753
  case "recap": {
741
754
  // PR visual recap helpers used by the GitHub Action. Promoted to the CLI
742
755
  // so an installed repo's workflow can call `agent-native recap …` instead
@@ -925,6 +938,9 @@ Usage:
925
938
  Launch Content in local-file mode for a local
926
939
  docs/content folder. Use --no-open, --port N,
927
940
  or --profile docs/no-bookkeeping as needed.
941
+ agent-native design connect Start a localhost Design bridge for a running
942
+ dev server. Use --url, --port, --root, or
943
+ --json to print the route/source manifest.
928
944
  agent-native recap <cmd> PR visual recap setup and GitHub Action helpers.
929
945
  Run 'agent-native recap help' for subcommands.
930
946
  agent-native plan <cmd> Plan helpers for block catalogs and local files.