@agent-native/core 0.129.1 → 0.130.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 (596) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +78 -0
  3. package/corpus/core/docs/content/cloneable-saas.mdx +114 -0
  4. package/corpus/core/docs/content/creating-templates.mdx +28 -2
  5. package/corpus/core/docs/content/syncing-template-changes.mdx +7 -0
  6. package/corpus/core/docs/content/template-clips-developers.mdx +12 -5
  7. package/corpus/core/docs/content/template-dispatch-developers.mdx +1 -1
  8. package/corpus/core/docs/content/template-dispatch.mdx +1 -1
  9. package/corpus/core/package.json +1 -1
  10. package/corpus/core/src/action-ui.ts +1 -0
  11. package/corpus/core/src/action.ts +5 -1
  12. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +15 -5
  13. package/corpus/core/src/agent/harness/runner.ts +5 -0
  14. package/corpus/core/src/agent/production-agent.ts +33 -0
  15. package/corpus/core/src/agent/run-loop-with-resume.ts +5 -0
  16. package/corpus/core/src/agent/run-manager.ts +126 -1
  17. package/corpus/core/src/agent/thread-data-builder.ts +47 -2
  18. package/corpus/core/src/agent/types.ts +2 -0
  19. package/corpus/core/src/chat-threads/store.ts +4 -5
  20. package/corpus/core/src/cli/create.ts +1139 -65
  21. package/corpus/core/src/cli/design-connect.ts +3 -7
  22. package/corpus/core/src/cli/index.ts +5 -3
  23. package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +83 -47
  24. package/corpus/core/src/client/AssistantChat.tsx +27 -16
  25. package/corpus/core/src/client/agent-chat-adapter.ts +24 -0
  26. package/corpus/core/src/client/blocks/library/wireframe-kit.tsx +17 -2
  27. package/corpus/core/src/client/chat/index.ts +1 -0
  28. package/corpus/core/src/client/chat/message-components.tsx +104 -1
  29. package/corpus/core/src/client/chat/run-recovery.tsx +15 -3
  30. package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +10 -29
  31. package/corpus/core/src/client/chat/widgets/WorkspaceFileWidget.tsx +71 -0
  32. package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +22 -0
  33. package/corpus/core/src/client/chat/widgets/workspace-file-result.ts +49 -0
  34. package/corpus/core/src/client/embed-auth.ts +2 -0
  35. package/corpus/core/src/client/org/InvitationBanner.tsx +14 -1
  36. package/corpus/core/src/client/org/OrgSwitcher.tsx +23 -0
  37. package/corpus/core/src/client/org/TeamPage.tsx +130 -0
  38. package/corpus/core/src/client/org/WorkspaceNotice.tsx +85 -0
  39. package/corpus/core/src/client/org/hooks.ts +14 -0
  40. package/corpus/core/src/client/org/index.ts +2 -0
  41. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +27 -40
  42. package/corpus/core/src/client/resources/ResourcesPanel.tsx +134 -51
  43. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +7 -0
  44. package/corpus/core/src/client/resources/use-resources.ts +6 -0
  45. package/corpus/core/src/client/use-action.ts +3 -1
  46. package/corpus/core/src/client/widgets/index.ts +1 -0
  47. package/corpus/core/src/coding-tools/run-code.ts +2 -1
  48. package/corpus/core/src/db/client.ts +28 -4
  49. package/corpus/core/src/deploy/build.ts +31 -3
  50. package/corpus/core/src/eject/remote-mcp-presets.ts +1 -1
  51. package/corpus/core/src/index.browser.ts +1 -0
  52. package/corpus/core/src/index.ts +1 -0
  53. package/corpus/core/src/integrations/google-docs-poller.ts +3 -0
  54. package/corpus/core/src/integrations/webhook-handler.ts +28 -11
  55. package/corpus/core/src/jobs/scheduler.ts +4 -0
  56. package/corpus/core/src/localization/default-messages.ts +3 -2
  57. package/corpus/core/src/mcp/build-server.ts +20 -2
  58. package/corpus/core/src/observability/traces.ts +48 -12
  59. package/corpus/core/src/org/handlers.ts +52 -1
  60. package/corpus/core/src/org/migrations.ts +4 -0
  61. package/corpus/core/src/org/plugin.ts +14 -0
  62. package/corpus/core/src/org/schema.ts +1 -0
  63. package/corpus/core/src/org/types.ts +8 -0
  64. package/corpus/core/src/org/workspace-url.ts +74 -0
  65. package/corpus/core/src/resources/handlers.ts +35 -5
  66. package/corpus/core/src/scripts/runner.ts +183 -5
  67. package/corpus/core/src/server/action-routes.ts +32 -2
  68. package/corpus/core/src/server/agent-chat-plugin.ts +29 -0
  69. package/corpus/core/src/server/agent-teams.ts +10 -1
  70. package/corpus/core/src/server/auth.ts +33 -7
  71. package/corpus/core/src/server/embed-route.ts +9 -0
  72. package/corpus/core/src/server/embed-session.ts +62 -3
  73. package/corpus/core/src/server/open-route.ts +20 -6
  74. package/corpus/core/src/server/prompts/framework-core-compact.ts +1 -1
  75. package/corpus/core/src/server/prompts/framework-core.ts +1 -0
  76. package/corpus/core/src/server/request-context.ts +36 -1
  77. package/corpus/core/src/shared/embed-auth.ts +1 -0
  78. package/corpus/core/src/shared/html-document.ts +115 -0
  79. package/corpus/core/src/shared/index.ts +1 -0
  80. package/corpus/core/src/sharing/access.ts +8 -1
  81. package/corpus/core/src/sharing/registry.ts +11 -2
  82. package/corpus/core/src/workspace-files/actions.ts +100 -0
  83. package/corpus/core/src/workspace-files/tool.ts +4 -0
  84. package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +4 -0
  85. package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +9 -1
  86. package/corpus/templates/analytics/AGENTS.md +17 -24
  87. package/corpus/templates/analytics/actions/data-source-status.ts +11 -1
  88. package/corpus/templates/analytics/app/i18n-data.ts +34 -0
  89. package/corpus/templates/analytics/app/lib/data-source-status.ts +86 -0
  90. package/corpus/templates/analytics/app/lib/native-mcp-exclusions.ts +9 -0
  91. package/corpus/templates/analytics/app/pages/DataSources.tsx +184 -20
  92. package/corpus/templates/analytics/changelog/2026-07-28-native-analytics-data-sources-no-longer-show-duplicate-mc.md +6 -0
  93. package/corpus/templates/analytics/changelog/2026-07-29-exports-now-appear-in-chat-with-a-direct-download-instead-of.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-29-queued-chat-prompts-no-longer-resend-after-analytics-navigat.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-07-29-scheduled-dashboard-emails-load-every-panel-reliably-without.md +6 -0
  96. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +6 -3
  97. package/corpus/templates/analytics/server/lib/credential-keys.ts +1 -1
  98. package/corpus/templates/analytics/server/lib/hubspot.ts +1 -1
  99. package/corpus/templates/analytics/server/lib/provider-credentials.ts +55 -1
  100. package/corpus/templates/analytics/server/plugins/agent-chat.ts +123 -27
  101. package/corpus/templates/analytics/server/routes/[...page].get.ts +2 -7
  102. package/corpus/templates/analytics/vite.config.ts +7 -0
  103. package/corpus/templates/brain/actions/list-connection-providers.ts +100 -2
  104. package/corpus/templates/brain/app/lib/brain.ts +10 -0
  105. package/corpus/templates/brain/app/routes/sources.tsx +15 -4
  106. package/corpus/templates/brain/changelog/2026-07-29-brain-automatically-retries-failed-source-syncs-and-guides-y.md +6 -0
  107. package/corpus/templates/brain/jobs/process-ingest-queue.ts +13 -0
  108. package/corpus/templates/brain/server/jobs/sync-sources.ts +27 -22
  109. package/corpus/templates/brain/server/plugins/agent-chat.ts +2 -1
  110. package/corpus/templates/brain/server/routes/api/brain/queue/run.post.ts +7 -1
  111. package/corpus/templates/clips/AGENTS.md +1 -1
  112. package/corpus/templates/clips/actions/create-recording-agent-link.ts +11 -1
  113. package/corpus/templates/clips/actions/update-comment.ts +68 -0
  114. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +0 -1
  115. package/corpus/templates/clips/app/components/player/comments-panel.tsx +221 -65
  116. package/corpus/templates/clips/app/components/player/video-player.tsx +101 -27
  117. package/corpus/templates/clips/app/i18n/en-US.ts +2 -1
  118. package/corpus/templates/clips/app/routes/bug-report.done.tsx +48 -27
  119. package/corpus/templates/clips/app/routes/bug-report.tsx +43 -4
  120. package/corpus/templates/clips/app/routes/record.tsx +2 -0
  121. package/corpus/templates/clips/changelog/2026-07-29-clip-playback-now-recovers-instead-of-getting-stuck-when-a-b.md +6 -0
  122. package/corpus/templates/clips/changelog/2026-07-29-comments-can-now-be-edited-after-posting.md +6 -0
  123. package/corpus/templates/clips/changelog/2026-07-29-download-actions-now-use-a-shorter-clearer-label.md +6 -0
  124. package/corpus/templates/clips/changelog/2026-07-29-embedded-bug-reports-now-return-a-temporary-agent-readable.md +6 -0
  125. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
  126. package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +21 -1
  127. package/corpus/templates/clips/shared/bug-report.ts +99 -0
  128. package/corpus/templates/content/actions/_content-database-personal-view.ts +7 -1
  129. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +5 -2
  130. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +20 -8
  131. package/corpus/templates/content/changelog/2026-07-29-missing-databases-no-longer-trigger-repeated-personal-view-e.md +6 -0
  132. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +83 -47
  133. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +474 -55
  134. package/corpus/templates/design/.generated/bridge/embedded-wheel.generated.ts +3 -0
  135. package/corpus/templates/design/.generated/bridge/hit-test.generated.ts +18 -1
  136. package/corpus/templates/design/.generated/bridge/source-location.generated.ts +348 -0
  137. package/corpus/templates/design/actions/add-localhost-screens.ts +2 -7
  138. package/corpus/templates/design/actions/apply-visual-edit.ts +7 -1
  139. package/corpus/templates/design/actions/connect-localhost.ts +5 -9
  140. package/corpus/templates/design/actions/create-component.ts +16 -13
  141. package/corpus/templates/design/actions/grant-localhost-write-consent.ts +2 -7
  142. package/corpus/templates/design/actions/list-design-source-capabilities.ts +4 -7
  143. package/corpus/templates/design/actions/list-local-files.ts +26 -50
  144. package/corpus/templates/design/actions/list-localhost-connections.ts +2 -7
  145. package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +2 -2
  146. package/corpus/templates/design/actions/open-visual-edit.ts +234 -135
  147. package/corpus/templates/design/actions/read-local-file.ts +26 -50
  148. package/corpus/templates/design/actions/request-localhost-write-consent.ts +2 -7
  149. package/corpus/templates/design/actions/write-local-file.ts +31 -73
  150. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +307 -133
  151. package/corpus/templates/design/app/components/design/EditPanel.tsx +94 -22
  152. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +137 -60
  153. package/corpus/templates/design/app/components/design/ResponsiveInteractBar.tsx +75 -14
  154. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +755 -97
  155. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +8 -0
  156. package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +24 -1
  157. package/corpus/templates/design/app/components/design/bridge/source-location.bridge.ts +530 -0
  158. package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbenchLoader.tsx +278 -0
  159. package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +32 -12
  160. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-setup.ts +14 -3
  161. package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +87 -24
  162. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +36 -0
  163. package/corpus/templates/design/app/components/design/code-workbench/store.tsx +2 -1
  164. package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +48 -8
  165. package/corpus/templates/design/app/components/design/design-canvas/content-size-report.ts +3 -13
  166. package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +4 -2
  167. package/corpus/templates/design/app/components/design/design-canvas/hit-test.ts +3 -13
  168. package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +3 -1
  169. package/corpus/templates/design/app/components/design/edit-panel/inspect-code-source.ts +93 -0
  170. package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +4 -2
  171. package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +35 -0
  172. package/corpus/templates/design/app/components/design/multi-screen/iframe-targeting.ts +24 -0
  173. package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -0
  174. package/corpus/templates/design/app/components/design/types.ts +29 -0
  175. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -4
  176. package/corpus/templates/design/app/hooks/use-navigation-state.ts +3 -0
  177. package/corpus/templates/design/app/i18n-data.ts +153 -46
  178. package/corpus/templates/design/app/i18n-responsive-interact.ts +12 -12
  179. package/corpus/templates/design/app/lib/design-editor-route.ts +23 -0
  180. package/corpus/templates/design/app/pages/VisualEdit.tsx +19 -6
  181. package/corpus/templates/design/app/pages/design-editor/action-error.ts +19 -0
  182. package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +29 -0
  183. package/corpus/templates/design/app/pages/design-editor/clone-and-pen-edit.ts +6 -0
  184. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +277 -15
  185. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +75 -9
  186. package/corpus/templates/design/app/pages/design-editor/layer-state-scope.ts +28 -0
  187. package/corpus/templates/design/app/pages/design-editor/live-screen-layer-drop.ts +41 -0
  188. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +496 -41
  189. package/corpus/templates/design/app/pages/design-editor/pending-live-edit-unload-guard.ts +27 -0
  190. package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +10 -0
  191. package/corpus/templates/design/app/pages/design-editor/react-semantic-handoff.ts +168 -9
  192. package/corpus/templates/design/app/pages/design-editor/responsive-interact.ts +41 -3
  193. package/corpus/templates/design/app/pages/design-editor/screen-command-utils.ts +5 -0
  194. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +42 -13
  195. package/corpus/templates/design/app/pages/design-editor/source-location.ts +180 -0
  196. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +17 -0
  197. package/corpus/templates/design/app/public-routes.ts +1 -0
  198. package/corpus/templates/design/app/routes/visual-edit.$id.tsx +15 -0
  199. package/corpus/templates/design/changelog/2026-06-29-screen-overview-is-easier-to-find-and-named-screens-open-dir.md +1 -1
  200. package/corpus/templates/design/changelog/2026-07-28-deleting-a-selected-element-now-removes-it-from-the-live-pre.md +6 -0
  201. package/corpus/templates/design/changelog/2026-07-28-deleting-an-element-on-a-connected-localhost-screen-now-queu.md +6 -0
  202. package/corpus/templates/design/changelog/2026-07-28-interact-mode-now-shows-a-responsive-device-preview-with-pre.md +6 -0
  203. package/corpus/templates/design/changelog/2026-07-28-layer-hide-and-lock-now-apply-to-the-live-preview-instead-of.md +6 -0
  204. package/corpus/templates/design/changelog/2026-07-28-layers-panel-selections-on-a-connected-localhost-screen-can-.md +6 -0
  205. package/corpus/templates/design/changelog/2026-07-28-locked-layers-now-show-a-subtle-dashed-outline-in-the-live-p.md +6 -0
  206. package/corpus/templates/design/changelog/2026-07-28-the-apply-design-updates-button-now-counts-pending-live-text.md +6 -0
  207. package/corpus/templates/design/changelog/2026-07-28-the-design-canvas-no-longer-stalls-on-a-render-loop-while-a-.md +6 -0
  208. package/corpus/templates/design/changelog/2026-07-28-visual-edit-on-a-local-dev-server-no-longer-requires-signing.md +6 -0
  209. package/corpus/templates/design/changelog/2026-07-28-visual-edits-on-a-react-19-app-no-longer-report-a-source-lin.md +6 -0
  210. package/corpus/templates/design/changelog/2026-07-29-an-edit-that-cannot-be-written-to-source-now-names-the-reaso.md +6 -0
  211. package/corpus/templates/design/changelog/2026-07-29-applying-a-primitive-dropped-onto-a-connected-localhost-scre.md +6 -0
  212. package/corpus/templates/design/changelog/2026-07-29-changing-a-style-in-the-inspector-now-updates-a-connected-lo.md +6 -0
  213. package/corpus/templates/design/changelog/2026-07-29-choosing-edit-or-annotate-from-a-focused-screen-now-returns-.md +6 -0
  214. package/corpus/templates/design/changelog/2026-07-29-concurrent-source-edits-now-return-a-clear-conflict-response.md +6 -0
  215. package/corpus/templates/design/changelog/2026-07-29-creating-a-component-from-an-element-that-repeats-in-the-sou.md +6 -0
  216. package/corpus/templates/design/changelog/2026-07-29-deleting-an-element-you-just-dropped-onto-a-live-screen-no-l.md +6 -0
  217. package/corpus/templates/design/changelog/2026-07-29-dragging-a-layer-across-screens-no-longer-dies-when-the-poin.md +6 -0
  218. package/corpus/templates/design/changelog/2026-07-29-dragging-an-element-from-a-stored-screen-into-a-live-localho.md +6 -0
  219. package/corpus/templates/design/changelog/2026-07-29-drawing-a-box-on-the-canvas-and-dragging-it-into-a-connected.md +6 -0
  220. package/corpus/templates/design/changelog/2026-07-29-fixed-a-loading-screen-flicker-when-reopening-designs-with-a.md +6 -0
  221. package/corpus/templates/design/changelog/2026-07-29-interact-mode-has-edit-and-annotate-buttons-again-so-you-can.md +6 -0
  222. package/corpus/templates/design/changelog/2026-07-29-layer-groups-can-be-dropped-onto-live-localhost-screens.md +6 -0
  223. package/corpus/templates/design/changelog/2026-07-29-localhost-source-errors-now-say-what-actually-went-wrong-whi.md +6 -0
  224. package/corpus/templates/design/changelog/2026-07-29-opening-or-refreshing-a-live-localhost-screen-in-single-scre.md +6 -0
  225. package/corpus/templates/design/changelog/2026-07-29-redo-after-undoing-a-drop-onto-a-live-screen-puts-the-elemen.md +6 -0
  226. package/corpus/templates/design/changelog/2026-07-29-shapes-can-be-drawn-directly-onto-live-localhost-screens.md +6 -0
  227. package/corpus/templates/design/changelog/2026-07-29-shapes-drawn-on-the-canvas-board-now-appear-immediately-inst.md +6 -0
  228. package/corpus/templates/design/changelog/2026-07-29-style-edits-on-a-running-localhost-screen-now-preview-live-a.md +6 -0
  229. package/corpus/templates/design/changelog/2026-07-29-the-apply-design-updates-control-now-appears-as-a-clean-conn.md +6 -0
  230. package/corpus/templates/design/changelog/2026-07-29-visual-edits-on-a-mapped-component-instance-now-tell-the-age.md +6 -0
  231. package/corpus/templates/design/server/lib/design-data-access.ts +21 -7
  232. package/corpus/templates/design/server/lib/localhost-connection.ts +240 -0
  233. package/corpus/templates/design/server/routes/[...page].get.ts +2 -5
  234. package/corpus/templates/design/server/source-workspace.ts +2 -0
  235. package/corpus/templates/design/shared/code-layer.ts +43 -0
  236. package/corpus/templates/design/shared/html-content.ts +26 -0
  237. package/corpus/templates/design/shared/html-integrity.ts +21 -1
  238. package/corpus/templates/design/shared/local-jsx-visual-edit.ts +15 -0
  239. package/corpus/templates/design/shared/source-mode.ts +76 -0
  240. package/corpus/templates/dispatch/changelog/2026-07-29-workspace-members-without-admin-access-now-see-a-clear-permi.md +6 -0
  241. package/corpus/templates/dispatch/server/lib/usage-metrics.ts +2 -1
  242. package/corpus/templates/plan/app/lib/plan-annotation-runtime.ts +3 -4
  243. package/corpus/templates/plan/server/routes/[...page].get.ts +2 -5
  244. package/corpus/templates/slides/actions/patch-deck.ts +29 -17
  245. package/corpus/toolkit/CHANGELOG.md +6 -0
  246. package/corpus/toolkit/package.json +1 -1
  247. package/corpus/toolkit/src/composer/ComposerPlusMenu.tsx +3 -2
  248. package/dist/action-ui.d.ts +1 -0
  249. package/dist/action-ui.d.ts.map +1 -1
  250. package/dist/action-ui.js +1 -0
  251. package/dist/action-ui.js.map +1 -1
  252. package/dist/action.d.ts +5 -1
  253. package/dist/action.d.ts.map +1 -1
  254. package/dist/action.js.map +1 -1
  255. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  256. package/dist/agent/engine/ai-sdk-engine.js +13 -5
  257. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  258. package/dist/agent/harness/runner.d.ts.map +1 -1
  259. package/dist/agent/harness/runner.js +5 -0
  260. package/dist/agent/harness/runner.js.map +1 -1
  261. package/dist/agent/production-agent.d.ts +16 -0
  262. package/dist/agent/production-agent.d.ts.map +1 -1
  263. package/dist/agent/production-agent.js +18 -1
  264. package/dist/agent/production-agent.js.map +1 -1
  265. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  266. package/dist/agent/run-loop-with-resume.js +6 -0
  267. package/dist/agent/run-loop-with-resume.js.map +1 -1
  268. package/dist/agent/run-manager.d.ts +14 -0
  269. package/dist/agent/run-manager.d.ts.map +1 -1
  270. package/dist/agent/run-manager.js +91 -1
  271. package/dist/agent/run-manager.js.map +1 -1
  272. package/dist/agent/thread-data-builder.d.ts +3 -0
  273. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  274. package/dist/agent/thread-data-builder.js +35 -3
  275. package/dist/agent/thread-data-builder.js.map +1 -1
  276. package/dist/agent/types.d.ts +2 -0
  277. package/dist/agent/types.d.ts.map +1 -1
  278. package/dist/agent/types.js.map +1 -1
  279. package/dist/chat-threads/store.d.ts.map +1 -1
  280. package/dist/chat-threads/store.js +4 -6
  281. package/dist/chat-threads/store.js.map +1 -1
  282. package/dist/cli/create.d.ts +66 -6
  283. package/dist/cli/create.d.ts.map +1 -1
  284. package/dist/cli/create.js +765 -66
  285. package/dist/cli/create.js.map +1 -1
  286. package/dist/cli/design-connect.d.ts.map +1 -1
  287. package/dist/cli/design-connect.js +2 -7
  288. package/dist/cli/design-connect.js.map +1 -1
  289. package/dist/cli/index.js +5 -3
  290. package/dist/cli/index.js.map +1 -1
  291. package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
  292. package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
  293. package/dist/cli/skills-content/design-visual-edit-skill.js +83 -47
  294. package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
  295. package/dist/client/AssistantChat.d.ts.map +1 -1
  296. package/dist/client/AssistantChat.js +16 -9
  297. package/dist/client/AssistantChat.js.map +1 -1
  298. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  299. package/dist/client/agent-chat-adapter.js +21 -0
  300. package/dist/client/agent-chat-adapter.js.map +1 -1
  301. package/dist/client/blocks/library/wireframe-kit.d.ts +2 -0
  302. package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
  303. package/dist/client/blocks/library/wireframe-kit.js +8 -2
  304. package/dist/client/blocks/library/wireframe-kit.js.map +1 -1
  305. package/dist/client/chat/index.d.ts +1 -1
  306. package/dist/client/chat/index.d.ts.map +1 -1
  307. package/dist/client/chat/index.js +1 -1
  308. package/dist/client/chat/index.js.map +1 -1
  309. package/dist/client/chat/message-components.d.ts +17 -0
  310. package/dist/client/chat/message-components.d.ts.map +1 -1
  311. package/dist/client/chat/message-components.js +24 -2
  312. package/dist/client/chat/message-components.js.map +1 -1
  313. package/dist/client/chat/run-recovery.d.ts +6 -0
  314. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  315. package/dist/client/chat/run-recovery.js +13 -3
  316. package/dist/client/chat/run-recovery.js.map +1 -1
  317. package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
  318. package/dist/client/chat/widgets/DataTableWidget.js +2 -3
  319. package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
  320. package/dist/client/chat/widgets/WorkspaceFileWidget.d.ts +5 -0
  321. package/dist/client/chat/widgets/WorkspaceFileWidget.d.ts.map +1 -0
  322. package/dist/client/chat/widgets/WorkspaceFileWidget.js +34 -0
  323. package/dist/client/chat/widgets/WorkspaceFileWidget.js.map +1 -0
  324. package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
  325. package/dist/client/chat/widgets/builtin-tool-renderers.js +13 -1
  326. package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
  327. package/dist/client/chat/widgets/workspace-file-result.d.ts +12 -0
  328. package/dist/client/chat/widgets/workspace-file-result.d.ts.map +1 -0
  329. package/dist/client/chat/widgets/workspace-file-result.js +34 -0
  330. package/dist/client/chat/widgets/workspace-file-result.js.map +1 -0
  331. package/dist/client/embed-auth.d.ts.map +1 -1
  332. package/dist/client/embed-auth.js +2 -1
  333. package/dist/client/embed-auth.js.map +1 -1
  334. package/dist/client/org/InvitationBanner.d.ts +5 -2
  335. package/dist/client/org/InvitationBanner.d.ts.map +1 -1
  336. package/dist/client/org/InvitationBanner.js +9 -2
  337. package/dist/client/org/InvitationBanner.js.map +1 -1
  338. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  339. package/dist/client/org/OrgSwitcher.js +3 -2
  340. package/dist/client/org/OrgSwitcher.js.map +1 -1
  341. package/dist/client/org/TeamPage.d.ts.map +1 -1
  342. package/dist/client/org/TeamPage.js +27 -3
  343. package/dist/client/org/TeamPage.js.map +1 -1
  344. package/dist/client/org/WorkspaceNotice.d.ts +18 -0
  345. package/dist/client/org/WorkspaceNotice.d.ts.map +1 -0
  346. package/dist/client/org/WorkspaceNotice.js +56 -0
  347. package/dist/client/org/WorkspaceNotice.js.map +1 -0
  348. package/dist/client/org/hooks.d.ts +1 -0
  349. package/dist/client/org/hooks.d.ts.map +1 -1
  350. package/dist/client/org/hooks.js +12 -0
  351. package/dist/client/org/hooks.js.map +1 -1
  352. package/dist/client/org/index.d.ts +2 -1
  353. package/dist/client/org/index.d.ts.map +1 -1
  354. package/dist/client/org/index.js +2 -1
  355. package/dist/client/org/index.js.map +1 -1
  356. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  357. package/dist/client/resources/McpIntegrationDialog.js +8 -12
  358. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  359. package/dist/client/resources/ResourcesPanel.d.ts +3 -0
  360. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  361. package/dist/client/resources/ResourcesPanel.js +49 -20
  362. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  363. package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
  364. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  365. package/dist/client/resources/mcp-integration-catalog.js +3 -0
  366. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  367. package/dist/client/resources/use-resources.d.ts +1 -0
  368. package/dist/client/resources/use-resources.d.ts.map +1 -1
  369. package/dist/client/resources/use-resources.js +3 -0
  370. package/dist/client/resources/use-resources.js.map +1 -1
  371. package/dist/client/use-action.d.ts +3 -1
  372. package/dist/client/use-action.d.ts.map +1 -1
  373. package/dist/client/use-action.js +3 -1
  374. package/dist/client/use-action.js.map +1 -1
  375. package/dist/client/widgets/index.d.ts +1 -1
  376. package/dist/client/widgets/index.d.ts.map +1 -1
  377. package/dist/client/widgets/index.js +1 -1
  378. package/dist/client/widgets/index.js.map +1 -1
  379. package/dist/coding-tools/run-code.js +2 -1
  380. package/dist/coding-tools/run-code.js.map +1 -1
  381. package/dist/collab/awareness.d.ts +2 -2
  382. package/dist/collab/awareness.d.ts.map +1 -1
  383. package/dist/collab/routes.d.ts +1 -1
  384. package/dist/db/client.d.ts +1 -0
  385. package/dist/db/client.d.ts.map +1 -1
  386. package/dist/db/client.js +24 -3
  387. package/dist/db/client.js.map +1 -1
  388. package/dist/deploy/build.d.ts.map +1 -1
  389. package/dist/deploy/build.js +25 -3
  390. package/dist/deploy/build.js.map +1 -1
  391. package/dist/eject/remote-mcp-presets.js +1 -1
  392. package/dist/eject/remote-mcp-presets.js.map +1 -1
  393. package/dist/index.browser.d.ts +1 -1
  394. package/dist/index.browser.d.ts.map +1 -1
  395. package/dist/index.browser.js +1 -1
  396. package/dist/index.browser.js.map +1 -1
  397. package/dist/index.d.ts +1 -1
  398. package/dist/index.d.ts.map +1 -1
  399. package/dist/index.js +1 -1
  400. package/dist/index.js.map +1 -1
  401. package/dist/integrations/google-docs-poller.d.ts.map +1 -1
  402. package/dist/integrations/google-docs-poller.js +4 -1
  403. package/dist/integrations/google-docs-poller.js.map +1 -1
  404. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  405. package/dist/integrations/webhook-handler.js +23 -11
  406. package/dist/integrations/webhook-handler.js.map +1 -1
  407. package/dist/jobs/scheduler.js +4 -0
  408. package/dist/jobs/scheduler.js.map +1 -1
  409. package/dist/localization/default-messages.d.ts +3 -2
  410. package/dist/localization/default-messages.d.ts.map +1 -1
  411. package/dist/localization/default-messages.js +3 -2
  412. package/dist/localization/default-messages.js.map +1 -1
  413. package/dist/mcp/build-server.d.ts.map +1 -1
  414. package/dist/mcp/build-server.js +10 -1
  415. package/dist/mcp/build-server.js.map +1 -1
  416. package/dist/notifications/routes.d.ts +1 -1
  417. package/dist/observability/traces.d.ts.map +1 -1
  418. package/dist/observability/traces.js +27 -7
  419. package/dist/observability/traces.js.map +1 -1
  420. package/dist/org/handlers.d.ts +15 -0
  421. package/dist/org/handlers.d.ts.map +1 -1
  422. package/dist/org/handlers.js +45 -1
  423. package/dist/org/handlers.js.map +1 -1
  424. package/dist/org/migrations.d.ts.map +1 -1
  425. package/dist/org/migrations.js +4 -0
  426. package/dist/org/migrations.js.map +1 -1
  427. package/dist/org/plugin.d.ts +1 -0
  428. package/dist/org/plugin.d.ts.map +1 -1
  429. package/dist/org/plugin.js +10 -1
  430. package/dist/org/plugin.js.map +1 -1
  431. package/dist/org/schema.d.ts +19 -0
  432. package/dist/org/schema.d.ts.map +1 -1
  433. package/dist/org/schema.js +1 -0
  434. package/dist/org/schema.js.map +1 -1
  435. package/dist/org/types.d.ts +8 -0
  436. package/dist/org/types.d.ts.map +1 -1
  437. package/dist/org/types.js.map +1 -1
  438. package/dist/org/workspace-url.d.ts +32 -0
  439. package/dist/org/workspace-url.d.ts.map +1 -0
  440. package/dist/org/workspace-url.js +63 -0
  441. package/dist/org/workspace-url.js.map +1 -0
  442. package/dist/progress/routes.d.ts +1 -1
  443. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  444. package/dist/provider-api/actions/provider-api.d.ts +7 -7
  445. package/dist/resources/handlers.d.ts +2 -3
  446. package/dist/resources/handlers.d.ts.map +1 -1
  447. package/dist/resources/handlers.js +25 -5
  448. package/dist/resources/handlers.js.map +1 -1
  449. package/dist/scripts/runner.d.ts +17 -0
  450. package/dist/scripts/runner.d.ts.map +1 -1
  451. package/dist/scripts/runner.js +130 -5
  452. package/dist/scripts/runner.js.map +1 -1
  453. package/dist/secrets/routes.d.ts +9 -9
  454. package/dist/server/action-routes.d.ts.map +1 -1
  455. package/dist/server/action-routes.js +24 -2
  456. package/dist/server/action-routes.js.map +1 -1
  457. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  458. package/dist/server/agent-chat-plugin.js +26 -1
  459. package/dist/server/agent-chat-plugin.js.map +1 -1
  460. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  461. package/dist/server/agent-teams.d.ts.map +1 -1
  462. package/dist/server/agent-teams.js +10 -1
  463. package/dist/server/agent-teams.js.map +1 -1
  464. package/dist/server/auth.d.ts +22 -0
  465. package/dist/server/auth.d.ts.map +1 -1
  466. package/dist/server/auth.js +33 -7
  467. package/dist/server/auth.js.map +1 -1
  468. package/dist/server/embed-route.d.ts.map +1 -1
  469. package/dist/server/embed-route.js +6 -1
  470. package/dist/server/embed-route.js.map +1 -1
  471. package/dist/server/embed-session.d.ts +7 -0
  472. package/dist/server/embed-session.d.ts.map +1 -1
  473. package/dist/server/embed-session.js +46 -4
  474. package/dist/server/embed-session.js.map +1 -1
  475. package/dist/server/open-route.d.ts.map +1 -1
  476. package/dist/server/open-route.js +17 -7
  477. package/dist/server/open-route.js.map +1 -1
  478. package/dist/server/prompts/framework-core-compact.js +1 -1
  479. package/dist/server/prompts/framework-core-compact.js.map +1 -1
  480. package/dist/server/prompts/framework-core.d.ts.map +1 -1
  481. package/dist/server/prompts/framework-core.js +1 -0
  482. package/dist/server/prompts/framework-core.js.map +1 -1
  483. package/dist/server/request-context.d.ts +26 -0
  484. package/dist/server/request-context.d.ts.map +1 -1
  485. package/dist/server/request-context.js +18 -1
  486. package/dist/server/request-context.js.map +1 -1
  487. package/dist/shared/embed-auth.d.ts +1 -0
  488. package/dist/shared/embed-auth.d.ts.map +1 -1
  489. package/dist/shared/embed-auth.js +1 -0
  490. package/dist/shared/embed-auth.js.map +1 -1
  491. package/dist/shared/html-document.d.ts +12 -0
  492. package/dist/shared/html-document.d.ts.map +1 -0
  493. package/dist/shared/html-document.js +92 -0
  494. package/dist/shared/html-document.js.map +1 -0
  495. package/dist/shared/index.d.ts +1 -0
  496. package/dist/shared/index.d.ts.map +1 -1
  497. package/dist/shared/index.js +1 -0
  498. package/dist/shared/index.js.map +1 -1
  499. package/dist/sharing/access.d.ts +1 -0
  500. package/dist/sharing/access.d.ts.map +1 -1
  501. package/dist/sharing/access.js +8 -2
  502. package/dist/sharing/access.js.map +1 -1
  503. package/dist/sharing/registry.d.ts +3 -0
  504. package/dist/sharing/registry.d.ts.map +1 -1
  505. package/dist/sharing/registry.js.map +1 -1
  506. package/dist/workspace-files/actions.d.ts +28 -0
  507. package/dist/workspace-files/actions.d.ts.map +1 -0
  508. package/dist/workspace-files/actions.js +75 -0
  509. package/dist/workspace-files/actions.js.map +1 -0
  510. package/dist/workspace-files/tool.d.ts.map +1 -1
  511. package/dist/workspace-files/tool.js +4 -0
  512. package/dist/workspace-files/tool.js.map +1 -1
  513. package/docs/content/cloneable-saas.mdx +114 -0
  514. package/docs/content/creating-templates.mdx +28 -2
  515. package/docs/content/syncing-template-changes.mdx +7 -0
  516. package/docs/content/template-clips-developers.mdx +12 -5
  517. package/docs/content/template-dispatch-developers.mdx +1 -1
  518. package/docs/content/template-dispatch.mdx +1 -1
  519. package/package.json +2 -2
  520. package/src/action-ui.ts +1 -0
  521. package/src/action.ts +5 -1
  522. package/src/agent/engine/ai-sdk-engine.ts +15 -5
  523. package/src/agent/harness/runner.ts +5 -0
  524. package/src/agent/production-agent.ts +33 -0
  525. package/src/agent/run-loop-with-resume.ts +5 -0
  526. package/src/agent/run-manager.ts +126 -1
  527. package/src/agent/thread-data-builder.ts +47 -2
  528. package/src/agent/types.ts +2 -0
  529. package/src/chat-threads/store.ts +4 -5
  530. package/src/cli/create.ts +1139 -65
  531. package/src/cli/design-connect.ts +3 -7
  532. package/src/cli/index.ts +5 -3
  533. package/src/cli/skills-content/design-visual-edit-skill.ts +83 -47
  534. package/src/client/AssistantChat.tsx +27 -16
  535. package/src/client/agent-chat-adapter.ts +24 -0
  536. package/src/client/blocks/library/wireframe-kit.tsx +17 -2
  537. package/src/client/chat/index.ts +1 -0
  538. package/src/client/chat/message-components.tsx +104 -1
  539. package/src/client/chat/run-recovery.tsx +15 -3
  540. package/src/client/chat/widgets/DataTableWidget.tsx +10 -29
  541. package/src/client/chat/widgets/WorkspaceFileWidget.tsx +71 -0
  542. package/src/client/chat/widgets/builtin-tool-renderers.tsx +22 -0
  543. package/src/client/chat/widgets/workspace-file-result.ts +49 -0
  544. package/src/client/embed-auth.ts +2 -0
  545. package/src/client/org/InvitationBanner.tsx +14 -1
  546. package/src/client/org/OrgSwitcher.tsx +23 -0
  547. package/src/client/org/TeamPage.tsx +130 -0
  548. package/src/client/org/WorkspaceNotice.tsx +85 -0
  549. package/src/client/org/hooks.ts +14 -0
  550. package/src/client/org/index.ts +2 -0
  551. package/src/client/resources/McpIntegrationDialog.tsx +27 -40
  552. package/src/client/resources/ResourcesPanel.tsx +134 -51
  553. package/src/client/resources/mcp-integration-catalog.ts +7 -0
  554. package/src/client/resources/use-resources.ts +6 -0
  555. package/src/client/use-action.ts +3 -1
  556. package/src/client/widgets/index.ts +1 -0
  557. package/src/coding-tools/run-code.ts +2 -1
  558. package/src/db/client.ts +28 -4
  559. package/src/deploy/build.ts +31 -3
  560. package/src/eject/remote-mcp-presets.ts +1 -1
  561. package/src/index.browser.ts +1 -0
  562. package/src/index.ts +1 -0
  563. package/src/integrations/google-docs-poller.ts +3 -0
  564. package/src/integrations/webhook-handler.ts +28 -11
  565. package/src/jobs/scheduler.ts +4 -0
  566. package/src/localization/default-messages.ts +3 -2
  567. package/src/mcp/build-server.ts +20 -2
  568. package/src/observability/traces.ts +48 -12
  569. package/src/org/handlers.ts +52 -1
  570. package/src/org/migrations.ts +4 -0
  571. package/src/org/plugin.ts +14 -0
  572. package/src/org/schema.ts +1 -0
  573. package/src/org/types.ts +8 -0
  574. package/src/org/workspace-url.ts +74 -0
  575. package/src/resources/handlers.ts +35 -5
  576. package/src/scripts/runner.ts +183 -5
  577. package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +2 -1
  578. package/src/server/action-routes.ts +32 -2
  579. package/src/server/agent-chat-plugin.ts +29 -0
  580. package/src/server/agent-teams.ts +10 -1
  581. package/src/server/auth.ts +33 -7
  582. package/src/server/embed-route.ts +9 -0
  583. package/src/server/embed-session.ts +62 -3
  584. package/src/server/open-route.ts +20 -6
  585. package/src/server/prompts/framework-core-compact.ts +1 -1
  586. package/src/server/prompts/framework-core.ts +1 -0
  587. package/src/server/request-context.ts +36 -1
  588. package/src/shared/embed-auth.ts +1 -0
  589. package/src/shared/html-document.ts +115 -0
  590. package/src/shared/index.ts +1 -0
  591. package/src/sharing/access.ts +8 -1
  592. package/src/sharing/registry.ts +11 -2
  593. package/src/workspace-files/actions.ts +100 -0
  594. package/src/workspace-files/tool.ts +4 -0
  595. package/corpus/templates/design/changelog/2026-07-28-interact-mode-can-preview-designs-in-responsive-device-sizes.md +0 -6
  596. package/corpus/templates/design/changelog/2026-07-28-interact-mode-now-opens-a-full-screen-responsive-preview-wit.md +0 -6
@@ -6,22 +6,26 @@
6
6
  * grant (reads do not require user write consent, only editor access + a
7
7
  * valid bridge connection):
8
8
  * 1. assertAccess: the caller must have editor access to the design.
9
- * 2. Bridge URL resolution: only the current user's own connection row.
9
+ * 2. Bridge URL resolution: only the current user's own connection row, in
10
+ * the caller's own org scope. A miss throws a classified 4xx from
11
+ * server/lib/localhost-connection.ts so the client sees the actual
12
+ * condition instead of a generic 500.
10
13
  * 3. Loopback check: bridgeUrl must resolve to localhost/127.0.0.1.
11
14
  * 4. Bridge token: the connection's stored bridge token is sent as
12
15
  * X-Bridge-Token so the bridge can reject unauthorized callers.
13
16
  */
14
17
 
15
18
  import { defineAction } from "@agent-native/core";
16
- import {
17
- getRequestOrgId,
18
- getRequestUserEmail,
19
- } from "@agent-native/core/server/request-context";
20
19
  import { assertAccess } from "@agent-native/core/sharing";
21
- import { and, eq, isNull } from "drizzle-orm";
22
20
  import { z } from "zod";
23
21
 
24
- import { getDb, schema } from "../server/db/index.js";
22
+ import {
23
+ fetchLocalhostBridge,
24
+ localhostBridgeRequestError,
25
+ requireLocalhostBridgeToken,
26
+ resolveLocalhostBridgeConnection,
27
+ resolveLocalhostConnectionScope,
28
+ } from "../server/lib/localhost-connection.js";
25
29
 
26
30
  function isLoopbackHostname(hostname: string): boolean {
27
31
  const normalized = hostname.toLowerCase();
@@ -77,53 +81,25 @@ export default defineAction({
77
81
  run: async ({ designId, connectionId }) => {
78
82
  await assertAccess("design", designId, "editor");
79
83
 
80
- const ownerEmail = getRequestUserEmail();
81
- if (!ownerEmail) throw new Error("no authenticated user");
82
- const orgId = getRequestOrgId() ?? null;
83
-
84
- const db = getDb();
85
- const [connection] = await db
86
- .select({
87
- bridgeUrl: schema.designLocalhostConnections.bridgeUrl,
88
- bridgeToken: schema.designLocalhostConnections.bridgeToken,
89
- })
90
- .from(schema.designLocalhostConnections)
91
- .where(
92
- and(
93
- eq(schema.designLocalhostConnections.id, connectionId),
94
- eq(schema.designLocalhostConnections.ownerEmail, ownerEmail),
95
- orgId
96
- ? eq(schema.designLocalhostConnections.orgId, orgId)
97
- : isNull(schema.designLocalhostConnections.orgId),
98
- ),
99
- )
100
- .limit(1);
101
-
102
- if (!connection?.bridgeUrl) {
103
- throw new Error(
104
- `No bridge URL found for connection "${connectionId}". ` +
105
- "Ensure the design bridge is running (npx @agent-native/core@latest design connect).",
106
- );
107
- }
108
- if (!connection.bridgeToken) {
109
- throw new Error(
110
- `No bridge token found for connection "${connectionId}". ` +
111
- "Reconnect via npx @agent-native/core@latest design connect.",
112
- );
113
- }
84
+ const scope = await resolveLocalhostConnectionScope();
85
+ const connection = await resolveLocalhostBridgeConnection({
86
+ connectionId,
87
+ ...scope,
88
+ });
89
+ const bridgeToken = requireLocalhostBridgeToken(
90
+ connectionId,
91
+ connection.bridgeToken,
92
+ );
114
93
 
115
- const bridgeUrl = normalizeBridgeUrl(connection.bridgeUrl);
116
- const res = await fetch(`${bridgeUrl}/list-files`, {
117
- method: "POST",
118
- headers: {
119
- "Content-Type": "application/json",
120
- "X-Bridge-Token": connection.bridgeToken,
121
- },
122
- body: JSON.stringify({}),
94
+ const res = await fetchLocalhostBridge({
95
+ bridgeUrl: normalizeBridgeUrl(connection.bridgeUrl),
96
+ operation: "list-files",
97
+ bridgeToken,
98
+ body: {},
123
99
  });
124
100
  if (!res.ok) {
125
101
  const errText = await res.text().catch(() => res.statusText);
126
- throw new Error(`Bridge list-files failed (${res.status}): ${errText}`);
102
+ throw localhostBridgeRequestError("list-files", res.status, errText);
127
103
  }
128
104
  const body = (await res.json()) as {
129
105
  files?: Array<{ path: string; size: number }>;
@@ -1,12 +1,9 @@
1
1
  import { defineAction } from "@agent-native/core";
2
- import {
3
- getRequestOrgId,
4
- getRequestUserEmail,
5
- } from "@agent-native/core/server/request-context";
6
2
  import { and, desc, eq, isNull } from "drizzle-orm";
7
3
  import { z } from "zod";
8
4
 
9
5
  import { getDb, schema } from "../server/db/index.js";
6
+ import { resolveLocalhostConnectionScope } from "../server/lib/localhost-connection.js";
10
7
  import type {
11
8
  DesignBridgeCapability,
12
9
  LocalhostDesignRouteManifest,
@@ -33,9 +30,7 @@ export default defineAction({
33
30
  readOnly: true,
34
31
  http: { method: "GET" },
35
32
  run: async ({ id, status }) => {
36
- const ownerEmail = getRequestUserEmail();
37
- if (!ownerEmail) throw new Error("no authenticated user");
38
- const orgId = getRequestOrgId() ?? null;
33
+ const { ownerEmail, orgId } = await resolveLocalhostConnectionScope();
39
34
  const clauses = [
40
35
  eq(schema.designLocalhostConnections.ownerEmail, ownerEmail),
41
36
  orgId
@@ -31,6 +31,7 @@
31
31
 
32
32
  import { defineAction } from "@agent-native/core";
33
33
  import { seedFromText } from "@agent-native/core/collab";
34
+ import { injectDocumentMarkup } from "@agent-native/core/shared";
34
35
  import { assertAccess } from "@agent-native/core/sharing";
35
36
  import { and, eq } from "drizzle-orm";
36
37
  import { nanoid } from "nanoid";
@@ -181,8 +182,7 @@ export default defineAction({
181
182
  .map((entry) => boardObjectEntryToHtmlFragment(entry))
182
183
  .join("\n");
183
184
 
184
- // Insert fragments before </body>.
185
- boardHtml = boardHtml.replace("</body>", `${fragments}\n</body>`);
185
+ boardHtml = injectDocumentMarkup(boardHtml, `${fragments}\n`);
186
186
  }
187
187
 
188
188
  const now = new Date().toISOString();
@@ -1,6 +1,19 @@
1
+ import crypto from "node:crypto";
2
+ import path from "node:path";
3
+
1
4
  import { defineAction, embedApp } from "@agent-native/core";
2
5
  import { writeAppState } from "@agent-native/core/application-state";
3
- import { buildDeepLink } from "@agent-native/core/server";
6
+ import {
7
+ buildDeepLink,
8
+ buildEmbedStartPath,
9
+ createEmbedSessionTicket,
10
+ } from "@agent-native/core/server";
11
+ import {
12
+ getRequestContext,
13
+ getRequestOrgId,
14
+ getRequestUserEmail,
15
+ runWithRequestContext,
16
+ } from "@agent-native/core/server/request-context";
4
17
  import { eq } from "drizzle-orm";
5
18
  import { z } from "zod";
6
19
 
@@ -166,13 +179,53 @@ function isLoopbackUrl(value: string): boolean {
166
179
  );
167
180
  }
168
181
 
169
- function designOverviewDeepLink(designId: string): string {
182
+ const LOCAL_VISUAL_EDIT_TICKET_TTL_SECONDS = 5 * 60;
183
+ const LOCAL_VISUAL_EDIT_PRINCIPAL_DOMAIN =
184
+ "local.visual-edit.agent-native.invalid";
185
+
186
+ /**
187
+ * Stable owner partition for Design rows created by the local CLI skill when
188
+ * no account session exists. This value is never installed as a browser
189
+ * session; it only lets one trusted in-process `pnpm action` invocation compose
190
+ * the existing owner-scoped actions before minting a narrow embed capability.
191
+ */
192
+ export function localVisualEditWorkspacePrincipal(
193
+ workspacePath = process.cwd(),
194
+ ): string {
195
+ const workspaceId = crypto
196
+ .createHash("sha256")
197
+ .update(path.resolve(workspacePath))
198
+ .digest("hex")
199
+ .slice(0, 24);
200
+ return `workspace+${workspaceId}@${LOCAL_VISUAL_EDIT_PRINCIPAL_DOMAIN}`;
201
+ }
202
+
203
+ function localVisualEditPath(designId: string): string {
204
+ return `/visual-edit/${encodeURIComponent(designId)}?editorView=overview`;
205
+ }
206
+
207
+ function localVisualEditDeepLink(designId: string): string {
170
208
  return buildDeepLink({
171
209
  app: "design",
172
210
  view: "editor",
173
211
  params: { designId, editorView: "overview" },
174
- to: `/design/${encodeURIComponent(designId)}?editorView=overview`,
212
+ to: localVisualEditPath(designId),
213
+ });
214
+ }
215
+
216
+ async function createCallerHandoff(
217
+ targetPath: string,
218
+ ownerEmail: string,
219
+ designId: string,
220
+ ): Promise<string> {
221
+ const ticket = await createEmbedSessionTicket({
222
+ ownerEmail,
223
+ orgId: getRequestOrgId(),
224
+ targetPath,
225
+ scope: `capability:visual-edit:design:${encodeURIComponent(designId)}`,
226
+ ttlSeconds: LOCAL_VISUAL_EDIT_TICKET_TTL_SECONDS,
175
227
  });
228
+ return buildEmbedStartPath(ticket.ticket);
176
229
  }
177
230
 
178
231
  function routeManifestFromScreens(args: {
@@ -211,7 +264,7 @@ function routeManifestFromScreens(args: {
211
264
 
212
265
  export default defineAction({
213
266
  description:
214
- "Open or refresh a running localhost app in Design overview mode in one authenticated step. Registers the local bridge, creates or reuses a design, places URL-backed screens, stores the active visual-edit context, and navigates the current Design session to the canvas. Use this for /visual-edit launches and follow-up requests like adding a mobile-size screen.",
267
+ "Open or refresh a running localhost app in Design overview mode without requiring a Design account login. Registers the local bridge, creates or reuses a design, places URL-backed screens, stores the active visual-edit context, and navigates the current Design session to the canvas. Use this from the local /visual-edit skill and for follow-up requests like adding a mobile-size screen.",
215
268
  schema: z.object({
216
269
  designId: z
217
270
  .string()
@@ -310,153 +363,199 @@ export default defineAction({
310
363
  height: 680,
311
364
  }),
312
365
  },
313
- run: async (args) => {
366
+ run: async (args, ctx) => {
314
367
  const devServerUrl = normalizeBaseUrl(args.devServerUrl);
315
- const routeManifest = args.routeManifest
316
- ? {
317
- ...args.routeManifest,
318
- devServerUrl: args.routeManifest.devServerUrl ?? devServerUrl,
319
- rootPath: args.routeManifest.rootPath ?? args.rootPath,
368
+ const runForPrincipal = async () => {
369
+ const routeManifest = args.routeManifest
370
+ ? {
371
+ ...args.routeManifest,
372
+ devServerUrl: args.routeManifest.devServerUrl ?? devServerUrl,
373
+ rootPath: args.routeManifest.rootPath ?? args.rootPath,
374
+ }
375
+ : {
376
+ version: 1 as const,
377
+ sourceType: "localhost" as const,
378
+ devServerUrl,
379
+ rootPath: args.rootPath,
380
+ routes:
381
+ routeManifestFromScreens({
382
+ devServerUrl,
383
+ routes: args.routes,
384
+ paths: args.paths,
385
+ }) ?? [],
386
+ generatedAt: new Date().toISOString(),
387
+ };
388
+ const connection = await connectLocalhostAction.run({
389
+ // Let connect-localhost be the single source of truth for stable
390
+ // per-user/per-org id derivation. Duplicating it here can create a second
391
+ // tokenless row after the CLI self-registers the bridge token.
392
+ id: args.connectionId,
393
+ name: args.name,
394
+ devServerUrl,
395
+ bridgeUrl: args.bridgeUrl,
396
+ rootPath: routeManifest.rootPath ?? args.rootPath,
397
+ routeManifest,
398
+ capabilities: args.capabilities,
399
+ bridgeToken: args.bridgeToken,
400
+ previewToken: args.previewToken,
401
+ status: "connected",
402
+ });
403
+
404
+ let designId = args.designId;
405
+ let createdDesign = false;
406
+ let publicReadOnly = false;
407
+ if (!designId) {
408
+ const design = await createDesignAction.run({
409
+ title: args.title ?? `${new URL(devServerUrl).host} visual edit`,
410
+ description:
411
+ args.description ??
412
+ "URL-backed localhost screens prepared by visual-edit.",
413
+ projectType: "prototype",
414
+ });
415
+ designId = design.id;
416
+ createdDesign = true;
417
+ if (args.publicReadOnly && isLoopbackUrl(devServerUrl)) {
418
+ publicReadOnly = true;
419
+ await getDb()
420
+ .update(schema.designs)
421
+ .set({ visibility: "public" })
422
+ .where(eq(schema.designs.id, designId));
320
423
  }
321
- : {
322
- version: 1 as const,
323
- sourceType: "localhost" as const,
324
- devServerUrl,
325
- rootPath: args.rootPath,
326
- routes:
327
- routeManifestFromScreens({
328
- devServerUrl,
329
- routes: args.routes,
330
- paths: args.paths,
331
- }) ?? [],
332
- generatedAt: new Date().toISOString(),
333
- };
334
- const connection = await connectLocalhostAction.run({
335
- // Let connect-localhost be the single source of truth for stable
336
- // per-user/per-org id derivation. Duplicating it here can create a second
337
- // tokenless row after the CLI self-registers the bridge token.
338
- id: args.connectionId,
339
- name: args.name,
340
- devServerUrl,
341
- bridgeUrl: args.bridgeUrl,
342
- rootPath: routeManifest.rootPath ?? args.rootPath,
343
- routeManifest,
344
- capabilities: args.capabilities,
345
- bridgeToken: args.bridgeToken,
346
- previewToken: args.previewToken,
347
- status: "connected",
348
- });
424
+ }
349
425
 
350
- let designId = args.designId;
351
- let createdDesign = false;
352
- let publicReadOnly = false;
353
- if (!designId) {
354
- const design = await createDesignAction.run({
355
- title: args.title ?? `${new URL(devServerUrl).host} visual edit`,
356
- description:
357
- args.description ??
358
- "URL-backed localhost screens prepared by visual-edit.",
359
- projectType: "prototype",
360
- });
361
- designId = design.id;
362
- createdDesign = true;
363
- if (args.publicReadOnly && isLoopbackUrl(devServerUrl)) {
364
- publicReadOnly = true;
365
- await getDb()
366
- .update(schema.designs)
367
- .set({ visibility: "public" })
368
- .where(eq(schema.designs.id, designId));
426
+ const viewports = resolveViewports(args.viewports);
427
+ const requestedRoutes = args.routes?.length
428
+ ? args.routes
429
+ : args.paths?.length
430
+ ? args.paths.map((path) => ({ path }))
431
+ : viewports
432
+ ? routeManifest.routes.map((route) => ({
433
+ routeId: route.id,
434
+ path: route.path,
435
+ title: route.title,
436
+ }))
437
+ : undefined;
438
+ if (viewports && !requestedRoutes?.length) {
439
+ throw new Error(
440
+ "viewports needs at least one route: pass routes/paths, or connect a bridge whose manifest lists routes.",
441
+ );
369
442
  }
370
- }
371
443
 
372
- const viewports = resolveViewports(args.viewports);
373
- const requestedRoutes = args.routes?.length
374
- ? args.routes
375
- : args.paths?.length
376
- ? args.paths.map((path) => ({ path }))
377
- : viewports
378
- ? routeManifest.routes.map((route) => ({
379
- routeId: route.id,
380
- path: route.path,
381
- title: route.title,
382
- }))
383
- : undefined;
384
- if (viewports && !requestedRoutes?.length) {
385
- throw new Error(
386
- "viewports needs at least one route: pass routes/paths, or connect a bridge whose manifest lists routes.",
387
- );
388
- }
444
+ const screens = await addLocalhostScreensAction.run({
445
+ designId,
446
+ connectionId: connection.id,
447
+ routes:
448
+ viewports && requestedRoutes
449
+ ? expandRoutesAcrossViewports({
450
+ routes: requestedRoutes,
451
+ viewports,
452
+ startX: args.startX ?? 0,
453
+ startY: args.startY ?? 0,
454
+ gap: args.gap ?? 160,
455
+ })
456
+ : args.routes,
457
+ paths: viewports ? undefined : args.paths,
458
+ defaultWidth: args.defaultWidth,
459
+ defaultHeight: args.defaultHeight,
460
+ startX: args.startX,
461
+ startY: args.startY,
462
+ gap: args.gap,
463
+ });
389
464
 
390
- const screens = await addLocalhostScreensAction.run({
391
- designId,
392
- connectionId: connection.id,
393
- routes:
394
- viewports && requestedRoutes
395
- ? expandRoutesAcrossViewports({
396
- routes: requestedRoutes,
397
- viewports,
398
- startX: args.startX ?? 0,
399
- startY: args.startY ?? 0,
400
- gap: args.gap ?? 160,
401
- })
402
- : args.routes,
403
- paths: viewports ? undefined : args.paths,
404
- defaultWidth: args.defaultWidth,
405
- defaultHeight: args.defaultHeight,
406
- startX: args.startX,
407
- startY: args.startY,
408
- gap: args.gap,
409
- });
465
+ const urlPath = localVisualEditPath(designId);
466
+ await writeAppState("visual-edit", {
467
+ designId,
468
+ connectionId: connection.id,
469
+ devServerUrl,
470
+ bridgeUrl: connection.bridgeUrl,
471
+ rootPath: connection.rootPath,
472
+ urlPath,
473
+ screens: screens.screens,
474
+ updatedAt: new Date().toISOString(),
475
+ });
410
476
 
411
- const urlPath = `/design/${encodeURIComponent(
412
- designId,
413
- )}?editorView=overview`;
414
- await writeAppState("visual-edit", {
415
- designId,
416
- connectionId: connection.id,
417
- devServerUrl,
418
- bridgeUrl: connection.bridgeUrl,
419
- rootPath: connection.rootPath,
420
- urlPath,
421
- screens: screens.screens,
422
- updatedAt: new Date().toISOString(),
423
- });
477
+ if (args.navigate) {
478
+ await navigateAction.run({
479
+ view: "editor",
480
+ designId,
481
+ editorView: "overview",
482
+ path: urlPath,
483
+ });
484
+ }
424
485
 
425
- if (args.navigate) {
426
- await navigateAction.run({
427
- view: "editor",
486
+ const ownerEmail = getRequestUserEmail();
487
+ if (!ownerEmail) {
488
+ throw new Error("visual-edit principal was not established");
489
+ }
490
+ const deepLink = localVisualEditDeepLink(designId);
491
+ const embedStartUrl = isLoopbackUrl(devServerUrl)
492
+ ? await createCallerHandoff(urlPath, ownerEmail, designId)
493
+ : undefined;
494
+
495
+ const result = {
428
496
  designId,
429
- editorView: "overview",
430
- path: urlPath,
431
- });
497
+ connectionId: connection.id,
498
+ createdDesign,
499
+ publicReadOnly,
500
+ devServerUrl,
501
+ bridgeUrl: connection.bridgeUrl,
502
+ rootPath: connection.rootPath,
503
+ screenCount: screens.screenCount,
504
+ screens: screens.screens,
505
+ placedFrames: screens.placedFrames,
506
+ overview: true,
507
+ urlPath,
508
+ // Safe for model-visible action text and retained links. The MCP App
509
+ // receives the one-time launcher separately through hidden metadata.
510
+ openUrl: deepLink,
511
+ // Minted/stored by connect-localhost; the skill starts the bridge with
512
+ // `design connect --bridge-token <this>` so bridge and row agree.
513
+ bridgeToken: connection.bridgeToken,
514
+ previewToken: connection.previewToken,
515
+ };
516
+ if (embedStartUrl) {
517
+ // Trusted hosts and the CLI runner read this property directly. Keeping
518
+ // it non-enumerable prevents generic object/string serialization from
519
+ // copying the single-use bearer into model-visible action output.
520
+ Object.defineProperty(result, "embedStartUrl", {
521
+ value: embedStartUrl,
522
+ enumerable: false,
523
+ });
524
+ }
525
+ return result as typeof result & { embedStartUrl?: string };
526
+ };
527
+
528
+ if (getRequestUserEmail()) return runForPrincipal();
529
+ if (ctx?.caller !== "cli" || !isLoopbackUrl(devServerUrl)) {
530
+ throw new Error(
531
+ "Signed-out visual-edit is available only through the local CLI for a loopback app.",
532
+ );
533
+ }
534
+ if (args.publicReadOnly === false) {
535
+ throw new Error(
536
+ "Signed-out local visual-edit requires publicReadOnly so the resource can be opened through its narrow editor capability. Sign in to create a private Design resource.",
537
+ );
432
538
  }
433
539
 
434
- return {
435
- designId,
436
- connectionId: connection.id,
437
- createdDesign,
438
- publicReadOnly,
439
- devServerUrl,
440
- bridgeUrl: connection.bridgeUrl,
441
- rootPath: connection.rootPath,
442
- screenCount: screens.screenCount,
443
- screens: screens.screens,
444
- placedFrames: screens.placedFrames,
445
- overview: true,
446
- urlPath,
447
- openUrl: designOverviewDeepLink(designId),
448
- // Minted/stored by connect-localhost; the skill starts the bridge with
449
- // `design connect --bridge-token <this>` so bridge and row agree.
450
- bridgeToken: connection.bridgeToken,
451
- previewToken: connection.previewToken,
452
- };
540
+ return runWithRequestContext(
541
+ {
542
+ ...(getRequestContext() ?? {}),
543
+ userEmail: localVisualEditWorkspacePrincipal(),
544
+ orgId: undefined,
545
+ },
546
+ runForPrincipal,
547
+ );
453
548
  },
454
549
  link: ({ result }) => {
455
550
  if (!result || typeof result !== "object") return null;
456
- const designId = (result as { designId?: string }).designId;
551
+ const { designId } = result as {
552
+ designId?: string;
553
+ };
457
554
  if (!designId) return null;
458
555
  return {
459
- url: designOverviewDeepLink(designId),
556
+ // The single-use embed ticket stays in MCP result metadata. Keep the
557
+ // model-visible link credential-free.
558
+ url: localVisualEditDeepLink(designId),
460
559
  label: "Open overview",
461
560
  view: "editor",
462
561
  };
@@ -6,7 +6,10 @@
6
6
  * grant (reads do not require user write consent, only editor access + a
7
7
  * valid bridge connection):
8
8
  * 1. assertAccess: the caller must have editor access to the design.
9
- * 2. Bridge URL resolution: only the current user's own connection row.
9
+ * 2. Bridge URL resolution: only the current user's own connection row, in
10
+ * the caller's own org scope. A miss throws a classified 4xx from
11
+ * server/lib/localhost-connection.ts so the client sees the actual
12
+ * condition instead of a generic 500.
10
13
  * 3. Loopback check: bridgeUrl must resolve to localhost/127.0.0.1.
11
14
  * 4. Bridge token: the connection's stored bridge token is sent as
12
15
  * X-Bridge-Token so the bridge can reject unauthorized callers. The
@@ -15,15 +18,16 @@
15
18
  */
16
19
 
17
20
  import { defineAction } from "@agent-native/core";
18
- import {
19
- getRequestOrgId,
20
- getRequestUserEmail,
21
- } from "@agent-native/core/server/request-context";
22
21
  import { assertAccess } from "@agent-native/core/sharing";
23
- import { and, eq, isNull } from "drizzle-orm";
24
22
  import { z } from "zod";
25
23
 
26
- import { getDb, schema } from "../server/db/index.js";
24
+ import {
25
+ fetchLocalhostBridge,
26
+ localhostBridgeRequestError,
27
+ requireLocalhostBridgeToken,
28
+ resolveLocalhostBridgeConnection,
29
+ resolveLocalhostConnectionScope,
30
+ } from "../server/lib/localhost-connection.js";
27
31
 
28
32
  function isLoopbackHostname(hostname: string): boolean {
29
33
  const normalized = hostname.toLowerCase();
@@ -81,53 +85,25 @@ export default defineAction({
81
85
  run: async ({ designId, connectionId, path: relPath }) => {
82
86
  await assertAccess("design", designId, "editor");
83
87
 
84
- const ownerEmail = getRequestUserEmail();
85
- if (!ownerEmail) throw new Error("no authenticated user");
86
- const orgId = getRequestOrgId() ?? null;
87
-
88
- const db = getDb();
89
- const [connection] = await db
90
- .select({
91
- bridgeUrl: schema.designLocalhostConnections.bridgeUrl,
92
- bridgeToken: schema.designLocalhostConnections.bridgeToken,
93
- })
94
- .from(schema.designLocalhostConnections)
95
- .where(
96
- and(
97
- eq(schema.designLocalhostConnections.id, connectionId),
98
- eq(schema.designLocalhostConnections.ownerEmail, ownerEmail),
99
- orgId
100
- ? eq(schema.designLocalhostConnections.orgId, orgId)
101
- : isNull(schema.designLocalhostConnections.orgId),
102
- ),
103
- )
104
- .limit(1);
105
-
106
- if (!connection?.bridgeUrl) {
107
- throw new Error(
108
- `No bridge URL found for connection "${connectionId}". ` +
109
- "Ensure the design bridge is running (npx @agent-native/core@latest design connect).",
110
- );
111
- }
112
- if (!connection.bridgeToken) {
113
- throw new Error(
114
- `No bridge token found for connection "${connectionId}". ` +
115
- "Reconnect via npx @agent-native/core@latest design connect.",
116
- );
117
- }
88
+ const scope = await resolveLocalhostConnectionScope();
89
+ const connection = await resolveLocalhostBridgeConnection({
90
+ connectionId,
91
+ ...scope,
92
+ });
93
+ const bridgeToken = requireLocalhostBridgeToken(
94
+ connectionId,
95
+ connection.bridgeToken,
96
+ );
118
97
 
119
- const bridgeUrl = normalizeBridgeUrl(connection.bridgeUrl);
120
- const res = await fetch(`${bridgeUrl}/read-file`, {
121
- method: "POST",
122
- headers: {
123
- "Content-Type": "application/json",
124
- "X-Bridge-Token": connection.bridgeToken,
125
- },
126
- body: JSON.stringify({ relPath }),
98
+ const res = await fetchLocalhostBridge({
99
+ bridgeUrl: normalizeBridgeUrl(connection.bridgeUrl),
100
+ operation: "read-file",
101
+ bridgeToken,
102
+ body: { relPath },
127
103
  });
128
104
  if (!res.ok) {
129
105
  const errText = await res.text().catch(() => res.statusText);
130
- throw new Error(`Bridge read-file failed (${res.status}): ${errText}`);
106
+ throw localhostBridgeRequestError("read-file", res.status, errText);
131
107
  }
132
108
  const body = (await res.json()) as {
133
109
  content?: string;