@agent-native/core 0.127.3 → 0.128.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (457) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +101 -0
  3. package/corpus/core/README.md +5 -26
  4. package/corpus/core/docs/content/actions.mdx +47 -4
  5. package/corpus/core/docs/content/native-chat-ui.mdx +7 -0
  6. package/corpus/core/docs/content/organizations-teams-permissions.mdx +109 -3
  7. package/corpus/core/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
  8. package/corpus/core/docs/content/toolkit-org-team.mdx +72 -12
  9. package/corpus/core/package.json +2 -1
  10. package/corpus/core/src/a2a/artifact-response.ts +36 -29
  11. package/corpus/core/src/action.ts +83 -2
  12. package/corpus/core/src/chat-threads/store.ts +48 -43
  13. package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
  14. package/corpus/core/src/client/AgentPanel.tsx +26 -6
  15. package/corpus/core/src/client/AssistantChat.tsx +63 -7
  16. package/corpus/core/src/client/DefaultSpinner.tsx +29 -0
  17. package/corpus/core/src/client/org/TeamPage.tsx +161 -6
  18. package/corpus/core/src/client/org/hooks.ts +67 -0
  19. package/corpus/core/src/client/org/index.ts +9 -0
  20. package/corpus/core/src/client/transcription/use-live-transcription.ts +62 -10
  21. package/corpus/core/src/db/client.ts +42 -3
  22. package/corpus/core/src/db/ensure-additive-columns.ts +60 -33
  23. package/corpus/core/src/deploy/build.ts +31 -2
  24. package/corpus/core/src/mcp-client/routes.ts +10 -1
  25. package/corpus/core/src/org/app-roles-handlers.ts +152 -0
  26. package/corpus/core/src/org/app-roles.ts +355 -0
  27. package/corpus/core/src/org/index.ts +27 -1
  28. package/corpus/core/src/org/migrations.ts +22 -0
  29. package/corpus/core/src/org/plugin.ts +27 -0
  30. package/corpus/core/src/org/schema.ts +15 -0
  31. package/corpus/core/src/scripts/docs/search.ts +17 -0
  32. package/corpus/core/src/scripts/docs/source-search.ts +10 -0
  33. package/corpus/core/src/server/agent-chat/script-entries.ts +3 -0
  34. package/corpus/core/src/server/agent-chat-plugin.ts +53 -52
  35. package/corpus/core/src/server/builder-design-systems.ts +299 -82
  36. package/corpus/core/src/server/core-routes-plugin.ts +6 -1
  37. package/corpus/core/src/server/framework-request-handler.ts +44 -6
  38. package/corpus/core/src/server/index.ts +8 -0
  39. package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
  40. package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
  41. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +31 -0
  42. package/corpus/core/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
  43. package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
  44. package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
  45. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
  46. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
  47. package/corpus/core/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
  48. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +32 -0
  49. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +31 -0
  50. package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +4 -0
  51. package/corpus/templates/analytics/_gitignore +2 -0
  52. package/corpus/templates/analytics/actions/data-source-status.ts +21 -12
  53. package/corpus/templates/analytics/app/global.css +7 -7
  54. package/corpus/templates/analytics/app/i18n-data.ts +30 -0
  55. package/corpus/templates/analytics/app/lib/data-source-status.ts +2 -1
  56. package/corpus/templates/analytics/app/pages/DataSources.tsx +54 -10
  57. package/corpus/templates/analytics/changelog/2026-07-28-analytics-pages-load-reliably-with-large-dashboard-workspaces.md +6 -0
  58. package/corpus/templates/analytics/changelog/2026-07-28-dashboard-loading-shimmer-now-flows-smoothly-in-one-directi.md +6 -0
  59. package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +5 -4
  60. package/corpus/templates/analytics/server/plugins/agent-chat.ts +54 -42
  61. package/corpus/templates/analytics/server/plugins/db.ts +1 -18
  62. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +32 -0
  63. package/corpus/templates/assets/.agents/skills/security/SKILL.md +31 -0
  64. package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +4 -0
  65. package/corpus/templates/assets/_gitignore +2 -0
  66. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +32 -0
  67. package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +7 -0
  68. package/corpus/templates/brain/.agents/skills/security/SKILL.md +31 -0
  69. package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +4 -0
  70. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +32 -0
  71. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +31 -0
  72. package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +4 -0
  73. package/corpus/templates/calendar/_gitignore +2 -0
  74. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +32 -0
  75. package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
  76. package/corpus/templates/chat/.agents/skills/security/SKILL.md +31 -0
  77. package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
  78. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +32 -0
  79. package/corpus/templates/clips/.agents/skills/security/SKILL.md +31 -0
  80. package/corpus/templates/clips/_gitignore +2 -0
  81. package/corpus/templates/clips/actions/request-transcript.ts +77 -11
  82. package/corpus/templates/clips/actions/save-browser-transcript.ts +28 -7
  83. package/corpus/templates/clips/app/routes/record.tsx +11 -3
  84. package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-save-a-truncated-transcript-as-.md +6 -0
  85. package/corpus/templates/clips/changelog/2026-07-28-browser-recordings-no-longer-stop-transcribing-partway-throu.md +6 -0
  86. package/corpus/templates/clips/changelog/2026-07-28-desktop-full-screen-clips-now-get-an-instant-local-transcrip.md +6 -0
  87. package/corpus/templates/clips/changelog/2026-07-28-long-transcriptions-no-longer-show-a-false-transcription-sto.md +6 -0
  88. package/corpus/templates/clips/changelog/2026-07-28-restarting-for-an-update-now-installs-the-newest-release-ins.md +6 -0
  89. package/corpus/templates/clips/changelog/2026-07-28-the-meeting-recording-pill-now-anchors-to-the-right-edge-of-.md +6 -0
  90. package/corpus/templates/clips/desktop/src/lib/audio-meter.ts +31 -2
  91. package/corpus/templates/clips/desktop/src/lib/recorder.ts +114 -13
  92. package/corpus/templates/clips/desktop/src/lib/updater.ts +12 -4
  93. package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +40 -15
  94. package/corpus/templates/clips/desktop/src/styles.css +10 -7
  95. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +21 -14
  96. package/corpus/templates/clips/shared/transcript-status.ts +10 -0
  97. package/corpus/templates/content/.agents/skills/actions/SKILL.md +32 -0
  98. package/corpus/templates/content/.agents/skills/security/SKILL.md +31 -0
  99. package/corpus/templates/content/.agents/skills/sharing/SKILL.md +4 -0
  100. package/corpus/templates/content/_gitignore +2 -0
  101. package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +4 -0
  102. package/corpus/templates/design/.agents/skills/actions/SKILL.md +32 -0
  103. package/corpus/templates/design/.agents/skills/security/SKILL.md +31 -0
  104. package/corpus/templates/design/.agents/skills/sharing/SKILL.md +4 -0
  105. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +46 -3
  106. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +7 -5
  107. package/corpus/templates/design/_gitignore +2 -0
  108. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +2 -2
  109. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +7 -4
  110. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +1 -1
  111. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +10 -4
  112. package/corpus/templates/design/app/i18n-data.ts +10 -0
  113. package/corpus/templates/design/app/lib/builder-design-system-upload.ts +280 -0
  114. package/corpus/templates/design/app/lib/design-ui-events.ts +5 -0
  115. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +90 -54
  116. package/corpus/templates/design/app/root.tsx +18 -1
  117. package/corpus/templates/design/changelog/2026-07-28-figma-fig-uploads-now-show-indexing-progress-and-an-open-in-.md +6 -0
  118. package/corpus/templates/design/changelog/2026-07-28-show-or-hide-design-editing-chrome-with-cmd-on-apple-devices.md +6 -0
  119. package/corpus/templates/design/server/handlers/design-system-decode-job-status.ts +49 -0
  120. package/corpus/templates/design/server/handlers/design-system-upload-start.ts +87 -0
  121. package/corpus/templates/design/server/handlers/index-design-system-sources.ts +82 -0
  122. package/corpus/templates/design/server/routes/api/design-system-decode-job-status.get.ts +1 -0
  123. package/corpus/templates/design/server/routes/api/design-system-upload-start.post.ts +1 -0
  124. package/corpus/templates/design/server/routes/api/index-design-system-sources.post.ts +1 -0
  125. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +32 -0
  126. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +31 -0
  127. package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +4 -0
  128. package/corpus/templates/dispatch/_gitignore +2 -0
  129. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +32 -0
  130. package/corpus/templates/forms/.agents/skills/security/SKILL.md +31 -0
  131. package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +4 -0
  132. package/corpus/templates/forms/_gitignore +2 -0
  133. package/corpus/templates/macros/.agents/skills/security/SKILL.md +31 -0
  134. package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +4 -0
  135. package/corpus/templates/macros/_gitignore +2 -0
  136. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +32 -0
  137. package/corpus/templates/mail/.agents/skills/security/SKILL.md +31 -0
  138. package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +4 -0
  139. package/corpus/templates/mail/_gitignore +2 -0
  140. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +32 -0
  141. package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +7 -0
  142. package/corpus/templates/plan/.agents/skills/security/SKILL.md +31 -0
  143. package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +4 -0
  144. package/corpus/templates/plan/_gitignore +2 -0
  145. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +32 -0
  146. package/corpus/templates/slides/.agents/skills/security/SKILL.md +31 -0
  147. package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +4 -0
  148. package/corpus/templates/slides/_gitignore +2 -0
  149. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +126 -53
  150. package/corpus/templates/slides/app/components/design-system/builder-design-system-upload.ts +271 -0
  151. package/corpus/templates/slides/app/components/design-system/builder-index-response.ts +1 -1
  152. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  153. package/corpus/templates/slides/server/handlers/design-system-decode-job-status.ts +49 -0
  154. package/corpus/templates/slides/server/handlers/design-system-upload-start.ts +87 -0
  155. package/corpus/templates/slides/server/handlers/index-design-system-sources.ts +79 -0
  156. package/corpus/templates/slides/server/routes/api/design-system-decode-job-status.get.ts +1 -0
  157. package/corpus/templates/slides/server/routes/api/design-system-upload-start.post.ts +1 -0
  158. package/corpus/templates/slides/server/routes/api/index-design-system-sources.post.ts +1 -0
  159. package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +32 -0
  160. package/corpus/templates/tasks/.agents/skills/adding-a-feature/SKILL.md +7 -0
  161. package/corpus/templates/tasks/.agents/skills/security/SKILL.md +31 -0
  162. package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +4 -0
  163. package/corpus/templates/tasks/_gitignore +2 -0
  164. package/dist/a2a/artifact-response.d.ts.map +1 -1
  165. package/dist/a2a/artifact-response.js +30 -29
  166. package/dist/a2a/artifact-response.js.map +1 -1
  167. package/dist/action.d.ts +36 -0
  168. package/dist/action.d.ts.map +1 -1
  169. package/dist/action.js +37 -2
  170. package/dist/action.js.map +1 -1
  171. package/dist/chat-threads/store.d.ts +12 -0
  172. package/dist/chat-threads/store.d.ts.map +1 -1
  173. package/dist/chat-threads/store.js +48 -42
  174. package/dist/chat-threads/store.js.map +1 -1
  175. package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
  176. package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
  177. package/dist/cli/skills-content/design-visual-edit-skill.js +46 -3
  178. package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
  179. package/dist/client/AgentPanel.d.ts +3 -1
  180. package/dist/client/AgentPanel.d.ts.map +1 -1
  181. package/dist/client/AgentPanel.js +11 -9
  182. package/dist/client/AgentPanel.js.map +1 -1
  183. package/dist/client/AssistantChat.d.ts.map +1 -1
  184. package/dist/client/AssistantChat.js +57 -6
  185. package/dist/client/AssistantChat.js.map +1 -1
  186. package/dist/client/DefaultSpinner.d.ts +7 -0
  187. package/dist/client/DefaultSpinner.d.ts.map +1 -1
  188. package/dist/client/DefaultSpinner.js +25 -1
  189. package/dist/client/DefaultSpinner.js.map +1 -1
  190. package/dist/client/org/TeamPage.d.ts +13 -1
  191. package/dist/client/org/TeamPage.d.ts.map +1 -1
  192. package/dist/client/org/TeamPage.js +41 -11
  193. package/dist/client/org/TeamPage.js.map +1 -1
  194. package/dist/client/org/hooks.d.ts +37 -0
  195. package/dist/client/org/hooks.d.ts.map +1 -1
  196. package/dist/client/org/hooks.js +37 -0
  197. package/dist/client/org/hooks.js.map +1 -1
  198. package/dist/client/org/index.d.ts +3 -2
  199. package/dist/client/org/index.d.ts.map +1 -1
  200. package/dist/client/org/index.js +1 -1
  201. package/dist/client/org/index.js.map +1 -1
  202. package/dist/client/transcription/use-live-transcription.d.ts +8 -0
  203. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  204. package/dist/client/transcription/use-live-transcription.js +38 -11
  205. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  206. package/dist/collab/routes.d.ts +1 -1
  207. package/dist/db/client.d.ts +12 -0
  208. package/dist/db/client.d.ts.map +1 -1
  209. package/dist/db/client.js +40 -3
  210. package/dist/db/client.js.map +1 -1
  211. package/dist/db/ensure-additive-columns.d.ts.map +1 -1
  212. package/dist/db/ensure-additive-columns.js +54 -32
  213. package/dist/db/ensure-additive-columns.js.map +1 -1
  214. package/dist/deploy/build.d.ts +1 -0
  215. package/dist/deploy/build.d.ts.map +1 -1
  216. package/dist/deploy/build.js +23 -2
  217. package/dist/deploy/build.js.map +1 -1
  218. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  219. package/dist/mcp-client/routes.d.ts +3 -1
  220. package/dist/mcp-client/routes.d.ts.map +1 -1
  221. package/dist/mcp-client/routes.js +8 -2
  222. package/dist/mcp-client/routes.js.map +1 -1
  223. package/dist/notifications/routes.d.ts +1 -1
  224. package/dist/org/app-roles-handlers.d.ts +27 -0
  225. package/dist/org/app-roles-handlers.d.ts.map +1 -0
  226. package/dist/org/app-roles-handlers.js +125 -0
  227. package/dist/org/app-roles-handlers.js.map +1 -0
  228. package/dist/org/app-roles.d.ts +136 -0
  229. package/dist/org/app-roles.d.ts.map +1 -0
  230. package/dist/org/app-roles.js +216 -0
  231. package/dist/org/app-roles.js.map +1 -0
  232. package/dist/org/index.d.ts +4 -1
  233. package/dist/org/index.d.ts.map +1 -1
  234. package/dist/org/index.js +3 -1
  235. package/dist/org/index.js.map +1 -1
  236. package/dist/org/migrations.d.ts.map +1 -1
  237. package/dist/org/migrations.js +22 -0
  238. package/dist/org/migrations.js.map +1 -1
  239. package/dist/org/plugin.d.ts +2 -0
  240. package/dist/org/plugin.d.ts.map +1 -1
  241. package/dist/org/plugin.js +20 -0
  242. package/dist/org/plugin.js.map +1 -1
  243. package/dist/org/schema.d.ts +143 -0
  244. package/dist/org/schema.d.ts.map +1 -1
  245. package/dist/org/schema.js +14 -0
  246. package/dist/org/schema.js.map +1 -1
  247. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  248. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  249. package/dist/scripts/docs/search.d.ts.map +1 -1
  250. package/dist/scripts/docs/search.js +15 -0
  251. package/dist/scripts/docs/search.js.map +1 -1
  252. package/dist/scripts/docs/source-search.d.ts +7 -0
  253. package/dist/scripts/docs/source-search.d.ts.map +1 -1
  254. package/dist/scripts/docs/source-search.js +9 -0
  255. package/dist/scripts/docs/source-search.js.map +1 -1
  256. package/dist/secrets/routes.d.ts +9 -9
  257. package/dist/server/agent-chat/script-entries.d.ts.map +1 -1
  258. package/dist/server/agent-chat/script-entries.js +3 -0
  259. package/dist/server/agent-chat/script-entries.js.map +1 -1
  260. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  261. package/dist/server/agent-chat-plugin.js +46 -48
  262. package/dist/server/agent-chat-plugin.js.map +1 -1
  263. package/dist/server/builder-design-systems.d.ts +49 -0
  264. package/dist/server/builder-design-systems.d.ts.map +1 -1
  265. package/dist/server/builder-design-systems.js +221 -69
  266. package/dist/server/builder-design-systems.js.map +1 -1
  267. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  268. package/dist/server/core-routes-plugin.js +6 -1
  269. package/dist/server/core-routes-plugin.js.map +1 -1
  270. package/dist/server/framework-request-handler.d.ts.map +1 -1
  271. package/dist/server/framework-request-handler.js +42 -6
  272. package/dist/server/framework-request-handler.js.map +1 -1
  273. package/dist/server/index.d.ts +1 -1
  274. package/dist/server/index.d.ts.map +1 -1
  275. package/dist/server/index.js +1 -1
  276. package/dist/server/index.js.map +1 -1
  277. package/dist/server/realtime-token.d.ts +1 -1
  278. package/dist/templates/chat/.agents/skills/actions/SKILL.md +32 -0
  279. package/dist/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
  280. package/dist/templates/chat/.agents/skills/security/SKILL.md +31 -0
  281. package/dist/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
  282. package/dist/templates/default/.agents/skills/actions/SKILL.md +32 -0
  283. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
  284. package/dist/templates/default/.agents/skills/security/SKILL.md +31 -0
  285. package/dist/templates/headless/.agents/skills/actions/SKILL.md +32 -0
  286. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
  287. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
  288. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
  289. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
  290. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
  291. package/docs/content/actions.mdx +47 -4
  292. package/docs/content/native-chat-ui.mdx +7 -0
  293. package/docs/content/organizations-teams-permissions.mdx +109 -3
  294. package/docs/content/template-design-collaboration-and-full-apps.mdx +15 -0
  295. package/docs/content/toolkit-org-team.mdx +72 -12
  296. package/package.json +2 -1
  297. package/src/a2a/artifact-response.ts +36 -29
  298. package/src/action.ts +83 -2
  299. package/src/chat-threads/store.ts +48 -43
  300. package/src/cli/skills-content/design-visual-edit-skill.ts +46 -3
  301. package/src/client/AgentPanel.tsx +26 -6
  302. package/src/client/AssistantChat.tsx +63 -7
  303. package/src/client/DefaultSpinner.tsx +29 -0
  304. package/src/client/org/TeamPage.tsx +161 -6
  305. package/src/client/org/hooks.ts +67 -0
  306. package/src/client/org/index.ts +9 -0
  307. package/src/client/transcription/use-live-transcription.ts +62 -10
  308. package/src/db/client.ts +42 -3
  309. package/src/db/ensure-additive-columns.ts +60 -33
  310. package/src/deploy/build.ts +31 -2
  311. package/src/mcp-client/routes.ts +10 -1
  312. package/src/org/app-roles-handlers.ts +152 -0
  313. package/src/org/app-roles.ts +355 -0
  314. package/src/org/index.ts +27 -1
  315. package/src/org/migrations.ts +22 -0
  316. package/src/org/plugin.ts +27 -0
  317. package/src/org/schema.ts +15 -0
  318. package/src/scripts/docs/search.ts +17 -0
  319. package/src/scripts/docs/source-search.ts +10 -0
  320. package/src/server/agent-chat/script-entries.ts +3 -0
  321. package/src/server/agent-chat-plugin.ts +53 -52
  322. package/src/server/builder-design-systems.ts +299 -82
  323. package/src/server/core-routes-plugin.ts +6 -1
  324. package/src/server/framework-request-handler.ts +44 -6
  325. package/src/server/index.ts +8 -0
  326. package/src/templates/chat/.agents/skills/actions/SKILL.md +32 -0
  327. package/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +7 -0
  328. package/src/templates/chat/.agents/skills/security/SKILL.md +31 -0
  329. package/src/templates/chat/.agents/skills/sharing/SKILL.md +4 -0
  330. package/src/templates/default/.agents/skills/actions/SKILL.md +32 -0
  331. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +7 -0
  332. package/src/templates/default/.agents/skills/security/SKILL.md +31 -0
  333. package/src/templates/headless/.agents/skills/actions/SKILL.md +32 -0
  334. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -0
  335. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +7 -0
  336. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +40 -0
  337. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +31 -0
  338. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +4 -0
  339. package/corpus/core/src/templates/chat/.agents/skills/actions/SKILL.md +0 -530
  340. package/corpus/core/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +0 -191
  341. package/corpus/core/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +0 -115
  342. package/corpus/core/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +0 -177
  343. package/corpus/core/src/templates/chat/.agents/skills/capture-learnings/SKILL.md +0 -89
  344. package/corpus/core/src/templates/chat/.agents/skills/create-skill/SKILL.md +0 -221
  345. package/corpus/core/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +0 -220
  346. package/corpus/core/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +0 -263
  347. package/corpus/core/src/templates/chat/.agents/skills/feature-flags/SKILL.md +0 -169
  348. package/corpus/core/src/templates/chat/.agents/skills/frontend-design/SKILL.md +0 -174
  349. package/corpus/core/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +0 -232
  350. package/corpus/core/src/templates/chat/.agents/skills/security/SKILL.md +0 -282
  351. package/corpus/core/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +0 -119
  352. package/corpus/core/src/templates/chat/.agents/skills/shadcn-ui/SKILL.md +0 -123
  353. package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +0 -122
  354. package/corpus/core/src/templates/chat/.env.example +0 -5
  355. package/corpus/core/src/templates/chat/.ignore +0 -0
  356. package/corpus/core/src/templates/chat/.oxfmtrc.json +0 -8
  357. package/corpus/core/src/templates/chat/AGENTS.md +0 -77
  358. package/corpus/core/src/templates/chat/CHANGELOG.md +0 -10
  359. package/corpus/core/src/templates/chat/DEVELOPING.md +0 -185
  360. package/corpus/core/src/templates/chat/README.md +0 -32
  361. package/corpus/core/src/templates/chat/_gitignore +0 -46
  362. package/corpus/core/src/templates/chat/actions/hello.ts +0 -13
  363. package/corpus/core/src/templates/chat/actions/navigate.ts +0 -41
  364. package/corpus/core/src/templates/chat/actions/run.ts +0 -2
  365. package/corpus/core/src/templates/chat/actions/view-screen.ts +0 -31
  366. package/corpus/core/src/templates/chat/app/components/layout/Header.tsx +0 -60
  367. package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +0 -188
  368. package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +0 -505
  369. package/corpus/core/src/templates/chat/app/components/ui/button.tsx +0 -1
  370. package/corpus/core/src/templates/chat/app/components/ui/card.tsx +0 -1
  371. package/corpus/core/src/templates/chat/app/components/ui/dropdown-menu.tsx +0 -1
  372. package/corpus/core/src/templates/chat/app/components/ui/input.tsx +0 -1
  373. package/corpus/core/src/templates/chat/app/components/ui/label.tsx +0 -1
  374. package/corpus/core/src/templates/chat/app/components/ui/sheet.tsx +0 -1
  375. package/corpus/core/src/templates/chat/app/components/ui/toolkit-provider.tsx +0 -17
  376. package/corpus/core/src/templates/chat/app/components/ui/tooltip.tsx +0 -1
  377. package/corpus/core/src/templates/chat/app/design-system.ts +0 -3
  378. package/corpus/core/src/templates/chat/app/entry.client.tsx +0 -22
  379. package/corpus/core/src/templates/chat/app/entry.server.tsx +0 -10
  380. package/corpus/core/src/templates/chat/app/global.css +0 -93
  381. package/corpus/core/src/templates/chat/app/hooks/use-navigation-state.ts +0 -93
  382. package/corpus/core/src/templates/chat/app/i18n/ar-SA.ts +0 -68
  383. package/corpus/core/src/templates/chat/app/i18n/de-DE.ts +0 -71
  384. package/corpus/core/src/templates/chat/app/i18n/en-US.ts +0 -70
  385. package/corpus/core/src/templates/chat/app/i18n/es-ES.ts +0 -71
  386. package/corpus/core/src/templates/chat/app/i18n/fr-FR.ts +0 -71
  387. package/corpus/core/src/templates/chat/app/i18n/hi-IN.ts +0 -69
  388. package/corpus/core/src/templates/chat/app/i18n/index.ts +0 -34
  389. package/corpus/core/src/templates/chat/app/i18n/ja-JP.ts +0 -70
  390. package/corpus/core/src/templates/chat/app/i18n/ko-KR.ts +0 -70
  391. package/corpus/core/src/templates/chat/app/i18n/pt-BR.ts +0 -71
  392. package/corpus/core/src/templates/chat/app/i18n/zh-CN.ts +0 -66
  393. package/corpus/core/src/templates/chat/app/i18n/zh-TW.ts +0 -66
  394. package/corpus/core/src/templates/chat/app/i18n-data.ts +0 -556
  395. package/corpus/core/src/templates/chat/app/lib/agent-page.tsx +0 -49
  396. package/corpus/core/src/templates/chat/app/lib/app-config.ts +0 -11
  397. package/corpus/core/src/templates/chat/app/lib/tab-id.ts +0 -1
  398. package/corpus/core/src/templates/chat/app/lib/utils.ts +0 -1
  399. package/corpus/core/src/templates/chat/app/root.tsx +0 -173
  400. package/corpus/core/src/templates/chat/app/routes/_index.tsx +0 -94
  401. package/corpus/core/src/templates/chat/app/routes/agent.tsx +0 -24
  402. package/corpus/core/src/templates/chat/app/routes/chat.$threadId.tsx +0 -1
  403. package/corpus/core/src/templates/chat/app/routes/database.tsx +0 -17
  404. package/corpus/core/src/templates/chat/app/routes/extensions.$id.$slug.tsx +0 -2
  405. package/corpus/core/src/templates/chat/app/routes/extensions.$id.tsx +0 -11
  406. package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +0 -11
  407. package/corpus/core/src/templates/chat/app/routes/extensions.tsx +0 -5
  408. package/corpus/core/src/templates/chat/app/routes/observability.tsx +0 -19
  409. package/corpus/core/src/templates/chat/app/routes/settings.tsx +0 -89
  410. package/corpus/core/src/templates/chat/app/routes/team.tsx +0 -11
  411. package/corpus/core/src/templates/chat/app/routes.ts +0 -4
  412. package/corpus/core/src/templates/chat/app/vite-env.d.ts +0 -6
  413. package/corpus/core/src/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
  414. package/corpus/core/src/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
  415. package/corpus/core/src/templates/chat/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
  416. package/corpus/core/src/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +0 -6
  417. package/corpus/core/src/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
  418. package/corpus/core/src/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +0 -5
  419. package/corpus/core/src/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +0 -6
  420. package/corpus/core/src/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +0 -6
  421. package/corpus/core/src/templates/chat/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +0 -6
  422. package/corpus/core/src/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +0 -6
  423. package/corpus/core/src/templates/chat/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +0 -6
  424. package/corpus/core/src/templates/chat/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +0 -6
  425. package/corpus/core/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +0 -6
  426. package/corpus/core/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +0 -6
  427. package/corpus/core/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +0 -6
  428. package/corpus/core/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +0 -6
  429. package/corpus/core/src/templates/chat/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +0 -6
  430. package/corpus/core/src/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +0 -6
  431. package/corpus/core/src/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +0 -6
  432. package/corpus/core/src/templates/chat/changelog/2026-07-25-settings-navigation-now-keeps-manage-agent-as-a-dedicated-li.md +0 -6
  433. package/corpus/core/src/templates/chat/components.json +0 -20
  434. package/corpus/core/src/templates/chat/learnings.defaults.md +0 -5
  435. package/corpus/core/src/templates/chat/netlify.toml +0 -11
  436. package/corpus/core/src/templates/chat/package.json +0 -92
  437. package/corpus/core/src/templates/chat/public/agent-native-icon-dark.svg +0 -10
  438. package/corpus/core/src/templates/chat/public/agent-native-icon-light.svg +0 -10
  439. package/corpus/core/src/templates/chat/public/agent-native-logo-dark.svg +0 -21
  440. package/corpus/core/src/templates/chat/public/agent-native-logo-light.svg +0 -21
  441. package/corpus/core/src/templates/chat/public/favicon.svg +0 -1
  442. package/corpus/core/src/templates/chat/public/icon-180.svg +0 -1
  443. package/corpus/core/src/templates/chat/public/icon-192.svg +0 -1
  444. package/corpus/core/src/templates/chat/public/icon-512.svg +0 -1
  445. package/corpus/core/src/templates/chat/public/manifest.json +0 -21
  446. package/corpus/core/src/templates/chat/react-router.config.ts +0 -7
  447. package/corpus/core/src/templates/chat/server/middleware/auth.ts +0 -15
  448. package/corpus/core/src/templates/chat/server/plugins/agent-chat.ts +0 -21
  449. package/corpus/core/src/templates/chat/server/plugins/auth.ts +0 -17
  450. package/corpus/core/src/templates/chat/server/routes/[...page].get.ts +0 -5
  451. package/corpus/core/src/templates/chat/ssr-entry.ts +0 -15
  452. package/corpus/core/src/templates/chat/tsconfig.json +0 -21
  453. package/corpus/core/src/templates/chat/vite.config.ts +0 -19
  454. package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +0 -151
  455. package/corpus/templates/design/server/routes/api/index-design-system-with-builder.post.ts +0 -1
  456. package/corpus/templates/slides/server/handlers/index-design-system-with-builder.ts +0 -119
  457. package/corpus/templates/slides/server/routes/api/index-design-system-with-builder.post.ts +0 -1
@@ -11,6 +11,21 @@ Once a prototype is in good shape, this page covers what happens next: pulling i
11
11
 
12
12
  Design isn't only for prototypes generated from a prompt — a coding agent can install `/visual-edit` to bring a real, already-running local app into Design as its own screens. Each requested path or URL becomes its own screen on the canvas, and a numbered flow (an onboarding step 1, 2, 3) stays as separate ordered screens instead of collapsing into one. The entry route renders before sign-in, and a shared design link works read-only without an account — but saving the layout, generating new screens, or sharing still requires signing in first.
13
13
 
14
+ ### Keep the canvas beside your chat
15
+
16
+ When your coding app has an inline browser, ask `/visual-edit` to open the returned Design URL there. In Codex Desktop, that means the built-in Browser; in Claude Code Desktop's Code tab, it means the Browser pane. Both can keep the canvas inside the coding app beside the conversation. In VS Code, the Agent Native extension opens the same Design URL in its side-panel webview. Browser panes can be disabled or unavailable in CLI, remote, or restricted sessions, so `/visual-edit` falls back to an **Open design** link instead of claiming the canvas opened.
17
+
18
+ Once Design is open, choose **Show/Hide UI** from the `Cmd+K` menu or press `Cmd+Shift+\` on Apple devices / `Ctrl+Shift+\` elsewhere to toggle all editing chrome so only the canvas remains. The same action is available by right-clicking empty canvas space.
19
+
20
+ These are especially useful canvas sets:
21
+
22
+ - **A multi-step flow:** `/visual-edit localhost:5173 — cart, shipping, payment, confirmation; open it beside this chat`
23
+ - **Several pages:** `/visual-edit localhost:5173 — home, pricing, docs, and settings`
24
+ - **One page at several sizes:** `/visual-edit localhost:5173/dashboard — desktop, tablet, and mobile side by side`
25
+ - **Several states of one page:** `/visual-edit localhost:5173/inbox — empty, selected, and compose-open states`
26
+
27
+ The agent keeps named steps in order and places responsive variants in aligned columns, so the canvas reads like a flow or comparison board rather than a pile of screenshots. Name the routes and sizes you care about; requesting every discovered route at every viewport can create a noisy canvas.
28
+
14
29
  <Diagram id="doc-block-design8" title="Three source modes" summary={"A design's source is inline, localhost, or fusion — the mode decides where an edit actually lands."}>
15
30
 
16
31
  ```html
@@ -21,17 +21,21 @@ connections, service tokens, and app switching.
21
21
 
22
22
  ## Pieces {#pieces}
23
23
 
24
- | Piece | Purpose |
25
- | --------------------- | ----------------------------------------------------------------------------------------------- |
26
- | `<TeamPage>` | Standard team management page for members, invites, roles, and organization preferences. |
27
- | `<OrgSwitcher>` | Current organization picker for sidebars and headers. |
28
- | `<InvitationBanner>` | One-click invite and domain-match join prompts. |
29
- | `<RequireActiveOrg>` | Guard for pages that need an active organization before rendering app data. |
30
- | `useOrgRole()` | Shared role booleans for member, invite, settings, and domain controls. |
31
- | Organization handlers | Create, rename, switch, invite, accept, remove, and update roles/domains. |
32
- | Roles | Owner, admin, and member gates for sharing, settings, service tokens, and provider connections. |
33
- | Allowed domains | Automatic join and domain-scoped access policy. |
34
- | App links | Workspace app-link parsing and visible app-switcher helpers. |
24
+ | Piece | Purpose |
25
+ | ----------------------- | ----------------------------------------------------------------------------------------------- |
26
+ | `<TeamPage>` | Standard team management page for members, invites, roles, and organization preferences. |
27
+ | `<OrgSwitcher>` | Current organization picker for sidebars and headers. |
28
+ | `<InvitationBanner>` | One-click invite and domain-match join prompts. |
29
+ | `<RequireActiveOrg>` | Guard for pages that need an active organization before rendering app data. |
30
+ | `useOrgRole()` | Shared role booleans for member, invite, settings, and domain controls. |
31
+ | `appRoles` prop | Adds a per-app role column and picker to `<TeamPage>` from a `defineAppRoles` descriptor. |
32
+ | `useAppRoles()` | An app's role vocabulary, its assignments in the active org, and whether the viewer may edit. |
33
+ | `useAppRole()` | The current user's role in one app, or `null` when unassigned. |
34
+ | `useSetAppMemberRole()` | Assign or clear one member's app role. Org owner/admin only, enforced server-side. |
35
+ | Organization handlers | Create, rename, switch, invite, accept, remove, and update roles/domains. |
36
+ | Roles | Owner, admin, and member gates for sharing, settings, service tokens, and provider connections. |
37
+ | Allowed domains | Automatic join and domain-scoped access policy. |
38
+ | App links | Workspace app-link parsing and visible app-switcher helpers. |
35
39
 
36
40
  ## API {#api}
37
41
 
@@ -66,12 +70,68 @@ export function AdminOnlyControl() {
66
70
 
67
71
  Server code imports the same role helpers from `@agent-native/core/org-team`.
68
72
  The route plugin mounts `/_agent-native/org/*` for org creation, switching,
69
- invites, domains, member roles, and A2A secret sync.
73
+ invites, domains, member roles, app roles, and A2A secret sync.
74
+
75
+ ### Per-app roles {#app-roles}
76
+
77
+ When an app needs its own permission vocabulary on top of team membership,
78
+ declare it with `defineAppRoles` and pass the descriptor to `TeamPage`. The
79
+ descriptor is the serializable half of the declaration — no database imports —
80
+ so the same object can be handed to `defineAppRoles` on the server and to the
81
+ component in the browser bundle:
82
+
83
+ ```tsx
84
+ import {
85
+ RequireActiveOrg,
86
+ TeamPage,
87
+ useAppRole,
88
+ useAppRoles,
89
+ useSetAppMemberRole,
90
+ } from "@agent-native/core/client/org-team";
91
+ import { coachRoles } from "../shared/coach-roles";
92
+
93
+ export function SettingsTeamTab() {
94
+ return (
95
+ <RequireActiveOrg>
96
+ <TeamPage appRoles={coachRoles} />
97
+ </RequireActiveOrg>
98
+ );
99
+ }
100
+
101
+ export function CoachOnlyControl() {
102
+ const { role } = useAppRole("coach");
103
+ return role === "coach-admin" ? <button type="button">Archive</button> : null;
104
+ }
105
+
106
+ export function RoleAdmin() {
107
+ const { data } = useAppRoles("coach");
108
+ const setRole = useSetAppMemberRole("coach");
109
+ if (!data?.canManage) return null;
110
+ return (
111
+ <button
112
+ type="button"
113
+ onClick={() => setRole.mutate({ email: "dana@acme.com", role: null })}
114
+ >
115
+ Clear role
116
+ </button>
117
+ );
118
+ }
119
+ ```
120
+
121
+ `role`, `myRole`, and `canManage` are progressive disclosure only. The server
122
+ re-resolves the caller's app role on every guarded operation, and assignment
123
+ edits require the org `owner`/`admin` role regardless of what the client
124
+ believes. See
125
+ [Organizations, Teams & Permissions → App roles](/docs/organizations-teams-permissions#app-roles-per-app-rbac)
126
+ for the role model and [Actions → Authorization](/docs/actions#authorize) for
127
+ the server-side `authorize` guard.
70
128
 
71
129
  ## UX Standard {#ux-standard}
72
130
 
73
131
  - Users can see which organization they are in before creating or sharing data.
74
132
  - Invites and roles live in the team settings surface, not per-resource dialogs.
133
+ - App-specific roles appear as another column on that same team surface, never
134
+ as a separate permissions page or a second organization.
75
135
  - Org domain changes are owner-only and explain who can auto-join.
76
136
  - App switching lists workspace/default app links. Active-org continuity comes
77
137
  from the target app sharing the same auth and organization state.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.127.3",
3
+ "version": "0.128.1",
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": {
@@ -327,6 +327,7 @@
327
327
  "@assistant-ui/react-markdown": "^0.12.6",
328
328
  "@assistant-ui/store": ">=0.2.9 <0.2.14",
329
329
  "@assistant-ui/tap": "^0.5.14",
330
+ "@builder.io/ai-utils": "^0.84.0",
330
331
  "@clack/prompts": "^1.4.0",
331
332
  "@codemirror/lang-sql": "^6.10.0",
332
333
  "@codemirror/theme-one-dark": "^6.1.3",
@@ -50,6 +50,11 @@ const ARTIFACT_IDENTITY_WRITE_TOOLS = new Set([
50
50
  "create-deck",
51
51
  "duplicate-deck",
52
52
  "add-slide",
53
+ "update-slide",
54
+ "patch-deck",
55
+ "save-deck",
56
+ "import-pptx",
57
+ "restore-deck-version",
53
58
  "update-dashboard",
54
59
  "rename-dashboard",
55
60
  "save-analysis",
@@ -513,27 +518,43 @@ function addImageArtifact(
513
518
  });
514
519
  }
515
520
 
516
- function isReadyDeckArtifact(parsed: Record<string, unknown>): boolean {
517
- const slideCount = numberValue(parsed.slideCount);
518
- if (slideCount !== undefined) return slideCount > 0;
519
- if (Array.isArray(parsed.slides)) return parsed.slides.length > 0;
520
- return true;
521
- }
522
-
523
521
  function addDeckArtifact(
524
522
  decks: Map<string, CreatedDeckArtifact>,
525
523
  parsed: Record<string, unknown>,
526
- options: { requireReady: boolean },
527
524
  ): void {
528
525
  const id = deckIdValue(parsed);
529
526
  if (!id) return;
530
- if (options.requireReady && !isReadyDeckArtifact(parsed)) return;
531
527
  decks.set(id, {
532
528
  id,
533
529
  url: stringValue(parsed.url) ?? stringValue(parsed.urlPath),
534
530
  });
535
531
  }
536
532
 
533
+ // Deck writes are spread across a dozen actions (create-deck, add-slide,
534
+ // patch-deck, save-deck, update-slide, import-*, restore-deck-version), so a
535
+ // per-tool allow-list refuses a real deck URL every time an action is added.
536
+ // Trust any successful result that names a deck the way the deck routes do: an
537
+ // explicit deckId, or a canonical /deck/<id> URL the action itself returned.
538
+ function addDeckArtifactFromAnyResult(
539
+ decks: Map<string, CreatedDeckArtifact>,
540
+ parsed: Record<string, unknown>,
541
+ ): void {
542
+ const url = stringValue(parsed.url) ?? stringValue(parsed.urlPath);
543
+ const deckId = stringValue(parsed.deckId);
544
+ if (deckId) {
545
+ decks.set(deckId, {
546
+ id: deckId,
547
+ url:
548
+ url && artifactUrlReferencesId(url, "deck", deckId) ? url : undefined,
549
+ });
550
+ }
551
+
552
+ const reference = url ? parseArtifactReferenceUrl(url) : null;
553
+ if (reference?.kind === "deck") {
554
+ decks.set(reference.id, { id: reference.id, url });
555
+ }
556
+ }
557
+
537
558
  function addListedDeckArtifacts(
538
559
  decks: Map<string, CreatedDeckArtifact>,
539
560
  parsed: Record<string, unknown>,
@@ -543,7 +564,7 @@ function addListedDeckArtifacts(
543
564
  for (const item of items) {
544
565
  const deck = asRecord(item);
545
566
  if (!deck) continue;
546
- addDeckArtifact(decks, deck, { requireReady: false });
567
+ addDeckArtifact(decks, deck);
547
568
  }
548
569
  }
549
570
 
@@ -617,6 +638,8 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
617
638
  const parsed = parseToolResultJson(toolResult.result);
618
639
  if (!parsed) continue;
619
640
 
641
+ addDeckArtifactFromAnyResult(decks, parsed);
642
+
620
643
  if (toolResult.tool === "save-monitor") {
621
644
  const id = stringValue(parsed.id);
622
645
  const url = stringValue(parsed.monitorAppUrl);
@@ -711,14 +734,10 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
711
734
 
712
735
  if (
713
736
  toolResult.tool === "create-deck" ||
714
- toolResult.tool === "duplicate-deck"
737
+ toolResult.tool === "duplicate-deck" ||
738
+ toolResult.tool === "get-deck"
715
739
  ) {
716
- addDeckArtifact(decks, parsed, { requireReady: true });
717
- continue;
718
- }
719
-
720
- if (toolResult.tool === "get-deck") {
721
- addDeckArtifact(decks, parsed, { requireReady: false });
740
+ addDeckArtifact(decks, parsed);
722
741
  continue;
723
742
  }
724
743
 
@@ -727,18 +746,6 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
727
746
  continue;
728
747
  }
729
748
 
730
- if (toolResult.tool === "add-slide") {
731
- const id = stringValue(parsed.deckId);
732
- const slideCount = numberValue(parsed.slideCount);
733
- if (id && slideCount !== undefined && slideCount > 0) {
734
- decks.set(id, {
735
- id,
736
- url: stringValue(parsed.url) ?? stringValue(parsed.urlPath),
737
- });
738
- }
739
- continue;
740
- }
741
-
742
749
  if (
743
750
  toolResult.tool === "update-dashboard" ||
744
751
  toolResult.tool === "rename-dashboard" ||
package/src/action.ts CHANGED
@@ -123,6 +123,19 @@ export interface ActionRunContext {
123
123
  turnId?: string;
124
124
  }
125
125
 
126
+ /**
127
+ * Pre-run authorization gate. Throw to deny with a specific message (the
128
+ * framework's `ForbiddenError` carries a 403), or return `false` for a generic
129
+ * denial. Returning `undefined` allows the call — a guard that forgets to
130
+ * return is therefore permissive, which is why `false` is honoured at all:
131
+ * `(args) => someCheck(args)` written against a boolean helper would otherwise
132
+ * pass silently on every denial.
133
+ */
134
+ export type ActionAuthorize<TArgs> = (
135
+ args: TArgs,
136
+ ctx?: ActionRunContext,
137
+ ) => void | boolean | Promise<void | boolean>;
138
+
126
139
  export interface AgentActionStopOptions {
127
140
  /** Optional stable code surfaced in run metadata and tests. */
128
141
  errorCode?: string;
@@ -466,6 +479,30 @@ interface DefineActionWithSchema<
466
479
  args: StandardSchemaV1.InferOutput<TSchema>,
467
480
  ctx?: ActionRunContext,
468
481
  ) => boolean | Promise<boolean>);
482
+ /**
483
+ * Authorization gate that runs before `run()` on **every** caller — agent
484
+ * tool, HTTP, frontend, MCP, A2A, and CLI. It wraps `run` itself rather than
485
+ * hanging off the action entry, because a flag consulted by the dispatcher
486
+ * only guards the dispatchers that remember to consult it.
487
+ *
488
+ * This is *authorization*, not approval: `needsApproval` asks a human to
489
+ * bless one call the caller is already allowed to make, while `authorize`
490
+ * decides whether they are allowed at all. It also does not replace
491
+ * `accessFilter` / `assertAccess` — those scope which rows a permitted caller
492
+ * may see; this decides whether the operation is open to them.
493
+ *
494
+ * ```ts
495
+ * import { coachAccess } from "../lib/access.js";
496
+ *
497
+ * export default defineAction({
498
+ * description: "Archive a training plan.",
499
+ * schema,
500
+ * authorize: coachAccess.requireAny("coach-admin"),
501
+ * run: async (args) => { ... },
502
+ * });
503
+ * ```
504
+ */
505
+ authorize?: ActionAuthorize<StandardSchemaV1.InferOutput<TSchema>>;
469
506
  /**
470
507
  * Audit-log configuration. **Default-on for mutating actions** — you only
471
508
  * need this to tune capture: declare the mutated `target` (so the change
@@ -556,6 +593,9 @@ interface DefineActionWithParams<
556
593
  args: InferParams<TParams>,
557
594
  ctx?: ActionRunContext,
558
595
  ) => boolean | Promise<boolean>);
596
+ /** Pre-run authorization gate applied to every caller. See the schema
597
+ * overload above for full semantics. */
598
+ authorize?: ActionAuthorize<InferParams<TParams>>;
559
599
  /** Audit-log configuration (default-on for mutations). See the schema
560
600
  * overload above and the `audit-log` skill. */
561
601
  audit?: ActionAuditConfig;
@@ -714,12 +754,21 @@ export function defineAction(options: any) {
714
754
  );
715
755
  }
716
756
 
757
+ // Authorization sits INSIDE input validation, so a gate that inspects `args`
758
+ // is handed the parsed, coerced value its type promises rather than whatever
759
+ // shape the caller sent. Putting it outside would have every guard reading
760
+ // attacker-shaped input while typed as though it were validated.
761
+ const guardedRun =
762
+ typeof options.authorize === "function"
763
+ ? wrapRunWithAuthorize(options.run, options.authorize)
764
+ : options.run;
765
+
717
766
  // Wrap run() with INPUT validation when schema is provided.
718
767
  // Pass toolParameters so the validation error can echo the expected signature
719
768
  // (required vs optional fields) and help the caller self-correct.
720
769
  const inputValidatedRun = hasSchema
721
- ? wrapWithValidation(options.schema, options.run, toolParameters)
722
- : options.run;
770
+ ? wrapWithValidation(options.schema, guardedRun, toolParameters)
771
+ : guardedRun;
723
772
 
724
773
  // Then wrap with OUTPUT validation when an outputSchema is provided. This
725
774
  // composes AROUND the input-validated run so the order is: validate input →
@@ -877,6 +926,38 @@ export function defineAction(options: any) {
877
926
  };
878
927
  }
879
928
 
929
+ /**
930
+ * Wrap an action's run with its `authorize` gate.
931
+ *
932
+ * The gate is applied here, around `run`, rather than exposed as a flag on the
933
+ * action entry: `run` is the one thing all six dispatch sites (agent loop, HTTP
934
+ * route, frontend, MCP, A2A, CLI) go through, so there is no caller that can
935
+ * reach the body without passing the check. `needsApproval` took the flag route
936
+ * and is consequently honoured only inside the agent loop.
937
+ *
938
+ * Composed so the full order is: validate input → authorize → run → validate
939
+ * output → audit. The audit wrapper is outermost, so a denial is still recorded
940
+ * as an attempt — which is precisely what an audit trail is for.
941
+ *
942
+ * A guard that throws denies with its own message. A guard that returns `false`
943
+ * denies generically. Anything else — including `undefined` — allows.
944
+ */
945
+ function wrapRunWithAuthorize(
946
+ run: (args: any, ctx?: ActionRunContext) => any,
947
+ authorize: ActionAuthorize<any>,
948
+ ): (args: any, ctx?: ActionRunContext) => Promise<any> {
949
+ return async function authorizedRun(args: any, ctx?: ActionRunContext) {
950
+ const verdict = await authorize(args, ctx);
951
+ if (verdict === false) {
952
+ const err = new Error("Not authorized") as Error & { statusCode: number };
953
+ err.name = "ForbiddenError";
954
+ err.statusCode = 403;
955
+ throw err;
956
+ }
957
+ return run(args, ctx);
958
+ };
959
+ }
960
+
880
961
  /**
881
962
  * Wrap an action's (already input/output-validated) run so each call records an
882
963
  * audit event after it resolves — on success and on error. Best-effort: the
@@ -159,9 +159,6 @@ async function ensureTable(): Promise<void> {
159
159
  "chat_thread_shares_resource_idx",
160
160
  CHAT_THREAD_SHARES_RESOURCE_INDEX_SQL,
161
161
  );
162
- // One-time backfill of message_count for legacy rows written before
163
- // the column was maintained.
164
- await backfillLegacyMessageCounts(client);
165
162
  return;
166
163
  }
167
164
 
@@ -221,15 +218,6 @@ async function ensureTable(): Promise<void> {
221
218
  // Index already exists or the dialect rejected a duplicate.
222
219
  }
223
220
  }
224
- // One-time backfill of message_count for legacy rows written before
225
- // the column was maintained. The list/summary path now reads
226
- // message_count directly (instead of re-parsing the thread_data blob)
227
- // and filters on `message_count > 0`, so any legacy row that has
228
- // messages but a stale `message_count = 0` would otherwise vanish from
229
- // the sidebar. Recompute the count from thread_data and persist it so
230
- // the hot path can stay blob-free. Idempotent: only touches rows where
231
- // the count is still 0 but the blob clearly contains a messages array.
232
- await backfillLegacyMessageCounts(client);
233
221
  })().catch((err) => {
234
222
  // Retry init on the next call after a failed startup.
235
223
  _initPromise = undefined;
@@ -240,28 +228,47 @@ async function ensureTable(): Promise<void> {
240
228
  }
241
229
 
242
230
  /**
243
- * Recompute `message_count` from `thread_data` for legacy rows that still
244
- * have a stale `message_count = 0` despite carrying a messages array in the
245
- * blob. Without this, dropping the `thread_data` payload (and the
246
- * `OR thread_data LIKE '%"messages"%'` filter) from the list path would make
247
- * those rows disappear from the sidebar. Runs once at table bootstrap and is
248
- * idempotent — after the first pass no row matches the WHERE clause again.
231
+ * Explicitly repair `message_count` for legacy rows written before the count
232
+ * was maintained. This must never run from table/bootstrap initialization:
233
+ * serverless isolates would each scan the full `thread_data` blob column on
234
+ * cold start. Operators may invoke it once when upgrading an old database.
249
235
  */
250
- async function backfillLegacyMessageCounts(
251
- client: ReturnType<typeof getDbExec>,
252
- ): Promise<void> {
253
- const { rows } = await client.execute({
254
- sql: `SELECT id, thread_data, message_count FROM chat_threads WHERE message_count = 0 AND thread_data LIKE '%"messages"%'`,
255
- args: [],
256
- });
257
- for (const r of rows) {
258
- const count = deriveMessageCount(r.thread_data, 0);
259
- if (count <= 0) continue;
260
- await client.execute({
261
- sql: `UPDATE chat_threads SET message_count = ? WHERE id = ? AND message_count = 0`,
262
- args: [count, r.id as string],
236
+ export async function repairLegacyChatThreadMessageCounts(
237
+ options: {
238
+ batchSize?: number;
239
+ } = {},
240
+ ): Promise<{ scanned: number; updated: number }> {
241
+ await ensureTable();
242
+ const client = getDbExec();
243
+ const batchSize = Math.max(1, Math.min(options.batchSize ?? 100, 1_000));
244
+ let afterId = "";
245
+ let scanned = 0;
246
+ let updated = 0;
247
+ while (true) {
248
+ const { rows } = await client.execute({
249
+ sql: `SELECT id, thread_data, message_count FROM chat_threads
250
+ WHERE message_count = 0
251
+ AND thread_data LIKE '%"messages"%'
252
+ AND id > ?
253
+ ORDER BY id
254
+ LIMIT ?`,
255
+ args: [afterId, batchSize],
263
256
  });
257
+ if (rows.length === 0) break;
258
+ for (const row of rows) {
259
+ afterId = String(row.id);
260
+ scanned++;
261
+ const count = deriveMessageCount(row.thread_data, 0);
262
+ if (count <= 0) continue;
263
+ const result = await client.execute({
264
+ sql: `UPDATE chat_threads SET message_count = ? WHERE id = ? AND message_count = 0`,
265
+ args: [count, afterId],
266
+ });
267
+ if (result.rowsAffected > 0) updated++;
268
+ }
269
+ if (rows.length < batchSize) break;
264
270
  }
271
+ return { scanned, updated };
265
272
  }
266
273
 
267
274
  function generateId(): string {
@@ -407,8 +414,8 @@ function rowToThread(r: Record<string, unknown>): ChatThread {
407
414
 
408
415
  function rowToSummary(r: Record<string, unknown>): ChatThreadSummary | null {
409
416
  // The summary path never loads `thread_data`; the count comes from the
410
- // dedicated `message_count` column (maintained on write, backfilled for
411
- // legacy rows at bootstrap). Empty threads are filtered out of the list.
417
+ // dedicated `message_count` column maintained on write. Empty threads are
418
+ // filtered out of the list.
412
419
  const messageCount = Number(r.message_count);
413
420
  if (!Number.isFinite(messageCount) || messageCount <= 0) return null;
414
421
  return {
@@ -475,9 +482,8 @@ const THREAD_COLUMNS = `id, owner_email, title, preview, thread_data, message_co
475
482
  // message-history JSON blob and selecting it for every row turns "open the
476
483
  // sidebar" into "download every conversation". The summary derives nothing
477
484
  // from the blob anymore — preview and message_count are dedicated columns
478
- // (message_count is maintained on write and backfilled for legacy rows at
479
- // bootstrap). The detail path (`THREAD_COLUMNS` / `getThread`) still returns
480
- // the full blob.
485
+ // (message_count is maintained on write). The detail path (`THREAD_COLUMNS` /
486
+ // `getThread`) still returns the full blob.
481
487
  const SUMMARY_COLUMNS = `id, title, preview, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, org_id, visibility`;
482
488
 
483
489
  export function registerChatThreadsShareable(): void {
@@ -684,10 +690,9 @@ export async function listThreads(
684
690
  const limit = opts.limit ?? 50;
685
691
  const offset = opts.offset ?? 0;
686
692
  const client = getDbExec();
687
- // `message_count > 0` is the authoritative "has messages" signal: it is
688
- // maintained on every write and backfilled for legacy rows at bootstrap,
689
- // so the old `OR thread_data LIKE '%"messages"%'` substring scan over the
690
- // full blob is no longer needed here.
693
+ // `message_count > 0` is the authoritative "has messages" signal maintained
694
+ // on every write, so the old `OR thread_data LIKE '%"messages"%'` substring
695
+ // scan over the full blob is no longer needed here.
691
696
  const access = chatThreadAccessSql(
692
697
  ownerEmail,
693
698
  opts.orgId ?? getRequestOrgId(),
@@ -731,9 +736,9 @@ export async function searchThreads(
731
736
  await ensureTable();
732
737
  const client = getDbExec();
733
738
  const pattern = `%${escapeLike(query)}%`;
734
- // The count-guard uses the maintained/backfilled `message_count` column
735
- // (same as listThreads). The content match still scans `thread_data` —
736
- // search legitimately needs to look inside message history.
739
+ // The count-guard uses the maintained `message_count` column (same as
740
+ // listThreads). The content match still scans `thread_data` — search
741
+ // legitimately needs to look inside message history.
737
742
  const access = chatThreadAccessSql(
738
743
  ownerEmail,
739
744
  options.orgId ?? getRequestOrgId(),
@@ -25,6 +25,32 @@ hosted Design MCP connector together. The open Skills CLI path
25
25
  (\`npx skills@latest add BuilderIO/agent-native --skill visual-edit\`) installs
26
26
  exported instructions only, with no MCP connector registration.
27
27
 
28
+ ## Put Design Beside The Chat
29
+
30
+ After \`open-visual-edit\` returns \`openUrl\`, open that URL in the coding host's
31
+ inline browser when one is available. This is the preferred working surface:
32
+ the user can keep Design's canvas beside the conversation, inspect the same
33
+ screens as the agent, and iterate without switching apps.
34
+
35
+ - In Codex Desktop, use the in-app Browser tool to open \`openUrl\`. The built-in
36
+ browser is the right surface for localhost and public pages that should stay
37
+ inside the app.
38
+ - In Claude Code Desktop's Code tab, open or preview \`openUrl\` in the Browser
39
+ pane. Ask Claude to preview it rather than opening the system browser.
40
+ - In VS Code, use the Agent Native Design webview/deep link described below.
41
+ - Inline browser availability is host-dependent. CLI, remote, or restricted
42
+ sessions may not expose one. If the inline surface is unavailable or disabled,
43
+ return the normal **Open design** link instead of claiming it opened.
44
+
45
+ Prefer the host's browser/preview tool over telling the user to press a keyboard
46
+ shortcut. Keep the canvas pane beside chat when the host supports rearrangeable
47
+ panes.
48
+
49
+ Inside Design, use **Show/Hide UI** from the \`Cmd+K\` menu or press
50
+ \`Cmd+Shift+\\\` on Apple platforms / \`Ctrl+Shift+\\\` elsewhere to toggle all
51
+ editing chrome so only the canvas remains. The same action is available from
52
+ Design's empty-canvas context menu.
53
+
28
54
  ## Core Model
29
55
 
30
56
  - Each screen is a URL-backed iframe, not copied HTML.
@@ -54,6 +80,23 @@ exported instructions only, with no MCP connector registration.
54
80
  \`localhost:1234/onboarding/1\` means
55
81
  \`http://localhost:1234/onboarding/1\`.
56
82
 
83
+ ## Useful Canvas Sets
84
+
85
+ Translate the user's requested review into the smallest useful set of frames:
86
+
87
+ - **Multi-step flow:** one ordered frame per route or query state, such as cart,
88
+ shipping, payment, and confirmation.
89
+ - **Multiple pages:** one frame per meaningful route, such as home, pricing,
90
+ docs, and account settings.
91
+ - **Responsive comparison:** repeat the same route at the requested desktop,
92
+ tablet, and mobile viewports so they align in one row.
93
+ - **State review:** repeat a route for meaningful URL-addressable states such as
94
+ empty, loading, error, modal-open, or selected-item views.
95
+
96
+ Do not expand every discovered route or every viewport unless the user asks for
97
+ an exhaustive audit. Preserve the user's labels and sequence so the canvas reads
98
+ like the workflow they described.
99
+
57
100
  ## Select And Reprompt
58
101
 
59
102
  When a chat message begins with \`[Reprompt selection]\`, the selected subtree is
@@ -275,9 +318,9 @@ Fallback, only when \`open-visual-edit\` is unavailable:
275
318
  ## Open The Design Surface
276
319
 
277
320
  - Use the \`link\`, \`deepLink\`, or MCP App embed returned by Design actions so
278
- the user sees the canvas. In Codex Desktop or VS Code, prefer opening that
279
- Design URL in the available preview/webview panel; otherwise surface the
280
- "Open design" link.
321
+ the user sees the canvas. Follow **Put Design Beside The Chat**: prefer the
322
+ host's inline Browser, preview, or webview panel; otherwise surface the
323
+ **Open design** link.
281
324
  - Return or open the \`openUrl\` / action link, not a hand-built
282
325
  \`/design/:id?_session=...\` URL.
283
326
  - If the user is working in VS Code, the Agent Native extension can open the