@agent-native/core 0.92.0 → 0.92.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 (363) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +14 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/application-state/store.ts +12 -1
  5. package/corpus/core/src/client/AssistantChat.tsx +27 -14
  6. package/corpus/core/src/client/PoweredByBadge.tsx +1 -8
  7. package/corpus/core/src/client/agent-chat-adapter.ts +37 -10
  8. package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +52 -1
  9. package/corpus/core/src/client/db-admin/TableEditor.tsx +49 -0
  10. package/corpus/core/src/client/db-admin/export-utils.ts +13 -4
  11. package/corpus/core/src/client/db-admin/useAgentSync.ts +72 -0
  12. package/corpus/core/src/client/error-capture.ts +69 -7
  13. package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +5 -1
  14. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +53 -8
  15. package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +5 -1
  16. package/corpus/core/src/client/extensions/portable-extension.ts +1 -0
  17. package/corpus/core/src/client/org/OrgSwitcher.tsx +12 -9
  18. package/corpus/core/src/client/org/TeamPage.tsx +77 -71
  19. package/corpus/core/src/client/settings/SettingsPanel.tsx +205 -52
  20. package/corpus/core/src/client/settings/SettingsSection.tsx +8 -1
  21. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +25 -9
  22. package/corpus/core/src/db-admin/agent-tools.ts +8 -2
  23. package/corpus/core/src/db-admin/operations.ts +116 -4
  24. package/corpus/core/src/db-admin/routes.ts +1 -0
  25. package/corpus/core/src/db-admin/types.ts +4 -0
  26. package/corpus/core/src/extensions/html-shell.ts +5 -4
  27. package/corpus/core/src/extensions/routes.ts +10 -0
  28. package/corpus/core/src/navigation/index.ts +1 -1
  29. package/corpus/core/src/resources/handlers.ts +10 -8
  30. package/corpus/core/src/server/poll.ts +293 -8
  31. package/corpus/core/src/styles/agent-native.css +27 -0
  32. package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
  33. package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  34. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  35. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +7 -0
  36. package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  37. package/corpus/core/src/templates/default/AGENTS.md +4 -2
  38. package/corpus/core/src/templates/headless/AGENTS.md +4 -0
  39. package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  40. package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  41. package/corpus/core/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  42. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  43. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  44. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  45. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  46. package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  47. package/corpus/core/src/templates/workspace-core/AGENTS.md +7 -1
  48. package/corpus/core/src/templates/workspace-root/AGENTS.md +7 -1
  49. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +5 -0
  50. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
  51. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
  52. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +7 -0
  53. package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +5 -1
  54. package/corpus/templates/analytics/AGENTS.md +33 -14
  55. package/corpus/templates/analytics/actions/capture-test-error.ts +4 -0
  56. package/corpus/templates/analytics/actions/get-analytics-alert-rule-defaults.ts +23 -0
  57. package/corpus/templates/analytics/actions/get-error-issue.ts +1 -1
  58. package/corpus/templates/analytics/actions/list-analysis-revisions.ts +40 -0
  59. package/corpus/templates/analytics/actions/list-dashboard-revisions.ts +40 -0
  60. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +299 -0
  61. package/corpus/templates/analytics/actions/navigate.ts +4 -2
  62. package/corpus/templates/analytics/actions/restore-analysis-revision.ts +43 -0
  63. package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +68 -0
  64. package/corpus/templates/analytics/actions/save-analytics-alert-rule.ts +14 -0
  65. package/corpus/templates/analytics/actions/save-monitor.ts +1 -1
  66. package/corpus/templates/analytics/actions/view-screen.ts +24 -0
  67. package/corpus/templates/analytics/app/components/analysis/AnalysisHistoryPanel.tsx +181 -0
  68. package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +184 -0
  69. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +22 -16
  70. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
  71. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +27 -21
  72. package/corpus/templates/analytics/app/hooks/use-analysis-revisions.ts +43 -0
  73. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +110 -0
  74. package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +43 -0
  75. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +8 -3
  76. package/corpus/templates/analytics/app/i18n/zh-TW.ts +64 -2
  77. package/corpus/templates/analytics/app/i18n-data.ts +783 -3
  78. package/corpus/templates/analytics/app/pages/Agents.tsx +359 -19
  79. package/corpus/templates/analytics/app/pages/Settings.tsx +3 -2
  80. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +34 -1
  81. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +28 -0
  82. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +18 -1
  83. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +7 -10
  84. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +479 -23
  85. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +0 -9
  86. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +11 -0
  87. package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +9 -1
  88. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +6 -3
  89. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +26 -30
  90. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -99
  91. package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +262 -104
  92. package/corpus/templates/analytics/app/routes/team.tsx +1 -1
  93. package/corpus/templates/analytics/changelog/2026-07-08-admins-can-audit-dashboard-usage-ownership-and-cleanup-signa.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-08-agent-monitoring-stays-available-to-non-admins.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-07-08-alert-rules-are-easier-to-scan-expand-and-edit-from-settings.md +6 -0
  96. package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-forms-remember-last-email-recipients.md +6 -0
  97. package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-rules-can-now-use-per-rule-slack-and-webhook.md +6 -0
  98. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +5 -0
  99. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-usage-now-counts-explorer-dashboard-traffic.md +6 -0
  100. package/corpus/templates/analytics/changelog/2026-07-08-demo-mode-session-emails-are-filtered-and-anonymized.md +6 -0
  101. package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-adds-stack-traces-and-frequency-bars.md +6 -0
  102. package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-now-shows-the-latest-occurrence-message-a.md +6 -0
  103. package/corpus/templates/analytics/changelog/2026-07-08-monitoring-errors-only-show-test-action-when-empty.md +6 -0
  104. package/corpus/templates/analytics/changelog/2026-07-08-production-session-replay-now-requires-private-blob-storage-.md +6 -0
  105. package/corpus/templates/analytics/changelog/2026-07-08-shared-extension-links-now-show-a-clear-message-when-you-do-.md +6 -0
  106. package/corpus/templates/analytics/changelog/2026-07-08-team-settings-show-access-controls-next-to-member-lists.md +6 -0
  107. package/corpus/templates/analytics/changelog/2026-07-08-uptime-monitors-now-use-a-10-second-request-timeout-by-defau.md +6 -0
  108. package/corpus/templates/analytics/server/db/schema-monitoring.ts +1 -1
  109. package/corpus/templates/analytics/server/db/schema.ts +56 -0
  110. package/corpus/templates/analytics/server/lib/analytics-alerts.ts +92 -0
  111. package/corpus/templates/analytics/server/lib/dashboards-store.ts +334 -5
  112. package/corpus/templates/analytics/server/lib/error-capture.ts +231 -36
  113. package/corpus/templates/analytics/server/lib/session-replay.ts +114 -8
  114. package/corpus/templates/analytics/server/lib/uptime-monitors.ts +5 -4
  115. package/corpus/templates/analytics/server/plugins/db.ts +112 -2
  116. package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +1 -0
  117. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +5 -0
  118. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
  119. package/corpus/templates/assets/.agents/skills/security/SKILL.md +7 -0
  120. package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +5 -1
  121. package/corpus/templates/assets/AGENTS.md +4 -0
  122. package/corpus/templates/assets/app/routes/settings.tsx +1 -1
  123. package/corpus/templates/assets/app/routes/team.tsx +1 -1
  124. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +5 -0
  125. package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
  126. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
  127. package/corpus/templates/brain/.agents/skills/security/SKILL.md +7 -0
  128. package/corpus/templates/brain/AGENTS.md +4 -0
  129. package/corpus/templates/brain/app/routes/team.tsx +1 -1
  130. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +5 -0
  131. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
  132. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +7 -0
  133. package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +5 -1
  134. package/corpus/templates/calendar/AGENTS.md +4 -0
  135. package/corpus/templates/calendar/app/components/calendar/DayView.tsx +11 -2
  136. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +21 -8
  137. package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +7 -1
  138. package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -2
  139. package/corpus/templates/calendar/app/lib/popover-click-guard.ts +48 -4
  140. package/corpus/templates/calendar/app/pages/Settings.tsx +1 -1
  141. package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
  142. package/corpus/templates/calendar/changelog/2026-07-08-clicking-empty-calendar-space-closes-an-open-event-popover-b.md +6 -0
  143. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +5 -0
  144. package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
  145. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  146. package/corpus/templates/chat/.agents/skills/security/SKILL.md +7 -0
  147. package/corpus/templates/chat/AGENTS.md +4 -0
  148. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  149. package/corpus/templates/chat/app/routes/settings.tsx +2 -2
  150. package/corpus/templates/chat/app/routes/team.tsx +1 -1
  151. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +5 -0
  152. package/corpus/templates/clips/.agents/skills/security/SKILL.md +7 -0
  153. package/corpus/templates/clips/AGENTS.md +4 -0
  154. package/corpus/templates/clips/actions/finalize-recording.ts +9 -3
  155. package/corpus/templates/clips/actions/set-thumbnail.ts +11 -2
  156. package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +1 -7
  157. package/corpus/templates/clips/app/components/player/player-controls.tsx +21 -13
  158. package/corpus/templates/clips/app/components/player/video-player.tsx +30 -75
  159. package/corpus/templates/clips/app/i18n/ar-SA.ts +6 -5
  160. package/corpus/templates/clips/app/i18n/de-DE.ts +6 -6
  161. package/corpus/templates/clips/app/i18n/en-US.ts +6 -5
  162. package/corpus/templates/clips/app/i18n/es-ES.ts +6 -5
  163. package/corpus/templates/clips/app/i18n/fr-FR.ts +6 -6
  164. package/corpus/templates/clips/app/i18n/hi-IN.ts +6 -5
  165. package/corpus/templates/clips/app/i18n/ja-JP.ts +6 -5
  166. package/corpus/templates/clips/app/i18n/ko-KR.ts +6 -5
  167. package/corpus/templates/clips/app/i18n/pt-BR.ts +6 -5
  168. package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -5
  169. package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -5
  170. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +51 -118
  171. package/corpus/templates/clips/changelog/2026-07-08-hosted-clip-uploads-now-clear-failed-buffered-chunks.md +6 -0
  172. package/corpus/templates/clips/changelog/2026-07-08-hosted-recording-uploads-now-avoid-sql-chunk-storage.md +6 -0
  173. package/corpus/templates/clips/changelog/2026-07-08-meeting-recaps-now-keep-summaries-action-items-and-transcrip.md +6 -0
  174. package/corpus/templates/clips/changelog/2026-07-08-video-playback-controls-now-match-loom-style-5-second-skips-.md +6 -0
  175. package/corpus/templates/clips/server/lib/recording-upload-state.ts +63 -0
  176. package/corpus/templates/clips/server/lib/video-storage.ts +4 -0
  177. package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +19 -13
  178. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +40 -1
  179. package/corpus/templates/content/.agents/skills/actions/SKILL.md +5 -0
  180. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
  181. package/corpus/templates/content/.agents/skills/security/SKILL.md +7 -0
  182. package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +5 -1
  183. package/corpus/templates/content/AGENTS.md +4 -0
  184. package/corpus/templates/content/app/routes/_app.settings.tsx +2 -2
  185. package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
  186. package/corpus/templates/design/.agents/skills/actions/SKILL.md +5 -0
  187. package/corpus/templates/design/.agents/skills/security/SKILL.md +7 -0
  188. package/corpus/templates/design/AGENTS.md +4 -0
  189. package/corpus/templates/design/actions/take-design-screenshot.ts +12 -9
  190. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -13
  191. package/corpus/templates/design/app/routes/team.tsx +1 -1
  192. package/corpus/templates/design/changelog/2026-07-08-local-images-added-to-designs-now-upload-to-file-storage-ins.md +6 -0
  193. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +5 -0
  194. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +7 -0
  195. package/corpus/templates/dispatch/AGENTS.md +4 -0
  196. package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
  197. package/corpus/templates/dispatch/app/routes/settings.tsx +2 -2
  198. package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
  199. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +5 -0
  200. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
  201. package/corpus/templates/forms/.agents/skills/security/SKILL.md +7 -0
  202. package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +5 -1
  203. package/corpus/templates/forms/AGENTS.md +4 -0
  204. package/corpus/templates/forms/app/routes/_app.settings.tsx +2 -2
  205. package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
  206. package/corpus/templates/forms/shared/navigation.ts +1 -1
  207. package/corpus/templates/macros/.agents/skills/security/SKILL.md +7 -0
  208. package/corpus/templates/macros/AGENTS.md +4 -0
  209. package/corpus/templates/macros/app/routes/settings.tsx +2 -2
  210. package/corpus/templates/macros/app/routes/team.tsx +1 -1
  211. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +5 -0
  212. package/corpus/templates/mail/.agents/skills/email-drafts/SKILL.md +1 -1
  213. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
  214. package/corpus/templates/mail/.agents/skills/security/SKILL.md +7 -0
  215. package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +5 -1
  216. package/corpus/templates/mail/AGENTS.md +4 -0
  217. package/corpus/templates/mail/changelog/2026-07-08-mail-attachments-in-hosted-environments-now-require-file-sto.md +6 -0
  218. package/corpus/templates/mail/server/handlers/media.ts +26 -1
  219. package/corpus/templates/mail/server/lib/outgoing-email.ts +24 -1
  220. package/corpus/templates/mail/server/lib/upload-store.ts +2 -1
  221. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +5 -0
  222. package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
  223. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
  224. package/corpus/templates/plan/.agents/skills/security/SKILL.md +7 -0
  225. package/corpus/templates/plan/AGENTS.md +4 -0
  226. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
  227. package/corpus/templates/plan/app/routes/settings.tsx +2 -2
  228. package/corpus/templates/plan/app/routes/team.tsx +1 -1
  229. package/corpus/templates/plan/changelog/2026-07-08-hosted-plan-images-now-require-connected-storage.md +6 -0
  230. package/corpus/templates/plan/server/lib/plan-assets.ts +33 -4
  231. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +5 -0
  232. package/corpus/templates/slides/.agents/skills/security/SKILL.md +7 -0
  233. package/corpus/templates/slides/AGENTS.md +4 -0
  234. package/corpus/templates/slides/actions/generate-image-api.ts +15 -3
  235. package/corpus/templates/slides/app/routes/settings.tsx +2 -2
  236. package/corpus/templates/slides/app/routes/team.tsx +1 -1
  237. package/corpus/templates/slides/changelog/2026-07-08-generated-slide-images-now-return-hosted-file-storage-urls-i.md +6 -0
  238. package/corpus/templates/slides/shared/api.ts +1 -1
  239. package/dist/application-state/store.d.ts.map +1 -1
  240. package/dist/application-state/store.js +8 -2
  241. package/dist/application-state/store.js.map +1 -1
  242. package/dist/client/AssistantChat.d.ts.map +1 -1
  243. package/dist/client/AssistantChat.js +24 -13
  244. package/dist/client/AssistantChat.js.map +1 -1
  245. package/dist/client/PoweredByBadge.d.ts +1 -1
  246. package/dist/client/PoweredByBadge.d.ts.map +1 -1
  247. package/dist/client/PoweredByBadge.js +3 -9
  248. package/dist/client/PoweredByBadge.js.map +1 -1
  249. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  250. package/dist/client/agent-chat-adapter.js +28 -9
  251. package/dist/client/agent-chat-adapter.js.map +1 -1
  252. package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
  253. package/dist/client/chat/widgets/DataTableWidget.js +19 -2
  254. package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
  255. package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
  256. package/dist/client/db-admin/TableEditor.js +19 -2
  257. package/dist/client/db-admin/TableEditor.js.map +1 -1
  258. package/dist/client/db-admin/export-utils.d.ts +2 -0
  259. package/dist/client/db-admin/export-utils.d.ts.map +1 -1
  260. package/dist/client/db-admin/export-utils.js +11 -3
  261. package/dist/client/db-admin/export-utils.js.map +1 -1
  262. package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
  263. package/dist/client/db-admin/useAgentSync.js +63 -0
  264. package/dist/client/db-admin/useAgentSync.js.map +1 -1
  265. package/dist/client/error-capture.d.ts.map +1 -1
  266. package/dist/client/error-capture.js +41 -7
  267. package/dist/client/error-capture.js.map +1 -1
  268. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  269. package/dist/client/extensions/EmbeddedExtension.js +3 -1
  270. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  271. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  272. package/dist/client/extensions/ExtensionViewer.js +32 -5
  273. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  274. package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
  275. package/dist/client/extensions/InlineExtensionFrame.js +3 -1
  276. package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
  277. package/dist/client/extensions/portable-extension.d.ts.map +1 -1
  278. package/dist/client/extensions/portable-extension.js +1 -0
  279. package/dist/client/extensions/portable-extension.js.map +1 -1
  280. package/dist/client/org/OrgSwitcher.d.ts +1 -1
  281. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  282. package/dist/client/org/OrgSwitcher.js +11 -6
  283. package/dist/client/org/OrgSwitcher.js.map +1 -1
  284. package/dist/client/org/TeamPage.d.ts.map +1 -1
  285. package/dist/client/org/TeamPage.js +5 -5
  286. package/dist/client/org/TeamPage.js.map +1 -1
  287. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  288. package/dist/client/settings/SettingsPanel.js +37 -14
  289. package/dist/client/settings/SettingsPanel.js.map +1 -1
  290. package/dist/client/settings/SettingsSection.js +1 -1
  291. package/dist/client/settings/SettingsSection.js.map +1 -1
  292. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  293. package/dist/client/settings/SettingsTabsPage.js +21 -10
  294. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  295. package/dist/collab/routes.d.ts +1 -1
  296. package/dist/db-admin/agent-tools.d.ts.map +1 -1
  297. package/dist/db-admin/agent-tools.js +7 -2
  298. package/dist/db-admin/agent-tools.js.map +1 -1
  299. package/dist/db-admin/operations.d.ts.map +1 -1
  300. package/dist/db-admin/operations.js +90 -4
  301. package/dist/db-admin/operations.js.map +1 -1
  302. package/dist/db-admin/routes.d.ts.map +1 -1
  303. package/dist/db-admin/routes.js +1 -0
  304. package/dist/db-admin/routes.js.map +1 -1
  305. package/dist/db-admin/types.d.ts +4 -0
  306. package/dist/db-admin/types.d.ts.map +1 -1
  307. package/dist/db-admin/types.js.map +1 -1
  308. package/dist/extensions/html-shell.d.ts +5 -4
  309. package/dist/extensions/html-shell.d.ts.map +1 -1
  310. package/dist/extensions/html-shell.js.map +1 -1
  311. package/dist/extensions/routes.d.ts.map +1 -1
  312. package/dist/extensions/routes.js +8 -0
  313. package/dist/extensions/routes.js.map +1 -1
  314. package/dist/navigation/index.d.ts +1 -1
  315. package/dist/navigation/index.d.ts.map +1 -1
  316. package/dist/navigation/index.js +1 -1
  317. package/dist/navigation/index.js.map +1 -1
  318. package/dist/notifications/routes.d.ts +1 -1
  319. package/dist/observability/routes.d.ts +1 -1
  320. package/dist/resources/handlers.d.ts +6 -1
  321. package/dist/resources/handlers.d.ts.map +1 -1
  322. package/dist/resources/handlers.js +9 -8
  323. package/dist/resources/handlers.js.map +1 -1
  324. package/dist/server/poll.d.ts +12 -4
  325. package/dist/server/poll.d.ts.map +1 -1
  326. package/dist/server/poll.js +236 -9
  327. package/dist/server/poll.js.map +1 -1
  328. package/dist/styles/agent-native.css +27 -0
  329. package/dist/templates/default/.agents/skills/actions/SKILL.md +5 -0
  330. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  331. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  332. package/dist/templates/default/.agents/skills/security/SKILL.md +7 -0
  333. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  334. package/dist/templates/default/AGENTS.md +4 -2
  335. package/dist/templates/headless/AGENTS.md +4 -0
  336. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  337. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  338. package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  339. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  340. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  341. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  342. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  343. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  344. package/dist/templates/workspace-core/AGENTS.md +7 -1
  345. package/dist/templates/workspace-root/AGENTS.md +7 -1
  346. package/package.json +1 -1
  347. package/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
  348. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  349. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  350. package/src/templates/default/.agents/skills/security/SKILL.md +7 -0
  351. package/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  352. package/src/templates/default/AGENTS.md +4 -2
  353. package/src/templates/headless/AGENTS.md +4 -0
  354. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  355. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  356. package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  357. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  358. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  359. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  360. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  361. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  362. package/src/templates/workspace-core/AGENTS.md +7 -1
  363. package/src/templates/workspace-root/AGENTS.md +7 -1
@@ -1,5 +1,5 @@
1
1
  import { Navigate } from "react-router";
2
2
 
3
3
  export default function TeamRoute() {
4
- return <Navigate to="/settings#team" replace />;
4
+ return <Navigate to="/settings#organization" replace />;
5
5
  }
@@ -377,6 +377,11 @@ Most operations should be actions. You only need custom routes in `server/routes
377
377
  - **Webhooks** — external services POST to a specific URL
378
378
  - **OAuth callbacks** — redirect-based flows that need specific URL patterns
379
379
 
380
+ When the agent needs a durable image or file URL, call the core `upload-image`
381
+ action or use `uploadFile()` in server code. Do not write base64 into SQL,
382
+ markdown, deck/design JSON, or action results. `_agentImages` on action results
383
+ is for ephemeral vision previews only, not persistence.
384
+
380
385
  If it's a standard CRUD operation, data query, or a wrapper around an action, use the action instead.
381
386
 
382
387
  ## Legacy Pattern (bare export)
@@ -50,7 +50,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
50
50
 
51
51
  For list/sidebar queries, use the same pattern — pass the counter into the queryKey of every list query you want to keep fresh.
52
52
 
53
- 4. **Fallback** polling calls `/_agent-native/poll?since=N`. It runs every 2 seconds until SSE is connected, then relaxes to 15 seconds (`SSE_FALLBACK_INTERVAL_MS`). If SSE is disabled or unavailable (e.g., edge/serverless deployments), polling continues at the 2 s cadence. Polling is the universal serverless fallback it detects DB timestamp changes even when the write happened in a different process or invocation.
53
+ 4. **Fallback** polling calls `/_agent-native/poll?since=N`. It runs every 2 seconds until SSE is connected, then relaxes to 15 seconds (`SSE_FALLBACK_INTERVAL_MS`). If SSE is disabled or unavailable (e.g., edge/serverless deployments), polling continues at the 2 s cadence. Polling is the universal serverless fallback: new framework writes are read from the durable `sync_events` log, while the older DB timestamp scan remains as a slower safety net for direct SQL writes and older processes.
54
54
 
55
55
  5. When the agent writes to the database, the version increments, SSE/polling detects it, and React Query refetches the affected queries.
56
56
 
@@ -51,6 +51,13 @@ export default defineAction({
51
51
 
52
52
  The legacy `parameters:` field (plain JSON Schema) has no runtime validation — do not use it for new code.
53
53
 
54
+ ## Large Payloads
55
+
56
+ Do not accept or persist unbounded base64/file blobs through actions, SQL writes,
57
+ or `application_state`. Route uploads through the file-upload provider and store
58
+ references. This prevents database bloat, slow hot paths, and accidental secret
59
+ or customer-data embedding inside binary payloads.
60
+
54
61
  ## SQL Injection
55
62
 
56
63
  Never concatenate user input into SQL strings. Use Drizzle ORM's query builder (always safe) or parameterized queries:
@@ -13,7 +13,9 @@ metadata:
13
13
 
14
14
  ## Rule
15
15
 
16
- All application data lives in **SQL** (SQLite locally, persistent database in production). The agent and UI share the same database. Do not store durable app data in the filesystem unless the app is explicitly running a Local File Mode artifact flow described below.
16
+ All application data lives in **SQL** (SQLite locally, persistent database in production). The agent and UI share the same database. SQL stores structured records, metadata, references, and searchable text — not large raw file payloads. Do not store durable app data in the filesystem unless the app is explicitly running a Local File Mode artifact flow described below.
17
+
18
+ Large binary or file-like payloads (images, video/audio, PDFs, ZIPs, screenshots, session replay chunks, thumbnails, generated assets, `data:` URLs, and base64 file bodies) must go through configured file/blob storage such as `uploadFile()` or `putPrivateBlob()`. Persist only the returned URL, asset id, or opaque blob handle in SQL. If storage is unavailable in hosted or persistent-database mode, fail closed with setup guidance instead of falling back to base64 in `application_state`, `settings`, `resources`, or app tables. Local SQLite-only dev fallbacks may exist for tiny assets, but they must be capped, documented as dev-only, and kept off hot list/read paths.
17
19
 
18
20
  **Local File Mode exception:** some artifact apps (Content, Plans, Slides, Dashboards, Designs, etc.) can intentionally use repo files as the source of truth for the artifact itself. This must be explicit via `agent-native.json`, `AGENT_NATIVE_MODE=local-files`, or an app-owned local-file action helper. In that mode, the UI and agent still go through app actions, but those actions read/write scoped files through `@agent-native/core/local-artifacts` instead of SQL rows. App state, auth, settings, credentials, collaboration metadata, and hosted database mode remain SQL. File-to-database or file-to-provider synchronization is an explicit sync step, not an implicit side effect of editing.
19
21
 
@@ -136,6 +138,7 @@ Polling streams database changes to the UI. When the agent writes to the databas
136
138
  - Use the `settings` store for app configuration and user preferences
137
139
  - Use `application-state` for ephemeral UI state that the agent and UI share
138
140
  - Use `oauth-tokens` for OAuth credentials
141
+ - Use `uploadFile()` or `putPrivateBlob()` for large files/blob data and store only URLs, ids, or handles in SQL
139
142
  - Use core DB scripts (`db-schema`, `db-query`, `db-exec`, `db-patch`) for ad-hoc database operations
140
143
  - Use `db-exec --statements` instead of several separate `db-exec` calls for related writes; it is faster and rolls back the whole batch if one statement fails
141
144
  - Reach for `db-patch` instead of `db-exec UPDATE` whenever you're making a small change to a large text/JSON column — it's much cheaper on tokens
@@ -146,6 +149,7 @@ Polling streams database changes to the UI. When the agent writes to the databas
146
149
  - Don't store app state in localStorage, sessionStorage, or cookies (except for UI-only preferences like sidebar width)
147
150
  - Don't keep state only in memory (server variables, global stores)
148
151
  - Don't use Redis or any external state store for app data
152
+ - Don't store large files, base64 blobs, `data:` URLs, screenshots, videos, audio, PDFs, ZIPs, or session replay chunks directly in SQL rows, `application_state`, `settings`, or `resources`
149
153
  - Don't implement product features with raw SQL or `getDbExec()` when Drizzle can express the query
150
154
  - Don't write SQLite-only or Postgres-only SQL in app code
151
155
  - Don't interpolate user input directly into SQL queries — use Drizzle ORM's query builder
@@ -11,6 +11,10 @@ Detailed building, publishing, response, storage, and UI rules live in
11
11
 
12
12
  ## Core Rules
13
13
 
14
+ - Store large file/blob payloads in configured file/blob storage, not SQL: no
15
+ base64, `data:` URLs, images, video/audio, PDFs, ZIPs, screenshots,
16
+ thumbnails, or replay chunks in app tables, `application_state`, `settings`,
17
+ or `resources`; persist URLs, ids, or handles instead.
14
18
  - Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
15
19
  - Use actions for form lifecycle, fields, publishing, responses, navigation,
16
20
  sharing, and database work. Do not bypass ownable access checks.
@@ -49,7 +49,7 @@ export default function SettingsRoute() {
49
49
  extraTabs={agentSettingsTabs}
50
50
  generalSearchEntries={generalSearchEntries}
51
51
  general={
52
- <div className="mx-auto w-full max-w-3xl space-y-6">
52
+ <div className="mx-auto w-full max-w-2xl space-y-6">
53
53
  <p className="text-sm leading-6 text-muted-foreground">
54
54
  {t("settings.description")}
55
55
  </p>
@@ -79,7 +79,7 @@ export default function SettingsRoute() {
79
79
  </div>
80
80
  }
81
81
  whatsNew={
82
- <div className="mx-auto w-full max-w-3xl">
82
+ <div className="mx-auto w-full max-w-2xl">
83
83
  <ChangelogSettingsCard markdown={changelog} />
84
84
  </div>
85
85
  }
@@ -5,5 +5,5 @@ export function meta() {
5
5
  }
6
6
 
7
7
  export default function TeamRoute() {
8
- return <Navigate to="/settings#team" replace />;
8
+ return <Navigate to="/settings#organization" replace />;
9
9
  }
@@ -73,7 +73,7 @@ export function formsRoutePath(target: FormsNavigationTarget): string | null {
73
73
  ? `/response-insights?formId=${encodeURIComponent(formId)}`
74
74
  : "/response-insights";
75
75
  case "team":
76
- return "/settings#team";
76
+ return "/settings#organization";
77
77
  case "extensions":
78
78
  return "/extensions";
79
79
  case "form-preview":
@@ -51,6 +51,13 @@ export default defineAction({
51
51
 
52
52
  The legacy `parameters:` field (plain JSON Schema) has no runtime validation — do not use it for new code.
53
53
 
54
+ ## Large Payloads
55
+
56
+ Do not accept or persist unbounded base64/file blobs through actions, SQL writes,
57
+ or `application_state`. Route uploads through the file-upload provider and store
58
+ references. This prevents database bloat, slow hot paths, and accidental secret
59
+ or customer-data embedding inside binary payloads.
60
+
54
61
  ## SQL Injection
55
62
 
56
63
  Never concatenate user input into SQL strings. Use Drizzle ORM's query builder (always safe) or parameterized queries:
@@ -6,6 +6,10 @@ actions and SQL state.
6
6
 
7
7
  ## Core Rules
8
8
 
9
+ - Store large file/blob payloads in configured file/blob storage, not SQL: no
10
+ base64, `data:` URLs, images, video/audio, PDFs, ZIPs, screenshots,
11
+ thumbnails, or replay chunks in app tables, `application_state`, `settings`,
12
+ or `resources`; persist URLs, ids, or handles instead.
9
13
  - Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
10
14
  - Use actions for meals, foods, calorie/macro updates, voice command handling,
11
15
  stats, and navigation. Do not mutate app tables directly.
@@ -49,7 +49,7 @@ export default function SettingsRoute() {
49
49
  extraTabs={agentSettingsTabs}
50
50
  generalSearchEntries={generalSearchEntries}
51
51
  general={
52
- <div className="mx-auto w-full max-w-3xl space-y-6">
52
+ <div className="mx-auto w-full max-w-2xl space-y-6">
53
53
  <p className="text-sm leading-6 text-muted-foreground">
54
54
  {t("settings.description")}
55
55
  </p>
@@ -79,7 +79,7 @@ export default function SettingsRoute() {
79
79
  </div>
80
80
  }
81
81
  whatsNew={
82
- <div className="mx-auto w-full max-w-3xl">
82
+ <div className="mx-auto w-full max-w-2xl">
83
83
  <ChangelogSettingsCard markdown={changelog} />
84
84
  </div>
85
85
  }
@@ -7,5 +7,5 @@ export function meta() {
7
7
  }
8
8
 
9
9
  export default function TeamRoute() {
10
- return <Navigate to="/settings#team" replace />;
10
+ return <Navigate to="/settings#organization" replace />;
11
11
  }
@@ -377,6 +377,11 @@ Most operations should be actions. You only need custom routes in `server/routes
377
377
  - **Webhooks** — external services POST to a specific URL
378
378
  - **OAuth callbacks** — redirect-based flows that need specific URL patterns
379
379
 
380
+ When the agent needs a durable image or file URL, call the core `upload-image`
381
+ action or use `uploadFile()` in server code. Do not write base64 into SQL,
382
+ markdown, deck/design JSON, or action results. `_agentImages` on action results
383
+ is for ephemeral vision previews only, not persistence.
384
+
380
385
  If it's a standard CRUD operation, data query, or a wrapper around an action, use the action instead.
381
386
 
382
387
  ## Legacy Pattern (bare export)
@@ -119,7 +119,7 @@ const drafts = await listAppState("compose-");
119
119
 
120
120
  ## Attaching Files
121
121
 
122
- The `send-email` action accepts an optional `attachments` array. Each entry must reference a file that was previously uploaded via the media-upload endpoint (`/api/media/upload`). Pass the server-side `filename` (the key returned by the upload endpoint, e.g. `abc123.pdf`), and optionally `originalName` (display name for the recipient) and `mimeType`. The attachment plumbing resolves the file from the upload store (falling back to `data/uploads/`) and includes it as a MIME multipart attachment in the outgoing Gmail message. Files are never sent speculatively — only attach what the user has explicitly provided and confirmed.
122
+ The `send-email` action accepts an optional `attachments` array. Each entry must reference a file that was previously uploaded via the media-upload endpoint (`/api/media/upload`). Pass the server-side `filename` (the key returned by the upload endpoint, e.g. `abc123.pdf`), and optionally `originalName` (display name for the recipient) and `mimeType`. The attachment plumbing resolves the file from `data/uploads/` or from the configured file-storage URL recorded by the upload endpoint, then includes it as a MIME multipart attachment in the outgoing Gmail message. Do not store or paste attachment bytes, base64, or `data:` URLs in draft state/settings; files are never sent speculatively — only attach what the user has explicitly provided and confirmed.
123
123
 
124
124
  Example:
125
125
  ```json
@@ -50,7 +50,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
50
50
 
51
51
  For list/sidebar queries, use the same pattern — pass the counter into the queryKey of every list query you want to keep fresh.
52
52
 
53
- 4. **Fallback** polling calls `/_agent-native/poll?since=N`. It runs every 2 seconds until SSE is connected, then relaxes to 15 seconds (`SSE_FALLBACK_INTERVAL_MS`). If SSE is disabled or unavailable (e.g., edge/serverless deployments), polling continues at the 2 s cadence. Polling is the universal serverless fallback it detects DB timestamp changes even when the write happened in a different process or invocation.
53
+ 4. **Fallback** polling calls `/_agent-native/poll?since=N`. It runs every 2 seconds until SSE is connected, then relaxes to 15 seconds (`SSE_FALLBACK_INTERVAL_MS`). If SSE is disabled or unavailable (e.g., edge/serverless deployments), polling continues at the 2 s cadence. Polling is the universal serverless fallback: new framework writes are read from the durable `sync_events` log, while the older DB timestamp scan remains as a slower safety net for direct SQL writes and older processes.
54
54
 
55
55
  5. When the agent writes to the database, the version increments, SSE/polling detects it, and React Query refetches the affected queries.
56
56
 
@@ -51,6 +51,13 @@ export default defineAction({
51
51
 
52
52
  The legacy `parameters:` field (plain JSON Schema) has no runtime validation — do not use it for new code.
53
53
 
54
+ ## Large Payloads
55
+
56
+ Do not accept or persist unbounded base64/file blobs through actions, SQL writes,
57
+ or `application_state`. Route uploads through the file-upload provider and store
58
+ references. This prevents database bloat, slow hot paths, and accidental secret
59
+ or customer-data embedding inside binary payloads.
60
+
54
61
  ## SQL Injection
55
62
 
56
63
  Never concatenate user input into SQL strings. Use Drizzle ORM's query builder (always safe) or parameterized queries:
@@ -13,7 +13,9 @@ metadata:
13
13
 
14
14
  ## Rule
15
15
 
16
- All application data lives in **SQL** (SQLite locally, persistent database in production). The agent and UI share the same database. Do not store durable app data in the filesystem unless the app is explicitly running a Local File Mode artifact flow described below.
16
+ All application data lives in **SQL** (SQLite locally, persistent database in production). The agent and UI share the same database. SQL stores structured records, metadata, references, and searchable text — not large raw file payloads. Do not store durable app data in the filesystem unless the app is explicitly running a Local File Mode artifact flow described below.
17
+
18
+ Large binary or file-like payloads (images, video/audio, PDFs, ZIPs, screenshots, session replay chunks, thumbnails, generated assets, `data:` URLs, and base64 file bodies) must go through configured file/blob storage such as `uploadFile()` or `putPrivateBlob()`. Persist only the returned URL, asset id, or opaque blob handle in SQL. If storage is unavailable in hosted or persistent-database mode, fail closed with setup guidance instead of falling back to base64 in `application_state`, `settings`, `resources`, or app tables. Local SQLite-only dev fallbacks may exist for tiny assets, but they must be capped, documented as dev-only, and kept off hot list/read paths.
17
19
 
18
20
  **Local File Mode exception:** some artifact apps (Content, Plans, Slides, Dashboards, Designs, etc.) can intentionally use repo files as the source of truth for the artifact itself. This must be explicit via `agent-native.json`, `AGENT_NATIVE_MODE=local-files`, or an app-owned local-file action helper. In that mode, the UI and agent still go through app actions, but those actions read/write scoped files through `@agent-native/core/local-artifacts` instead of SQL rows. App state, auth, settings, credentials, collaboration metadata, and hosted database mode remain SQL. File-to-database or file-to-provider synchronization is an explicit sync step, not an implicit side effect of editing.
19
21
 
@@ -136,6 +138,7 @@ Polling streams database changes to the UI. When the agent writes to the databas
136
138
  - Use the `settings` store for app configuration and user preferences
137
139
  - Use `application-state` for ephemeral UI state that the agent and UI share
138
140
  - Use `oauth-tokens` for OAuth credentials
141
+ - Use `uploadFile()` or `putPrivateBlob()` for large files/blob data and store only URLs, ids, or handles in SQL
139
142
  - Use core DB scripts (`db-schema`, `db-query`, `db-exec`, `db-patch`) for ad-hoc database operations
140
143
  - Use `db-exec --statements` instead of several separate `db-exec` calls for related writes; it is faster and rolls back the whole batch if one statement fails
141
144
  - Reach for `db-patch` instead of `db-exec UPDATE` whenever you're making a small change to a large text/JSON column — it's much cheaper on tokens
@@ -146,6 +149,7 @@ Polling streams database changes to the UI. When the agent writes to the databas
146
149
  - Don't store app state in localStorage, sessionStorage, or cookies (except for UI-only preferences like sidebar width)
147
150
  - Don't keep state only in memory (server variables, global stores)
148
151
  - Don't use Redis or any external state store for app data
152
+ - Don't store large files, base64 blobs, `data:` URLs, screenshots, videos, audio, PDFs, ZIPs, or session replay chunks directly in SQL rows, `application_state`, `settings`, or `resources`
149
153
  - Don't implement product features with raw SQL or `getDbExec()` when Drizzle can express the query
150
154
  - Don't write SQLite-only or Postgres-only SQL in app code
151
155
  - Don't interpolate user input directly into SQL queries — use Drizzle ORM's query builder
@@ -9,6 +9,10 @@ Detailed draft, queue, and contact-resolution patterns live in
9
9
 
10
10
  ## Core Rules
11
11
 
12
+ - Store large file/blob payloads in configured file/blob storage, not SQL: no
13
+ base64, `data:` URLs, images, video/audio, PDFs, ZIPs, screenshots,
14
+ thumbnails, or replay chunks in app tables, `application_state`, `settings`,
15
+ or `resources`; persist URLs, ids, or handles instead.
12
16
  - Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
13
17
  - Use actions for email reads, labels, settings, drafts, queued drafts, filters,
14
18
  scheduling, refresh, and CRM context. Do not edit mail SQL directly unless a
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Mail attachments in hosted environments now require file storage instead of falling back to database-stored file bytes.
@@ -1,12 +1,14 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
 
4
+ import { uploadFile } from "@agent-native/core/file-upload";
4
5
  import { streamFile, getSession } from "@agent-native/core/server";
5
6
  import {
6
7
  defineEventHandler,
7
8
  getQuery,
8
9
  readRawBody,
9
10
  getRouterParam,
11
+ sendRedirect,
10
12
  setResponseStatus,
11
13
  setResponseHeader,
12
14
  type H3Event,
@@ -82,11 +84,27 @@ export const uploadMedia = defineEventHandler(async (event: H3Event) => {
82
84
  try {
83
85
  fs.writeFileSync(filePath, body);
84
86
  } catch {
87
+ const uploaded = await uploadFile({
88
+ data: body instanceof Uint8Array ? body : new Uint8Array(body),
89
+ filename: originalName,
90
+ mimeType,
91
+ ownerEmail: session.email,
92
+ recordAsset: false,
93
+ });
94
+ if (!uploaded?.url) {
95
+ setResponseStatus(event, 503);
96
+ return {
97
+ error:
98
+ "File storage is not configured. Connect Builder.io or another upload provider before attaching files in hosted environments.",
99
+ storageSetupRequired: true,
100
+ };
101
+ }
85
102
  await putStoredUpload(session.email, {
86
103
  ...payload,
87
- dataBase64: Buffer.from(body).toString("base64"),
104
+ url: uploaded.url,
88
105
  createdAt: Date.now(),
89
106
  });
107
+ return { ...payload, url: uploaded.url, provider: uploaded.provider };
90
108
  }
91
109
 
92
110
  return payload;
@@ -118,6 +136,13 @@ export const serveMedia = defineEventHandler(async (event: H3Event) => {
118
136
  setResponseStatus(event, 404);
119
137
  return { error: "File not found" };
120
138
  }
139
+ if (stored.url) {
140
+ return sendRedirect(event, stored.url, 302);
141
+ }
142
+ if (!stored.dataBase64) {
143
+ setResponseStatus(event, 404);
144
+ return { error: "File data not found" };
145
+ }
121
146
 
122
147
  setResponseHeader(event, "Content-Type", stored.mimeType);
123
148
  setResponseHeader(
@@ -17,6 +17,7 @@ import {
17
17
  import { getStoredUpload } from "./upload-store.js";
18
18
 
19
19
  const UPLOADS_DIR = path.resolve("data/uploads");
20
+ const MAX_ATTACHMENT_FETCH_BYTES = 15 * 1024 * 1024;
20
21
 
21
22
  export type ResolvedComposeAttachment = ComposeAttachment & {
22
23
  data: Buffer;
@@ -32,6 +33,22 @@ function stripCrlf(value: string): string {
32
33
  return value.replace(/[\r\n]+/g, " ").trim();
33
34
  }
34
35
 
36
+ async function fetchStoredUpload(url: string): Promise<Buffer> {
37
+ const response = await fetch(url);
38
+ if (!response.ok) {
39
+ throw new Error(`Stored upload fetch failed: ${response.status}`);
40
+ }
41
+ const contentLength = Number(response.headers.get("content-length") || "0");
42
+ if (contentLength > MAX_ATTACHMENT_FETCH_BYTES) {
43
+ throw new Error("Stored upload is too large to attach");
44
+ }
45
+ const bytes = Buffer.from(await response.arrayBuffer());
46
+ if (bytes.byteLength > MAX_ATTACHMENT_FETCH_BYTES) {
47
+ throw new Error("Stored upload is too large to attach");
48
+ }
49
+ return bytes;
50
+ }
51
+
35
52
  function safeHeaderParam(value: string): string {
36
53
  return stripCrlf(value).replace(/["\\]/g, "_") || "attachment";
37
54
  }
@@ -227,7 +244,13 @@ export async function resolveComposeAttachments(
227
244
  if (!ownerEmail) throw error;
228
245
  const stored = await getStoredUpload(ownerEmail, att.filename);
229
246
  if (!stored) throw error;
230
- data = Buffer.from(stored.dataBase64, "base64");
247
+ if (stored.url) {
248
+ data = await fetchStoredUpload(stored.url);
249
+ } else if (stored.dataBase64) {
250
+ data = Buffer.from(stored.dataBase64, "base64");
251
+ } else {
252
+ throw error;
253
+ }
231
254
  att.originalName = att.originalName || stored.originalName;
232
255
  att.mimeType = att.mimeType || stored.mimeType;
233
256
  att.size = att.size || stored.size;
@@ -8,7 +8,8 @@ export interface StoredUpload {
8
8
  mimeType: string;
9
9
  size: number;
10
10
  url?: string;
11
- dataBase64: string;
11
+ /** Legacy SQL fallback used by older uploads. New uploads store provider URLs. */
12
+ dataBase64?: string;
12
13
  createdAt: number;
13
14
  }
14
15
 
@@ -377,6 +377,11 @@ Most operations should be actions. You only need custom routes in `server/routes
377
377
  - **Webhooks** — external services POST to a specific URL
378
378
  - **OAuth callbacks** — redirect-based flows that need specific URL patterns
379
379
 
380
+ When the agent needs a durable image or file URL, call the core `upload-image`
381
+ action or use `uploadFile()` in server code. Do not write base64 into SQL,
382
+ markdown, deck/design JSON, or action results. `_agentImages` on action results
383
+ is for ephemeral vision previews only, not persistence.
384
+
380
385
  If it's a standard CRUD operation, data query, or a wrapper around an action, use the action instead.
381
386
 
382
387
  ## Legacy Pattern (bare export)
@@ -74,6 +74,11 @@ Builder/internal data, or customer data in the action, UI, seed data, fixtures,
74
74
  docs, prompts, or generated extension/app content. Register required secrets,
75
75
  use OAuth helpers, or read scoped values from the vault/credential store.
76
76
 
77
+ If the feature involves attachments, images, recordings, screenshots, exports,
78
+ or other file-like payloads, design the upload path in the same change:
79
+ provider upload first, then URL/id/blob handle in SQL. Do not add base64/binary
80
+ columns or stuff files into `application_state`.
81
+
77
82
  **If the action produces or lists a navigable resource**, add a `link` builder that returns `{ url: buildDeepLink({ app, view, params }), label }`. External coding agents and MCP hosts (Claude / ChatGPT / Claude Code / Cowork / Codex, over MCP/A2A) then surface an "Open in … →" deep link that drops the user back into the running UI focused on the record — for free. If a compatible MCP host should render an inline review/edit surface, also add `mcpApp` with `embedApp()` so the action embeds the real React app route instead of a one-off HTML UI. The `link` builder and `mcpApp` metadata must be pure and synchronous (no I/O). Any external-agent read/ingest action must be `http: { method: "GET" }` + `readOnly: true` + `publicAgent: { expose: true, readOnly: true, requiresAuth: true }`. See the `external-agents` skill.
78
83
 
79
84
  ### 3. Skills / Instructions
@@ -50,7 +50,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
50
50
 
51
51
  For list/sidebar queries, use the same pattern — pass the counter into the queryKey of every list query you want to keep fresh.
52
52
 
53
- 4. **Fallback** polling calls `/_agent-native/poll?since=N`. It runs every 2 seconds until SSE is connected, then relaxes to 15 seconds (`SSE_FALLBACK_INTERVAL_MS`). If SSE is disabled or unavailable (e.g., edge/serverless deployments), polling continues at the 2 s cadence. Polling is the universal serverless fallback it detects DB timestamp changes even when the write happened in a different process or invocation.
53
+ 4. **Fallback** polling calls `/_agent-native/poll?since=N`. It runs every 2 seconds until SSE is connected, then relaxes to 15 seconds (`SSE_FALLBACK_INTERVAL_MS`). If SSE is disabled or unavailable (e.g., edge/serverless deployments), polling continues at the 2 s cadence. Polling is the universal serverless fallback: new framework writes are read from the durable `sync_events` log, while the older DB timestamp scan remains as a slower safety net for direct SQL writes and older processes.
54
54
 
55
55
  5. When the agent writes to the database, the version increments, SSE/polling detects it, and React Query refetches the affected queries.
56
56
 
@@ -51,6 +51,13 @@ export default defineAction({
51
51
 
52
52
  The legacy `parameters:` field (plain JSON Schema) has no runtime validation — do not use it for new code.
53
53
 
54
+ ## Large Payloads
55
+
56
+ Do not accept or persist unbounded base64/file blobs through actions, SQL writes,
57
+ or `application_state`. Route uploads through the file-upload provider and store
58
+ references. This prevents database bloat, slow hot paths, and accidental secret
59
+ or customer-data embedding inside binary payloads.
60
+
54
61
  ## SQL Injection
55
62
 
56
63
  Never concatenate user input into SQL strings. Use Drizzle ORM's query builder (always safe) or parameterized queries:
@@ -7,6 +7,10 @@ review before code changes happen.
7
7
 
8
8
  ## Core Rules
9
9
 
10
+ - Store large file/blob payloads in configured file/blob storage, not SQL: no
11
+ base64, `data:` URLs, images, video/audio, PDFs, ZIPs, screenshots,
12
+ thumbnails, or replay chunks in app tables, `application_state`, `settings`,
13
+ or `resources`; persist URLs, ids, or handles instead.
10
14
  - Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
11
15
  - Follow the root framework rules: data in SQL, actions first, application
12
16
  state for navigation/selection, and shared agent chat for AI work.
@@ -195,7 +195,7 @@ function pathForView(view?: string): string {
195
195
  case "settings":
196
196
  return "/settings";
197
197
  case "team":
198
- return "/settings#team";
198
+ return "/settings#organization";
199
199
  default:
200
200
  return "/";
201
201
  }
@@ -56,7 +56,7 @@ export default function SettingsRoute() {
56
56
  extraTabs={agentSettingsTabs}
57
57
  generalSearchEntries={generalSearchEntries}
58
58
  general={
59
- <div className="mx-auto w-full max-w-3xl space-y-6">
59
+ <div className="mx-auto w-full max-w-2xl space-y-6">
60
60
  <p className="text-sm leading-6 text-muted-foreground">
61
61
  {t("settings.description")}
62
62
  </p>
@@ -108,7 +108,7 @@ export default function SettingsRoute() {
108
108
  </div>
109
109
  }
110
110
  whatsNew={
111
- <div className="mx-auto w-full max-w-3xl">
111
+ <div className="mx-auto w-full max-w-2xl">
112
112
  <ChangelogSettingsCard markdown={changelog} />
113
113
  </div>
114
114
  }
@@ -7,5 +7,5 @@ export function meta() {
7
7
  }
8
8
 
9
9
  export default function TeamRoute() {
10
- return <Navigate to="/settings#team" replace />;
10
+ return <Navigate to="/settings#organization" replace />;
11
11
  }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Hosted visual plan images now require connected storage instead of saving image files in SQL.
@@ -32,6 +32,8 @@ export {
32
32
 
33
33
  /** The route prefix under which plan assets are served. */
34
34
  export const PLAN_ASSET_ROUTE_PREFIX = "/_agent-native/plan-asset";
35
+ const PLAN_ASSET_STORAGE_REQUIRED_REASON =
36
+ "Image storage is not connected yet. Connect Builder.io or configure S3-compatible storage to add images to visual plans.";
35
37
 
36
38
  /**
37
39
  * Build the serving URL for an asset stored in the `plan_assets` table.
@@ -55,21 +57,44 @@ export interface UpsertPlanAssetResult {
55
57
  assetId: string;
56
58
  /**
57
59
  * A CDN URL when an upload provider was configured and the upload succeeded.
58
- * `null` when falling back to the local `plan_assets` table.
60
+ * `null` only for local-development fallback rows in `plan_assets`.
59
61
  */
60
62
  cdnUrl: string | null;
61
63
  /**
62
64
  * The final `src` to embed in the image block.
63
65
  * - CDN URL when provider upload succeeded.
64
- * - Local route URL (`/_agent-native/plan-asset/...`) otherwise.
66
+ * - Local route URL (`/_agent-native/plan-asset/...`) for dev fallback rows.
65
67
  */
66
68
  src: string;
67
69
  filename: string;
68
70
  }
69
71
 
72
+ function requiresConfiguredPlanAssetStorage(): boolean {
73
+ return process.env.NODE_ENV === "production" || !isLocalPlanAssetDatabase();
74
+ }
75
+
76
+ function appDatabaseUrl(): string {
77
+ const appName = process.env.APP_NAME?.toUpperCase().replace(/-/g, "_");
78
+ if (appName) {
79
+ const appUrl = process.env[`${appName}_DATABASE_URL`];
80
+ if (appUrl) return appUrl;
81
+ }
82
+ return process.env.DATABASE_URL || process.env.NETLIFY_DATABASE_URL || "";
83
+ }
84
+
85
+ function isLocalPlanAssetDatabase(): boolean {
86
+ const url = appDatabaseUrl().toLowerCase();
87
+ return (
88
+ url === "" ||
89
+ url.startsWith("file:") ||
90
+ url.startsWith("pglite:") ||
91
+ !url.includes("://")
92
+ );
93
+ }
94
+
70
95
  /**
71
96
  * Store a plan asset, uploading via the active file-upload provider first.
72
- * Falls back to the `plan_assets` SQL table when no provider is configured.
97
+ * Falls back to the `plan_assets` SQL table only on local databases.
73
98
  *
74
99
  * Enforces single-asset and per-plan size caps.
75
100
  */
@@ -130,7 +155,11 @@ export async function upsertPlanAsset(
130
155
  };
131
156
  }
132
157
 
133
- // SQL fallback: store base64 in plan_assets.
158
+ if (requiresConfiguredPlanAssetStorage()) {
159
+ throw new Error(PLAN_ASSET_STORAGE_REQUIRED_REASON);
160
+ }
161
+
162
+ // Local SQL fallback: store base64 in plan_assets for development-only use.
134
163
  const assetId = `passet_${randomUUID().replace(/-/g, "")}`;
135
164
  const now = new Date().toISOString();
136
165
  await db.insert(schema.planAssets).values({
@@ -377,6 +377,11 @@ Most operations should be actions. You only need custom routes in `server/routes
377
377
  - **Webhooks** — external services POST to a specific URL
378
378
  - **OAuth callbacks** — redirect-based flows that need specific URL patterns
379
379
 
380
+ When the agent needs a durable image or file URL, call the core `upload-image`
381
+ action or use `uploadFile()` in server code. Do not write base64 into SQL,
382
+ markdown, deck/design JSON, or action results. `_agentImages` on action results
383
+ is for ephemeral vision previews only, not persistence.
384
+
380
385
  If it's a standard CRUD operation, data query, or a wrapper around an action, use the action instead.
381
386
 
382
387
  ## Legacy Pattern (bare export)
@@ -51,6 +51,13 @@ export default defineAction({
51
51
 
52
52
  The legacy `parameters:` field (plain JSON Schema) has no runtime validation — do not use it for new code.
53
53
 
54
+ ## Large Payloads
55
+
56
+ Do not accept or persist unbounded base64/file blobs through actions, SQL writes,
57
+ or `application_state`. Route uploads through the file-upload provider and store
58
+ references. This prevents database bloat, slow hot paths, and accidental secret
59
+ or customer-data embedding inside binary payloads.
60
+
54
61
  ## SQL Injection
55
62
 
56
63
  Never concatenate user input into SQL strings. Use Drizzle ORM's query builder (always safe) or parameterized queries:
@@ -9,6 +9,10 @@ Detailed deck, slide-editing, image, design-system, and export workflows live in
9
9
 
10
10
  ## Core Rules
11
11
 
12
+ - Store large file/blob payloads in configured file/blob storage, not SQL: no
13
+ base64, `data:` URLs, images, video/audio, PDFs, ZIPs, screenshots,
14
+ thumbnails, or replay chunks in app tables, `application_state`, `settings`,
15
+ or `resources`; persist URLs, ids, or handles instead.
12
16
  - Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
13
17
  - Use actions for deck lifecycle, slide edits, imports, exports, images, design
14
18
  systems, and sharing. Do not write deck/slide rows directly.