@agent-native/core 0.137.8 → 0.139.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (472) hide show
  1. package/agent-native.eject.json +2 -0
  2. package/corpus/README.md +1 -1
  3. package/corpus/templates/analytics/.agents/skills/agent-native-docs/SKILL.md +23 -3
  4. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  5. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +15 -0
  6. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +23 -2
  7. package/corpus/templates/analytics/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  8. package/corpus/templates/analytics/AGENTS.md +2 -2
  9. package/corpus/templates/analytics/actions/get-first-party-analytics-health.ts +65 -0
  10. package/corpus/templates/analytics/actions/provider-api-catalog.ts +3 -6
  11. package/corpus/templates/analytics/actions/provider-api-docs.ts +3 -6
  12. package/corpus/templates/analytics/actions/provider-api-request.ts +3 -6
  13. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +3 -3
  14. package/corpus/templates/analytics/agent-native.json +12 -0
  15. package/corpus/templates/analytics/app/i18n-data.ts +162 -0
  16. package/corpus/templates/analytics/app/pages/DataSources.tsx +126 -1
  17. package/corpus/templates/analytics/changelog/2026-08-05-analytics-now-flags-neon-pressure-and-guides-high-volume-tra.md +6 -0
  18. package/corpus/templates/analytics/changelog/2026-08-05-first-party-analytics-uses-compact-rollups-for-faster-usage-.md +6 -0
  19. package/corpus/templates/analytics/server/db/schema.ts +52 -0
  20. package/corpus/templates/analytics/server/lib/credential-keys.ts +3 -0
  21. package/corpus/templates/analytics/server/lib/dashboard-report.ts +2 -0
  22. package/corpus/templates/analytics/server/lib/emails.ts +51 -0
  23. package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +397 -0
  24. package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +182 -0
  25. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +86 -15
  26. package/corpus/templates/analytics/server/lib/provider-api.ts +20 -1
  27. package/corpus/templates/analytics/server/lib/replay-storage.ts +1 -1
  28. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -0
  29. package/corpus/templates/analytics/server/plugins/db.ts +60 -0
  30. package/corpus/templates/analytics/server/plugins/transactional-emails.ts +5 -0
  31. package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +23 -3
  32. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  33. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +23 -2
  34. package/corpus/templates/assets/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  35. package/corpus/templates/assets/agent-native.json +12 -0
  36. package/corpus/templates/assets/server/lib/generation.ts +8 -8
  37. package/corpus/templates/assets/server/lib/storage.ts +1 -1
  38. package/corpus/templates/assets/server/plugins/onboarding.ts +1 -1
  39. package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +23 -3
  40. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  41. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +23 -2
  42. package/corpus/templates/brain/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  43. package/corpus/templates/brain/agent-native.json +12 -0
  44. package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +23 -3
  45. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  46. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +23 -2
  47. package/corpus/templates/calendar/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  48. package/corpus/templates/calendar/agent-native.json +12 -0
  49. package/corpus/templates/calendar/server/lib/booking-emails.ts +154 -70
  50. package/corpus/templates/calendar/server/lib/emails.ts +167 -0
  51. package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +64 -28
  52. package/corpus/templates/calendar/server/plugins/transactional-emails.ts +5 -0
  53. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  54. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  55. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  56. package/corpus/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  57. package/corpus/templates/chat/AGENTS.md +3 -0
  58. package/corpus/templates/chat/DESIGN.md +28 -0
  59. package/corpus/templates/chat/agent-native.json +12 -0
  60. package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +23 -3
  61. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  62. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +23 -2
  63. package/corpus/templates/clips/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  64. package/corpus/templates/clips/actions/cleanup-transcript.ts +2 -2
  65. package/corpus/templates/clips/actions/delete-recording-permanent.ts +3 -0
  66. package/corpus/templates/clips/actions/get-playback-position.ts +68 -0
  67. package/corpus/templates/clips/actions/import-loom-recording.ts +2 -2
  68. package/corpus/templates/clips/actions/invite-member.ts +39 -15
  69. package/corpus/templates/clips/actions/save-playback-position.ts +80 -0
  70. package/corpus/templates/clips/actions/set-thumbnail.ts +1 -1
  71. package/corpus/templates/clips/agent-native.json +12 -0
  72. package/corpus/templates/clips/app/components/player/video-player.tsx +54 -5
  73. package/corpus/templates/clips/app/hooks/use-playback-position.ts +188 -0
  74. package/corpus/templates/clips/app/hooks/use-view-tracking.ts +6 -24
  75. package/corpus/templates/clips/app/lib/playback-position.ts +99 -0
  76. package/corpus/templates/clips/app/lib/viewer-session.ts +29 -0
  77. package/corpus/templates/clips/changelog/2026-08-05-clip-buffering-now-uses-buffering-copy-after-playback.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-08-05-clips-remembers-your-playback-position-when-you-reopen-a-cli.md +6 -0
  79. package/corpus/templates/clips/learnings.defaults.md +1 -1
  80. package/corpus/templates/clips/server/db/schema.ts +18 -0
  81. package/corpus/templates/clips/server/lib/emails.ts +256 -0
  82. package/corpus/templates/clips/server/lib/public-agent-context.ts +1 -1
  83. package/corpus/templates/clips/server/lib/transactional-email-templates.ts +24 -0
  84. package/corpus/templates/clips/server/lib/video-storage.ts +1 -1
  85. package/corpus/templates/clips/server/plugins/db.ts +15 -0
  86. package/corpus/templates/clips/server/plugins/transactional-email-catalog.ts +5 -0
  87. package/corpus/templates/clips/server/routes/api/media/index.post.ts +1 -1
  88. package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +23 -3
  89. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  90. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +13 -0
  91. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +23 -2
  92. package/corpus/templates/content/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  93. package/corpus/templates/content/AGENTS.md +1 -0
  94. package/corpus/templates/content/actions/_content-database-mutation-lock.ts +41 -0
  95. package/corpus/templates/content/actions/_content-database-row-migration.ts +569 -0
  96. package/corpus/templates/content/actions/_database-source-utils.ts +82 -36
  97. package/corpus/templates/content/actions/_database-utils.ts +5 -0
  98. package/corpus/templates/content/actions/_delete-content-space.ts +25 -11
  99. package/corpus/templates/content/actions/add-database-item.ts +60 -42
  100. package/corpus/templates/content/actions/attach-content-database-source.ts +2 -0
  101. package/corpus/templates/content/actions/configure-document-property.ts +99 -104
  102. package/corpus/templates/content/actions/delete-content-database.ts +19 -7
  103. package/corpus/templates/content/actions/delete-document-property.ts +47 -58
  104. package/corpus/templates/content/actions/delete-document.ts +390 -167
  105. package/corpus/templates/content/actions/disconnect-content-database-source.ts +41 -24
  106. package/corpus/templates/content/actions/duplicate-database-item.ts +63 -31
  107. package/corpus/templates/content/actions/duplicate-database-items.ts +86 -43
  108. package/corpus/templates/content/actions/duplicate-document-property.ts +37 -14
  109. package/corpus/templates/content/actions/migrate-content-database-rows.ts +830 -0
  110. package/corpus/templates/content/actions/move-database-item.ts +14 -0
  111. package/corpus/templates/content/actions/permanently-delete-document.ts +27 -6
  112. package/corpus/templates/content/actions/remove-database-items.ts +13 -0
  113. package/corpus/templates/content/actions/reorder-document-property.ts +45 -46
  114. package/corpus/templates/content/actions/set-document-property.ts +68 -28
  115. package/corpus/templates/content/actions/submit-content-database-form.ts +49 -0
  116. package/corpus/templates/content/actions/transcribe-media.ts +1 -1
  117. package/corpus/templates/content/agent-native.json +12 -0
  118. package/corpus/templates/content/app/components/editor/image-upload.ts +2 -2
  119. package/corpus/templates/content/app/i18n-data.ts +1 -1
  120. package/corpus/templates/content/changelog/2026-08-01-content-can-reorganize-every-row-in-an-existing-database-as-.md +6 -0
  121. package/corpus/templates/content/parity/matrix.md +1 -1
  122. package/corpus/templates/content/parity/matrix.ts +4 -2
  123. package/corpus/templates/content/server/db/schema.ts +30 -0
  124. package/corpus/templates/content/server/lib/comment-notifications.ts +57 -26
  125. package/corpus/templates/content/server/lib/emails.ts +70 -0
  126. package/corpus/templates/content/server/plugins/db.ts +24 -0
  127. package/corpus/templates/content/server/plugins/onboarding.ts +2 -2
  128. package/corpus/templates/content/server/plugins/transactional-emails.ts +5 -0
  129. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +23 -3
  130. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  131. package/corpus/templates/crm/agent-native.json +12 -0
  132. package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +23 -3
  133. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  134. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +23 -2
  135. package/corpus/templates/design/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  136. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +2 -2
  137. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +2 -2
  138. package/corpus/templates/design/actions/apply-design-token-edit.ts +1 -1
  139. package/corpus/templates/design/actions/capture-design-state.ts +1 -1
  140. package/corpus/templates/design/actions/connect-builder-app.ts +2 -2
  141. package/corpus/templates/design/actions/create-design-branch.ts +1 -1
  142. package/corpus/templates/design/actions/create-fusion-app.ts +3 -3
  143. package/corpus/templates/design/actions/deploy-design-preview.ts +1 -1
  144. package/corpus/templates/design/actions/get-component-details.ts +1 -1
  145. package/corpus/templates/design/actions/get-design-branch-diff.ts +1 -1
  146. package/corpus/templates/design/actions/index-components.ts +3 -3
  147. package/corpus/templates/design/actions/index-design-system-with-builder.ts +1 -1
  148. package/corpus/templates/design/actions/migrate-inline-design-to-app.ts +3 -3
  149. package/corpus/templates/design/actions/open-component-source.ts +1 -1
  150. package/corpus/templates/design/actions/update-design.ts +61 -0
  151. package/corpus/templates/design/agent-native.json +12 -0
  152. package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +1 -1
  153. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +1 -1
  154. package/corpus/templates/design/scripts/qa-figma-stress-import.ts +1 -1
  155. package/corpus/templates/design/server/lib/figma-node-import.ts +1 -1
  156. package/corpus/templates/design/shared/design-source-capabilities.ts +25 -9
  157. package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +23 -3
  158. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  159. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +23 -2
  160. package/corpus/templates/dispatch/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  161. package/corpus/templates/dispatch/agent-native.json +12 -0
  162. package/corpus/templates/dispatch/app/routes/transactional-email.$appId.$id.tsx +4 -0
  163. package/corpus/templates/dispatch/app/routes/transactional-email.tsx +4 -0
  164. package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +23 -3
  165. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  166. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +23 -2
  167. package/corpus/templates/factory/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  168. package/corpus/templates/factory/agent-native.json +12 -0
  169. package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +23 -3
  170. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  171. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +23 -2
  172. package/corpus/templates/forms/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  173. package/corpus/templates/forms/actions/export-responses.ts +1 -1
  174. package/corpus/templates/forms/agent-native.json +12 -0
  175. package/corpus/templates/forms/server/lib/emails.ts +52 -0
  176. package/corpus/templates/forms/server/lib/response-email.ts +2 -0
  177. package/corpus/templates/forms/server/plugins/transactional-emails.ts +5 -0
  178. package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +23 -3
  179. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  180. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +23 -2
  181. package/corpus/templates/macros/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  182. package/corpus/templates/macros/agent-native.json +12 -0
  183. package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +23 -3
  184. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  185. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +23 -2
  186. package/corpus/templates/mail/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  187. package/corpus/templates/mail/agent-native.json +12 -0
  188. package/corpus/templates/mail/app/i18n/en-US.ts +1 -1
  189. package/corpus/templates/mail/server/lib/media-upload.ts +1 -1
  190. package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +23 -3
  191. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  192. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +23 -2
  193. package/corpus/templates/plan/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  194. package/corpus/templates/plan/actions/request-plan-access.ts +33 -12
  195. package/corpus/templates/plan/agent-native.json +12 -0
  196. package/corpus/templates/plan/server/lib/comment-notifications.ts +53 -27
  197. package/corpus/templates/plan/server/lib/emails.ts +67 -0
  198. package/corpus/templates/plan/server/lib/plan-assets.ts +1 -1
  199. package/corpus/templates/plan/server/plugins/transactional-emails.ts +5 -0
  200. package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +23 -3
  201. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  202. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +23 -2
  203. package/corpus/templates/slides/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  204. package/corpus/templates/slides/actions/generate-image-api.ts +1 -1
  205. package/corpus/templates/slides/actions/generate-slides-ai.ts +1 -1
  206. package/corpus/templates/slides/actions/import-file.ts +2 -2
  207. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +1 -1
  208. package/corpus/templates/slides/agent-native.json +12 -0
  209. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +1 -1
  210. package/corpus/templates/slides/app/i18n/en-US.ts +2 -2
  211. package/corpus/templates/slides/app/lib/deck-sorting.ts +19 -0
  212. package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +1 -1
  213. package/corpus/templates/slides/app/pages/Index.tsx +7 -2
  214. package/corpus/templates/slides/changelog/2026-08-05-decks-are-now-sorted-by-most-recently-updated.md +6 -0
  215. package/corpus/templates/slides/server/handlers/assets.ts +1 -1
  216. package/corpus/templates/slides/server/handlers/uploads.ts +1 -1
  217. package/corpus/templates/slides/server/lib/comment-notifications.ts +44 -21
  218. package/corpus/templates/slides/server/lib/emails.ts +40 -0
  219. package/corpus/templates/slides/server/plugins/transactional-emails.ts +5 -0
  220. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +23 -3
  221. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  222. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +23 -2
  223. package/corpus/templates/tasks/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  224. package/corpus/templates/tasks/agent-native.json +12 -0
  225. package/dist/action.d.ts +6 -0
  226. package/dist/agent/engine/builder-engine.js +2 -2
  227. package/dist/agent/engine/credential-errors.d.ts +1 -1
  228. package/dist/agent/engine/credential-errors.js +2 -2
  229. package/dist/agent/production-agent.js +3 -2
  230. package/dist/brand-kit/fig/index.js +1 -1
  231. package/dist/cli/agent.js +45 -3
  232. package/dist/cli/code-agent-executor.js +2 -1
  233. package/dist/cli/create.d.ts +9 -1
  234. package/dist/cli/create.js +94 -1
  235. package/dist/cli/doctor.d.ts +8 -11
  236. package/dist/cli/doctor.js +92 -24
  237. package/dist/cli/index.js +6 -5
  238. package/dist/client/AgentAskPopover.d.ts +3 -1
  239. package/dist/client/AgentAskPopover.js +2 -2
  240. package/dist/client/AgentPanel.js +9 -3
  241. package/dist/client/AssistantChat.js +54 -33
  242. package/dist/client/MultiTabAssistantChat.js +1 -1
  243. package/dist/client/RouteTransitionIndicator.d.ts +7 -0
  244. package/dist/client/RouteTransitionIndicator.js +31 -0
  245. package/dist/client/agent-engine-key.js +1 -1
  246. package/dist/client/app-providers.js +11 -2
  247. package/dist/client/chat/message-components.js +1 -1
  248. package/dist/client/chat/run-recovery.js +1 -1
  249. package/dist/client/chat/tool-call-display.d.ts +3 -1
  250. package/dist/client/chat/tool-call-display.js +4 -3
  251. package/dist/client/chat-model-groups.d.ts +6 -0
  252. package/dist/client/chat-model-groups.js +11 -0
  253. package/dist/client/error-format.js +1 -1
  254. package/dist/client/i18n.js +1 -1
  255. package/dist/client/onboarding/FirstRunOnboarding.d.ts +5 -1
  256. package/dist/client/onboarding/FirstRunOnboarding.js +29 -13
  257. package/dist/client/onboarding/first-run-enabled.d.ts +6 -1
  258. package/dist/client/onboarding/first-run-enabled.js +33 -3
  259. package/dist/client/onboarding/use-onboarding.js +16 -11
  260. package/dist/client/resources/mcp-integration-catalog.js +26 -0
  261. package/dist/client/resources/mcp-integration-logos.js +4 -0
  262. package/dist/client/route-warmup.js +56 -10
  263. package/dist/client/settings/AccountSettingsCard.js +78 -3
  264. package/dist/client/settings/SettingsPanel.js +1 -1
  265. package/dist/client/settings/VoiceTranscriptionSection.js +2 -2
  266. package/dist/client/settings/useBuilderStatus.js +1 -1
  267. package/dist/client/setup-connections/useBuilderConnectCardController.js +1 -1
  268. package/dist/client/ui/index.d.ts +1 -0
  269. package/dist/client/ui/index.js +1 -0
  270. package/dist/client/uploads/upload-editor-image.js +1 -1
  271. package/dist/client/use-chat-threads.js +3 -0
  272. package/dist/collab/routes.d.ts +1 -1
  273. package/dist/config.d.ts +48 -0
  274. package/dist/config.js +111 -0
  275. package/dist/db/migrations.js +5 -0
  276. package/dist/eject/provider-api-definitions.d.ts +1 -1
  277. package/dist/eject/provider-api-definitions.js +1 -0
  278. package/dist/eject/remote-mcp-presets.js +1 -0
  279. package/dist/email-catalog/actions/list-email-activity.d.ts +6 -0
  280. package/dist/email-catalog/actions/list-email-activity.js +15 -0
  281. package/dist/email-catalog/actions/list-email-engagement.d.ts +6 -0
  282. package/dist/email-catalog/actions/list-email-engagement.js +15 -0
  283. package/dist/email-catalog/actions/list-email-log.d.ts +8 -0
  284. package/dist/email-catalog/actions/list-email-log.js +22 -0
  285. package/dist/email-catalog/actions/list-transactional-emails.d.ts +23 -0
  286. package/dist/email-catalog/actions/list-transactional-emails.js +61 -0
  287. package/dist/email-catalog/actions/render-transactional-email-preview.d.ts +10 -0
  288. package/dist/email-catalog/actions/render-transactional-email-preview.js +24 -0
  289. package/dist/email-catalog/authorize.d.ts +2 -0
  290. package/dist/email-catalog/authorize.js +10 -0
  291. package/dist/email-catalog/log.d.ts +57 -0
  292. package/dist/email-catalog/log.js +117 -0
  293. package/dist/email-catalog/provider-metrics.d.ts +34 -0
  294. package/dist/email-catalog/provider-metrics.js +165 -0
  295. package/dist/email-catalog/registry.d.ts +79 -0
  296. package/dist/email-catalog/registry.js +71 -0
  297. package/dist/email-catalog/schema.d.ts +212 -0
  298. package/dist/email-catalog/schema.js +49 -0
  299. package/dist/email-catalog/system-emails.d.ts +14 -0
  300. package/dist/email-catalog/system-emails.js +68 -0
  301. package/dist/extensions/web-search-tool.js +2 -2
  302. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  303. package/dist/file-upload/actions/upload-image.js +1 -1
  304. package/dist/file-upload/registry.js +1 -1
  305. package/dist/guards/index.d.ts +3 -0
  306. package/dist/guards/index.js +2 -0
  307. package/dist/guards/no-empty-migrations.d.ts +14 -0
  308. package/dist/guards/no-empty-migrations.js +126 -0
  309. package/dist/index.browser.d.ts +1 -0
  310. package/dist/index.browser.js +3 -0
  311. package/dist/index.d.ts +1 -0
  312. package/dist/index.js +1 -0
  313. package/dist/localization/default-messages.d.ts +69 -0
  314. package/dist/localization/default-messages.js +71 -2
  315. package/dist/notifications/routes.d.ts +2 -2
  316. package/dist/onboarding/app-profile.js +1 -1
  317. package/dist/onboarding/plugin.d.ts +2 -0
  318. package/dist/onboarding/plugin.js +29 -2
  319. package/dist/org/handlers.js +8 -1
  320. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  321. package/dist/provider-api/actions/provider-api.d.ts +13 -13
  322. package/dist/provider-api/index.d.ts +4 -4
  323. package/dist/provider-api/index.js +35 -0
  324. package/dist/resources/handlers.d.ts +1 -1
  325. package/dist/resources/handlers.js +1 -1
  326. package/dist/scripts/docs/framework-search.d.ts +9 -0
  327. package/dist/scripts/docs/framework-search.js +239 -0
  328. package/dist/scripts/docs/index.js +1 -0
  329. package/dist/scripts/docs/search.d.ts +10 -0
  330. package/dist/scripts/docs/search.js +1 -1
  331. package/dist/scripts/docs/source-search.d.ts +10 -2
  332. package/dist/scripts/docs/source-search.js +108 -41
  333. package/dist/search-utils/index.d.ts +11 -0
  334. package/dist/search-utils/index.js +72 -0
  335. package/dist/server/action-change.d.ts +6 -0
  336. package/dist/server/action-change.js +28 -14
  337. package/dist/server/action-discovery.js +31 -0
  338. package/dist/server/action-routes.js +1 -0
  339. package/dist/server/agent-chat/browser-team-tools.js +1 -1
  340. package/dist/server/agent-chat/script-entries.js +43 -2
  341. package/dist/server/auth-login-mode.d.ts +8 -0
  342. package/dist/server/auth-login-mode.js +17 -0
  343. package/dist/server/auth.js +100 -15
  344. package/dist/server/better-auth-instance.d.ts +36 -0
  345. package/dist/server/better-auth-instance.js +42 -5
  346. package/dist/server/builder-design-systems.js +1 -1
  347. package/dist/server/core-routes-plugin.js +17 -14
  348. package/dist/server/credential-provider.js +3 -3
  349. package/dist/server/email-templates.d.ts +7 -0
  350. package/dist/server/email-templates.js +24 -0
  351. package/dist/server/email.d.ts +26 -0
  352. package/dist/server/email.js +66 -4
  353. package/dist/server/framework-request-handler.js +6 -0
  354. package/dist/server/index.d.ts +1 -0
  355. package/dist/server/index.js +1 -0
  356. package/dist/server/onboarding-html.d.ts +2 -0
  357. package/dist/server/onboarding-html.js +169 -8
  358. package/dist/server/realtime-token.d.ts +1 -1
  359. package/dist/server/realtime-voice.js +1 -1
  360. package/dist/server/sentry.d.ts +1 -1
  361. package/dist/server/transcribe-voice.js +3 -3
  362. package/dist/shared/first-run-onboarding.d.ts +1 -0
  363. package/dist/shared/first-run-onboarding.js +1 -0
  364. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  365. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  366. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  367. package/dist/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  368. package/dist/templates/chat/AGENTS.md +3 -0
  369. package/dist/templates/chat/DESIGN.md +28 -0
  370. package/dist/templates/chat/agent-native.json +12 -0
  371. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +23 -3
  372. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  373. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +23 -2
  374. package/dist/templates/default/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  375. package/dist/templates/default/AGENTS.md +4 -0
  376. package/dist/templates/default/DESIGN.md +30 -0
  377. package/dist/templates/default/agent-native.json +9 -0
  378. package/dist/templates/default/app/i18n/ar-SA.ts +2 -2
  379. package/dist/templates/default/app/i18n/de-DE.ts +2 -2
  380. package/dist/templates/default/app/i18n/en-US.ts +2 -2
  381. package/dist/templates/default/app/i18n/es-ES.ts +2 -2
  382. package/dist/templates/default/app/i18n/fr-FR.ts +2 -2
  383. package/dist/templates/default/app/i18n/hi-IN.ts +2 -2
  384. package/dist/templates/default/app/i18n/ja-JP.ts +2 -2
  385. package/dist/templates/default/app/i18n/ko-KR.ts +2 -2
  386. package/dist/templates/default/app/i18n/pt-BR.ts +2 -2
  387. package/dist/templates/default/app/i18n/zh-CN.ts +2 -2
  388. package/dist/templates/default/app/i18n/zh-TW.ts +1 -1
  389. package/dist/templates/default/package.json +1 -0
  390. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +23 -3
  391. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  392. package/dist/templates/headless/agent-native.json +9 -0
  393. package/dist/templates/headless/package.json +2 -0
  394. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +23 -3
  395. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  396. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +23 -2
  397. package/dist/templates/workspace-core/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  398. package/dist/templates/workspace-core/AGENTS.md +3 -0
  399. package/dist/templates/workspace-core/DESIGN.md +35 -0
  400. package/dist/templates/workspace-root/AGENTS.md +3 -0
  401. package/dist/templates/workspace-root/DESIGN.md +35 -0
  402. package/dist/templates/workspace-root/agent-native.json +9 -0
  403. package/dist/templates/workspace-root/package.json +3 -0
  404. package/dist/transcription/builder-transcription.js +1 -1
  405. package/dist/user-profile/actions/change-password.d.ts +8 -0
  406. package/dist/user-profile/actions/change-password.js +24 -0
  407. package/dist/user-profile/actions/get-auth-methods.d.ts +6 -0
  408. package/dist/user-profile/actions/get-auth-methods.js +23 -0
  409. package/dist/user-profile/actions/set-password.d.ts +7 -0
  410. package/dist/user-profile/actions/set-password.js +23 -0
  411. package/dist/vite/client.d.ts +8 -1
  412. package/dist/vite/client.js +63 -12
  413. package/dist/vite/index.d.ts +1 -0
  414. package/dist/vite/index.js +1 -0
  415. package/docs/AGENTS.md +7 -2
  416. package/docs/SKILL.md +7 -5
  417. package/docs/content/agent-native-config.mdx +165 -0
  418. package/docs/content/agent-native-toolkit.mdx +1 -1
  419. package/docs/content/deployment.mdx +7 -2
  420. package/docs/content/doctor.mdx +21 -13
  421. package/docs/content/environment-variables.mdx +158 -0
  422. package/docs/content/file-uploads.mdx +1 -1
  423. package/docs/content/getting-started.mdx +1 -1
  424. package/docs/content/key-concepts.mdx +1 -1
  425. package/docs/content/multi-app-workspace.mdx +1 -1
  426. package/docs/content/template-clips-ai-and-editing.mdx +6 -6
  427. package/docs/content/template-clips-developers.mdx +3 -3
  428. package/docs/content/toolkit-settings.mdx +1 -1
  429. package/docs/content/voice-input.mdx +4 -4
  430. package/package.json +7 -2
  431. package/src/eject/provider-api-definitions.ts +1 -0
  432. package/src/eject/remote-mcp-presets.ts +1 -0
  433. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +23 -3
  434. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  435. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +23 -2
  436. package/src/templates/chat/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  437. package/src/templates/chat/AGENTS.md +3 -0
  438. package/src/templates/chat/DESIGN.md +28 -0
  439. package/src/templates/chat/agent-native.json +12 -0
  440. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +23 -3
  441. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  442. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +23 -2
  443. package/src/templates/default/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  444. package/src/templates/default/AGENTS.md +4 -0
  445. package/src/templates/default/DESIGN.md +30 -0
  446. package/src/templates/default/agent-native.json +9 -0
  447. package/src/templates/default/app/i18n/ar-SA.ts +2 -2
  448. package/src/templates/default/app/i18n/de-DE.ts +2 -2
  449. package/src/templates/default/app/i18n/en-US.ts +2 -2
  450. package/src/templates/default/app/i18n/es-ES.ts +2 -2
  451. package/src/templates/default/app/i18n/fr-FR.ts +2 -2
  452. package/src/templates/default/app/i18n/hi-IN.ts +2 -2
  453. package/src/templates/default/app/i18n/ja-JP.ts +2 -2
  454. package/src/templates/default/app/i18n/ko-KR.ts +2 -2
  455. package/src/templates/default/app/i18n/pt-BR.ts +2 -2
  456. package/src/templates/default/app/i18n/zh-CN.ts +2 -2
  457. package/src/templates/default/app/i18n/zh-TW.ts +1 -1
  458. package/src/templates/default/package.json +1 -0
  459. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +23 -3
  460. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  461. package/src/templates/headless/agent-native.json +9 -0
  462. package/src/templates/headless/package.json +2 -0
  463. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +23 -3
  464. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +16 -0
  465. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +23 -2
  466. package/src/templates/workspace-core/.agents/skills/frontend-design/references/visual-direction.md +99 -0
  467. package/src/templates/workspace-core/AGENTS.md +3 -0
  468. package/src/templates/workspace-core/DESIGN.md +35 -0
  469. package/src/templates/workspace-root/AGENTS.md +3 -0
  470. package/src/templates/workspace-root/DESIGN.md +35 -0
  471. package/src/templates/workspace-root/agent-native.json +9 -0
  472. package/src/templates/workspace-root/package.json +3 -0
@@ -240,6 +240,11 @@ export function runMigrations(migrations, options) {
240
240
  seenNames.add(m.name);
241
241
  }
242
242
  }
243
+ // A plugin with no migrations is intentionally a no-op. Creating or reading
244
+ // a bookkeeping table here turns an empty app plugin into a database cold
245
+ // start on every serverless boot.
246
+ if (migrations.length === 0)
247
+ return async () => { };
243
248
  const namedTable = `${table}_named`;
244
249
  return async () => {
245
250
  try {
@@ -6,7 +6,7 @@ export declare function mergeProviderApiConfigs(overrides?: readonly ProviderApi
6
6
  export declare function getProviderApiConfig(providerId: ProviderApiId | string, overrides?: readonly ProviderApiConfig[]): ProviderApiConfig;
7
7
  export declare function listProviderApiIdsForTemplateUse(templateUse: WorkspaceConnectionTemplateUse, overrides?: readonly ProviderApiConfig[]): ProviderApiId[];
8
8
  export declare function listProviderApiCatalog(providerId?: ProviderApiId | string, options?: Parameters<typeof listRuntimeProviderApiCatalog>[1]): {
9
- id: "amplitude" | "apollo" | "bigquery" | "clay" | "commonroom" | "dataforseo" | "figma" | "ga4" | "gcloud" | "github" | "gmail" | "gong" | "google_calendar" | "google_drive" | "google_slides" | "grafana" | "granola" | "hubspot" | "jira" | "mixpanel" | "notion" | "posthog" | "prometheus" | "pylon" | "salesforce" | "sentry" | "slack" | "stripe" | "twitter";
9
+ id: "amplitude" | "apollo" | "bigquery" | "clay" | "commonroom" | "dataforseo" | "figma" | "fullstory" | "ga4" | "gcloud" | "github" | "gmail" | "gong" | "google_calendar" | "google_drive" | "google_slides" | "grafana" | "granola" | "hubspot" | "jira" | "mixpanel" | "notion" | "posthog" | "prometheus" | "pylon" | "salesforce" | "sentry" | "slack" | "stripe" | "twitter";
10
10
  label: string;
11
11
  defaultBaseUrl: string;
12
12
  requiresConnectionId: boolean;
@@ -14,6 +14,7 @@ export const providerApiOverrides = [
14
14
  provider("gcloud"),
15
15
  provider("github"),
16
16
  provider("figma"),
17
+ provider("fullstory"),
17
18
  provider("gmail"),
18
19
  provider("gong"),
19
20
  provider("google_calendar"),
@@ -38,6 +38,7 @@ function preset(id) {
38
38
  export const DEFAULT_MCP_INTEGRATIONS = [
39
39
  preset("context7"),
40
40
  preset("sentry"),
41
+ preset("fullstory"),
41
42
  preset("notion"),
42
43
  preset("granola"),
43
44
  preset("semgrep"),
@@ -0,0 +1,6 @@
1
+ declare const _default: import("../../action.js").ActionDefinition<{
2
+ templateId: string;
3
+ limit?: unknown;
4
+ }, import("../provider-metrics.js").ProviderMetricsResult<import("../provider-metrics.js").EmailActivityEntry[]>>;
5
+ export default _default;
6
+ //# sourceMappingURL=list-email-activity.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ import { defineAction } from "../../action.js";
3
+ import { authorizeTransactionalEmailRead } from "../authorize.js";
4
+ import { fetchEmailActivity } from "../provider-metrics.js";
5
+ export default defineAction({
6
+ description: "List recent provider activity for one registered transactional email in this app. Organization admin only.",
7
+ schema: z.object({
8
+ templateId: z.string().min(1),
9
+ limit: z.coerce.number().int().min(1).max(1000).default(50),
10
+ }),
11
+ http: { method: "GET" },
12
+ authorize: ({ templateId }) => authorizeTransactionalEmailRead([templateId]),
13
+ run: async ({ templateId, limit }) => fetchEmailActivity({ templateId, limit }),
14
+ });
15
+ //# sourceMappingURL=list-email-activity.js.map
@@ -0,0 +1,6 @@
1
+ declare const _default: import("../../action.js").ActionDefinition<{
2
+ templateIds: string[];
3
+ windowDays?: unknown;
4
+ }, import("../provider-metrics.js").ProviderMetricsResult<import("../provider-metrics.js").EmailEngagement[]>>;
5
+ export default _default;
6
+ //# sourceMappingURL=list-email-engagement.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ import { defineAction } from "../../action.js";
3
+ import { authorizeTransactionalEmailRead } from "../authorize.js";
4
+ import { fetchEmailEngagement } from "../provider-metrics.js";
5
+ export default defineAction({
6
+ description: "Read provider engagement metrics for registered transactional emails in this app. Organization admin only.",
7
+ schema: z.object({
8
+ templateIds: z.array(z.string().min(1)).max(100),
9
+ windowDays: z.coerce.number().int().min(1).max(365).default(30),
10
+ }),
11
+ http: { method: "POST" },
12
+ authorize: ({ templateIds }) => authorizeTransactionalEmailRead(templateIds),
13
+ run: async ({ templateIds, windowDays }) => fetchEmailEngagement(templateIds, windowDays),
14
+ });
15
+ //# sourceMappingURL=list-email-engagement.js.map
@@ -0,0 +1,8 @@
1
+ declare const _default: import("../../action.js").ActionDefinition<{
2
+ templateId?: string;
3
+ limit?: unknown;
4
+ }, {
5
+ entries: import("../log.js").EmailLogEntry[];
6
+ }>;
7
+ export default _default;
8
+ //# sourceMappingURL=list-email-log.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { z } from "zod";
2
+ import { defineAction } from "../../action.js";
3
+ import { getAppSlug } from "../../server/app-name.js";
4
+ import { authorizeTransactionalEmailRead } from "../authorize.js";
5
+ import { listEmailLog } from "../log.js";
6
+ export default defineAction({
7
+ description: "List recent transactional email sends from this app, newest first, optionally filtered to one registered email id.",
8
+ schema: z.object({
9
+ templateId: z.string().optional(),
10
+ limit: z.coerce.number().int().min(1).max(500).default(100),
11
+ }),
12
+ http: { method: "GET" },
13
+ authorize: ({ templateId }) => authorizeTransactionalEmailRead(templateId ? [templateId] : []),
14
+ run: async ({ templateId, limit }) => ({
15
+ entries: await listEmailLog({
16
+ app: getAppSlug() ?? "unknown",
17
+ templateId,
18
+ limit,
19
+ }),
20
+ }),
21
+ });
22
+ //# sourceMappingURL=list-email-log.js.map
@@ -0,0 +1,23 @@
1
+ declare const _default: import("../../action.js").ActionDefinition<{
2
+ windowDays?: unknown;
3
+ }, {
4
+ app: string;
5
+ windowDays: number;
6
+ statsAvailable: boolean;
7
+ statsError: string;
8
+ emails: {
9
+ id: string;
10
+ app: string;
11
+ name: string;
12
+ trigger: string;
13
+ recipient: string;
14
+ recipientLabel: string;
15
+ sender: string;
16
+ senderLabel: string;
17
+ sent: number;
18
+ failed: number;
19
+ lastSentAt: number;
20
+ }[];
21
+ }>;
22
+ export default _default;
23
+ //# sourceMappingURL=list-transactional-emails.d.ts.map
@@ -0,0 +1,61 @@
1
+ import { z } from "zod";
2
+ import { defineAction } from "../../action.js";
3
+ import { getAppSlug } from "../../server/app-name.js";
4
+ import { getEmailSendStats } from "../log.js";
5
+ import { listTransactionalEmails } from "../registry.js";
6
+ import { registerCoreSystemEmails } from "../system-emails.js";
7
+ const DEFAULT_WINDOW_DAYS = 30;
8
+ export default defineAction({
9
+ description: "List the transactional emails this app can send, with the trigger, recipient and sender logic for each, plus local send counts and last-sent. Engagement metrics such as open rate are not included here — they live at the email provider.",
10
+ schema: z.object({
11
+ windowDays: z.coerce
12
+ .number()
13
+ .int()
14
+ .min(1)
15
+ .max(365)
16
+ .default(DEFAULT_WINDOW_DAYS)
17
+ .describe("How many days of send history to summarize."),
18
+ }),
19
+ http: { method: "GET" },
20
+ run: async ({ windowDays }) => {
21
+ registerCoreSystemEmails();
22
+ const since = Date.now() - windowDays * 24 * 60 * 60 * 1000;
23
+ const app = getAppSlug() ?? "unknown";
24
+ const definitions = listTransactionalEmails();
25
+ // A failed stats read must not masquerade as "no email ever sent" — the
26
+ // catalog is still worth returning, but the caller has to be able to tell
27
+ // that the numbers are missing rather than zero.
28
+ let statsById = null;
29
+ let statsError = null;
30
+ try {
31
+ const stats = await getEmailSendStats(since, app);
32
+ statsById = new Map(stats.map((row) => [row.templateId, row]));
33
+ }
34
+ catch (error) {
35
+ statsError = error instanceof Error ? error.message : String(error);
36
+ }
37
+ return {
38
+ app,
39
+ windowDays,
40
+ statsAvailable: statsError === null,
41
+ statsError,
42
+ emails: definitions.map((definition) => {
43
+ const stats = statsById?.get(definition.id);
44
+ return {
45
+ id: definition.id,
46
+ app: definition.app,
47
+ name: definition.name,
48
+ trigger: definition.trigger,
49
+ recipient: definition.recipient,
50
+ recipientLabel: definition.recipientLabel,
51
+ sender: definition.sender,
52
+ senderLabel: definition.senderLabel,
53
+ sent: stats?.sent ?? (statsById ? 0 : null),
54
+ failed: stats?.failed ?? (statsById ? 0 : null),
55
+ lastSentAt: stats?.lastSentAt ?? null,
56
+ };
57
+ }),
58
+ };
59
+ },
60
+ });
61
+ //# sourceMappingURL=list-transactional-emails.js.map
@@ -0,0 +1,10 @@
1
+ declare const _default: import("../../action.js").ActionDefinition<{
2
+ id: string;
3
+ }, {
4
+ id: string;
5
+ subject: string;
6
+ html: string;
7
+ text: string;
8
+ }>;
9
+ export default _default;
10
+ //# sourceMappingURL=render-transactional-email-preview.d.ts.map
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ import { defineAction } from "../../action.js";
3
+ import { renderTransactionalEmailPreview } from "../registry.js";
4
+ import { registerCoreSystemEmails } from "../system-emails.js";
5
+ export default defineAction({
6
+ description: "Render one of this app's transactional emails with representative dummy data, returning the subject, HTML and plain-text bodies for preview.",
7
+ schema: z.object({
8
+ id: z
9
+ .string()
10
+ .describe("Registered email id, e.g. calendar.booking-confirmed."),
11
+ }),
12
+ http: { method: "GET" },
13
+ run: async ({ id }) => {
14
+ registerCoreSystemEmails();
15
+ const rendered = renderTransactionalEmailPreview(id);
16
+ return {
17
+ id,
18
+ subject: rendered.subject,
19
+ html: rendered.html,
20
+ text: rendered.text,
21
+ };
22
+ },
23
+ });
24
+ //# sourceMappingURL=render-transactional-email-preview.js.map
@@ -0,0 +1,2 @@
1
+ export declare function authorizeTransactionalEmailRead(templateIds?: string[]): Promise<boolean>;
2
+ //# sourceMappingURL=authorize.d.ts.map
@@ -0,0 +1,10 @@
1
+ import { currentRequestUserIsOrgAdmin } from "../server/org-admin.js";
2
+ import { getTransactionalEmail } from "./registry.js";
3
+ import { registerCoreSystemEmails } from "./system-emails.js";
4
+ export async function authorizeTransactionalEmailRead(templateIds = []) {
5
+ if (!(await currentRequestUserIsOrgAdmin()))
6
+ return false;
7
+ registerCoreSystemEmails();
8
+ return templateIds.every((id) => Boolean(getTransactionalEmail(id)));
9
+ }
10
+ //# sourceMappingURL=authorize.js.map
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Durable send log for transactional emails.
3
+ *
4
+ * Written by `sendEmail` on every attempt, successful or not. Read by Dispatch
5
+ * to report per-email send counts and last-sent without depending on the
6
+ * provider's activity retention window.
7
+ */
8
+ export interface RecordEmailSendArgs {
9
+ templateId?: string;
10
+ app?: string;
11
+ recipient: string;
12
+ sender: string;
13
+ subject: string;
14
+ status: "sent" | "failed";
15
+ error?: string;
16
+ provider: string;
17
+ }
18
+ /**
19
+ * Append one send record.
20
+ *
21
+ * Callers treat logging as best-effort: a logging failure must not turn a
22
+ * delivered email into a thrown send. The failure is surfaced on the console
23
+ * rather than swallowed, so a persistently broken log is visible instead of
24
+ * quietly producing an empty activity view.
25
+ */
26
+ export declare function recordEmailSend(args: RecordEmailSendArgs): Promise<void>;
27
+ export interface EmailSendStats {
28
+ templateId: string;
29
+ sent: number;
30
+ failed: number;
31
+ lastSentAt: number | null;
32
+ }
33
+ /**
34
+ * Per-template send counts and last-sent, for sends at or after `since`.
35
+ * Templates with no rows are absent from the result — callers distinguish
36
+ * "never sent" from "sent zero times in window" by that absence.
37
+ */
38
+ export declare function getEmailSendStats(since: number, app: string): Promise<EmailSendStats[]>;
39
+ export interface EmailLogEntry {
40
+ id: string;
41
+ templateId: string | null;
42
+ app: string | null;
43
+ recipient: string;
44
+ sender: string;
45
+ subject: string;
46
+ status: string;
47
+ error: string | null;
48
+ provider: string;
49
+ createdAt: number;
50
+ }
51
+ /** Most recent sends for one app, newest first, optionally filtered to one template. */
52
+ export declare function listEmailLog(options: {
53
+ app: string;
54
+ templateId?: string;
55
+ limit?: number;
56
+ }): Promise<EmailLogEntry[]>;
57
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Durable send log for transactional emails.
3
+ *
4
+ * Written by `sendEmail` on every attempt, successful or not. Read by Dispatch
5
+ * to report per-email send counts and last-sent without depending on the
6
+ * provider's activity retention window.
7
+ */
8
+ import { randomUUID } from "node:crypto";
9
+ import { getDbExec, isPostgres } from "../db/client.js";
10
+ import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
11
+ let _initPromise;
12
+ async function ensureTable() {
13
+ if (!_initPromise) {
14
+ _initPromise = (async () => {
15
+ const { EMAIL_LOG_CREATE_SQL, EMAIL_LOG_TEMPLATE_INDEX_SQL } = await import("./schema.js");
16
+ // Generic INTEGER maps to BIGINT on Postgres, which millisecond
17
+ // timestamps need.
18
+ const createSql = isPostgres()
19
+ ? EMAIL_LOG_CREATE_SQL.replace(/\bINTEGER\b/g, "BIGINT")
20
+ : EMAIL_LOG_CREATE_SQL;
21
+ await ensureTableExists("email_log", createSql);
22
+ await ensureIndexExists("email_log_template_created_idx", EMAIL_LOG_TEMPLATE_INDEX_SQL);
23
+ })().catch((error) => {
24
+ // Don't memoize a failed bootstrap — the next send should retry rather
25
+ // than log nothing forever.
26
+ _initPromise = undefined;
27
+ throw error;
28
+ });
29
+ }
30
+ return _initPromise;
31
+ }
32
+ /**
33
+ * Append one send record.
34
+ *
35
+ * Callers treat logging as best-effort: a logging failure must not turn a
36
+ * delivered email into a thrown send. The failure is surfaced on the console
37
+ * rather than swallowed, so a persistently broken log is visible instead of
38
+ * quietly producing an empty activity view.
39
+ */
40
+ export async function recordEmailSend(args) {
41
+ try {
42
+ await ensureTable();
43
+ await getDbExec().execute({
44
+ sql: `INSERT INTO email_log
45
+ (id, template_id, app, recipient, sender, subject, status, error, provider, created_at)
46
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
47
+ args: [
48
+ randomUUID(),
49
+ args.templateId ?? null,
50
+ args.app ?? null,
51
+ args.recipient,
52
+ args.sender,
53
+ args.subject,
54
+ args.status,
55
+ args.error ?? null,
56
+ args.provider,
57
+ Date.now(),
58
+ ],
59
+ });
60
+ }
61
+ catch (error) {
62
+ console.error("[agent-native:email] failed to record send", error);
63
+ }
64
+ }
65
+ /**
66
+ * Per-template send counts and last-sent, for sends at or after `since`.
67
+ * Templates with no rows are absent from the result — callers distinguish
68
+ * "never sent" from "sent zero times in window" by that absence.
69
+ */
70
+ export async function getEmailSendStats(since, app) {
71
+ await ensureTable();
72
+ const { rows } = await getDbExec().execute({
73
+ sql: `SELECT template_id,
74
+ SUM(CASE WHEN status = 'sent' THEN 1 ELSE 0 END) AS sent,
75
+ SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) AS failed,
76
+ MAX(CASE WHEN status = 'sent' THEN created_at END) AS last_sent_at
77
+ FROM email_log
78
+ WHERE app = ? AND template_id IS NOT NULL AND created_at >= ?
79
+ GROUP BY template_id`,
80
+ args: [app, since],
81
+ });
82
+ return rows.map((row) => ({
83
+ templateId: String(row.template_id),
84
+ sent: Number(row.sent ?? 0),
85
+ failed: Number(row.failed ?? 0),
86
+ lastSentAt: row.last_sent_at == null ? null : Number(row.last_sent_at),
87
+ }));
88
+ }
89
+ /** Most recent sends for one app, newest first, optionally filtered to one template. */
90
+ export async function listEmailLog(options) {
91
+ await ensureTable();
92
+ const limit = Math.min(Math.max(options.limit ?? 100, 1), 500);
93
+ const where = options.templateId
94
+ ? `WHERE app = ? AND template_id = ?`
95
+ : `WHERE app = ?`;
96
+ const args = options.templateId
97
+ ? [options.app, options.templateId, limit]
98
+ : [options.app, limit];
99
+ const { rows } = await getDbExec().execute({
100
+ sql: `SELECT id, template_id, app, recipient, sender, subject, status, error, provider, created_at
101
+ FROM email_log ${where} ORDER BY created_at DESC LIMIT ?`,
102
+ args,
103
+ });
104
+ return rows.map((row) => ({
105
+ id: String(row.id),
106
+ templateId: row.template_id == null ? null : String(row.template_id),
107
+ app: row.app == null ? null : String(row.app),
108
+ recipient: String(row.recipient),
109
+ sender: String(row.sender),
110
+ subject: String(row.subject),
111
+ status: String(row.status),
112
+ error: row.error == null ? null : String(row.error),
113
+ provider: String(row.provider),
114
+ createdAt: Number(row.created_at),
115
+ }));
116
+ }
117
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Engagement metrics and activity for registered transactional emails, read
3
+ * from the active provider in the current app's request context.
4
+ */
5
+ export type ProviderMetricsResult<T> = {
6
+ available: true;
7
+ data: T;
8
+ } | {
9
+ available: false;
10
+ reason: string;
11
+ };
12
+ export interface EmailEngagement {
13
+ templateId: string;
14
+ delivered: number;
15
+ uniqueOpens: number;
16
+ uniqueClicks: number;
17
+ openRate: number | null;
18
+ }
19
+ export declare function fetchEmailEngagement(templateIds: string[], windowDays: number): Promise<ProviderMetricsResult<EmailEngagement[]>>;
20
+ export interface EmailActivityEntry {
21
+ msgId: string;
22
+ toEmail: string;
23
+ fromEmail: string;
24
+ subject: string;
25
+ status: string;
26
+ opensCount: number;
27
+ clicksCount: number;
28
+ lastEventTime: string;
29
+ }
30
+ export declare function fetchEmailActivity(options: {
31
+ templateId: string;
32
+ limit?: number;
33
+ }): Promise<ProviderMetricsResult<EmailActivityEntry[]>>;
34
+ //# sourceMappingURL=provider-metrics.d.ts.map
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Engagement metrics and activity for registered transactional emails, read
3
+ * from the active provider in the current app's request context.
4
+ */
5
+ import { z } from "zod";
6
+ import { resolveSecret } from "../server/credential-provider.js";
7
+ import { getEmailProvider } from "../server/email.js";
8
+ const SENDGRID_API = "https://api.sendgrid.com/v3";
9
+ const SENDGRID_PAGE_SIZE = 1000;
10
+ const SENDGRID_MAX_PAGES = 10;
11
+ const categoryMetricsSchema = z
12
+ .object({
13
+ delivered: z.number().default(0),
14
+ unique_opens: z.number().default(0),
15
+ unique_clicks: z.number().default(0),
16
+ })
17
+ .passthrough();
18
+ const categoryStatSchema = z
19
+ .object({
20
+ name: z.string(),
21
+ metrics: categoryMetricsSchema.default(() => ({
22
+ delivered: 0,
23
+ unique_opens: 0,
24
+ unique_clicks: 0,
25
+ })),
26
+ })
27
+ .passthrough();
28
+ const categorySumsSchema = z.object({
29
+ stats: z.array(categoryStatSchema).default([]),
30
+ });
31
+ const activitySchema = z.object({
32
+ messages: z
33
+ .array(z
34
+ .object({
35
+ msg_id: z.string().default(""),
36
+ to_email: z.string().default(""),
37
+ from_email: z.string().default(""),
38
+ subject: z.string().default(""),
39
+ status: z.string().default(""),
40
+ opens_count: z.coerce.number().default(0),
41
+ clicks_count: z.coerce.number().default(0),
42
+ last_event_time: z.string().default(""),
43
+ })
44
+ .passthrough())
45
+ .default([]),
46
+ });
47
+ async function activeSendGrid() {
48
+ const provider = await getEmailProvider();
49
+ if (provider === "resend") {
50
+ return {
51
+ available: false,
52
+ reason: "Email delivery uses Resend, so SendGrid metrics do not describe the active transport.",
53
+ };
54
+ }
55
+ if (provider !== "sendgrid") {
56
+ return {
57
+ available: false,
58
+ reason: "No email provider is configured, so provider metrics cannot be read.",
59
+ };
60
+ }
61
+ const key = await resolveSecret("SENDGRID_API_KEY");
62
+ if (!key) {
63
+ return {
64
+ available: false,
65
+ reason: "SendGrid is the active email transport, but SENDGRID_API_KEY could not be resolved.",
66
+ };
67
+ }
68
+ return { available: true, key };
69
+ }
70
+ function isoDate(ms) {
71
+ return new Date(ms).toISOString().slice(0, 10);
72
+ }
73
+ async function sendgridGet(key, path, params) {
74
+ const url = new URL(`${SENDGRID_API}${path}`);
75
+ for (const [name, value] of params)
76
+ url.searchParams.append(name, value);
77
+ const res = await fetch(url, {
78
+ headers: { Authorization: `Bearer ${key}` },
79
+ });
80
+ if (!res.ok) {
81
+ const body = await res
82
+ .text()
83
+ .catch((cause) => `<error body unreadable: ${cause}>`);
84
+ throw new Error(`SendGrid ${res.status} on ${path}: ${body.slice(0, 300)}`);
85
+ }
86
+ return res.json();
87
+ }
88
+ export async function fetchEmailEngagement(templateIds, windowDays) {
89
+ if (!templateIds.length)
90
+ return { available: true, data: [] };
91
+ const sendgrid = await activeSendGrid();
92
+ if (!sendgrid.available)
93
+ return sendgrid;
94
+ const end = Date.now();
95
+ const start = end - windowDays * 24 * 60 * 60 * 1000;
96
+ const requested = new Set(templateIds);
97
+ const data = [];
98
+ try {
99
+ for (let page = 0; page < SENDGRID_MAX_PAGES; page += 1) {
100
+ const payload = categorySumsSchema.parse(await sendgridGet(sendgrid.key, "/categories/stats/sums", [
101
+ ["start_date", isoDate(start)],
102
+ ["end_date", isoDate(end)],
103
+ ["limit", String(SENDGRID_PAGE_SIZE)],
104
+ ["offset", String(page * SENDGRID_PAGE_SIZE)],
105
+ ]));
106
+ for (const entry of payload.stats) {
107
+ if (!requested.has(entry.name))
108
+ continue;
109
+ requested.delete(entry.name);
110
+ const delivered = entry.metrics.delivered;
111
+ const uniqueOpens = entry.metrics.unique_opens;
112
+ data.push({
113
+ templateId: entry.name,
114
+ delivered,
115
+ uniqueOpens,
116
+ uniqueClicks: entry.metrics.unique_clicks,
117
+ openRate: delivered > 0 ? Math.min(uniqueOpens / delivered, 1) : null,
118
+ });
119
+ }
120
+ if (requested.size === 0 || payload.stats.length < SENDGRID_PAGE_SIZE) {
121
+ break;
122
+ }
123
+ }
124
+ return { available: true, data };
125
+ }
126
+ catch (error) {
127
+ return {
128
+ available: false,
129
+ reason: error instanceof Error ? error.message : String(error),
130
+ };
131
+ }
132
+ }
133
+ export async function fetchEmailActivity(options) {
134
+ const sendgrid = await activeSendGrid();
135
+ if (!sendgrid.available)
136
+ return sendgrid;
137
+ const limit = Math.min(Math.max(options.limit ?? 50, 1), 1000);
138
+ const safe = options.templateId.replace(/["\\]/g, "");
139
+ try {
140
+ const payload = activitySchema.parse(await sendgridGet(sendgrid.key, "/messages", [
141
+ ["limit", String(limit)],
142
+ ["query", `category="${safe}"`],
143
+ ]));
144
+ return {
145
+ available: true,
146
+ data: payload.messages.map((message) => ({
147
+ msgId: message.msg_id,
148
+ toEmail: message.to_email,
149
+ fromEmail: message.from_email,
150
+ subject: message.subject,
151
+ status: message.status,
152
+ opensCount: message.opens_count,
153
+ clicksCount: message.clicks_count,
154
+ lastEventTime: message.last_event_time,
155
+ })),
156
+ };
157
+ }
158
+ catch (error) {
159
+ return {
160
+ available: false,
161
+ reason: error instanceof Error ? error.message : String(error),
162
+ };
163
+ }
164
+ }
165
+ //# sourceMappingURL=provider-metrics.js.map