@agent-native/core 0.134.0 → 0.135.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 (493) hide show
  1. package/corpus/README.md +3 -3
  2. package/corpus/core/CHANGELOG.md +113 -0
  3. package/corpus/core/docs/content/template-content-developers.mdx +1 -1
  4. package/corpus/core/package.json +3 -2
  5. package/corpus/core/src/automations/service.ts +41 -4
  6. package/corpus/core/src/cli/mcp-config-writers.ts +27 -21
  7. package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +187 -85
  8. package/corpus/core/src/client/agent-page/AutomationDetailsDialog.tsx +208 -0
  9. package/corpus/core/src/client/agent-page/AutomationScheduleDialog.tsx +180 -0
  10. package/corpus/core/src/client/agent-page/TimezoneSelect.tsx +241 -0
  11. package/corpus/core/src/client/agent-page/use-jobs.ts +50 -10
  12. package/corpus/core/src/client/org/OrgSwitcher.tsx +26 -0
  13. package/corpus/core/src/client/settings/AccountSettingsCard.tsx +35 -31
  14. package/corpus/core/src/client/settings/SchedulingTimezoneField.tsx +71 -0
  15. package/corpus/core/src/client/settings/SettingsRow.tsx +113 -0
  16. package/corpus/core/src/client/settings/agent-settings-search.ts +2 -1
  17. package/corpus/core/src/client/settings/index.ts +6 -0
  18. package/corpus/core/src/integrations/identity.ts +2 -12
  19. package/corpus/core/src/jobs/actions/list-automation-runs.ts +33 -0
  20. package/corpus/core/src/jobs/actions/list-recurring-jobs.ts +27 -6
  21. package/corpus/core/src/jobs/actions/manage-recurring-job.ts +41 -9
  22. package/corpus/core/src/jobs/background-automation-runner.ts +88 -0
  23. package/corpus/core/src/jobs/cron.ts +52 -6
  24. package/corpus/core/src/jobs/frontmatter.ts +20 -0
  25. package/corpus/core/src/jobs/run-history.ts +242 -0
  26. package/corpus/core/src/jobs/scheduler.ts +73 -18
  27. package/corpus/core/src/jobs/tools.ts +54 -6
  28. package/corpus/core/src/localization/actions/get-localization-preference.ts +2 -2
  29. package/corpus/core/src/localization/actions/set-localization-preference.ts +49 -11
  30. package/corpus/core/src/localization/default-messages.ts +27 -0
  31. package/corpus/core/src/localization/shared.ts +39 -6
  32. package/corpus/core/src/localization/user-timezone.ts +36 -0
  33. package/corpus/core/src/org/app-roles-handlers.ts +1 -9
  34. package/corpus/core/src/org/index.ts +2 -0
  35. package/corpus/core/src/org/membership.ts +18 -0
  36. package/corpus/core/src/review/actions/create-review-comment.ts +4 -1
  37. package/corpus/core/src/review/actions/reply-review-comment.ts +4 -1
  38. package/corpus/core/src/review/index.ts +5 -0
  39. package/corpus/core/src/review/notifications.ts +163 -0
  40. package/corpus/core/src/review/types.ts +7 -0
  41. package/corpus/core/src/server/action-discovery.ts +4 -0
  42. package/corpus/core/src/server/activity-notifications.ts +174 -0
  43. package/corpus/core/src/server/app-name.ts +31 -0
  44. package/corpus/core/src/server/better-auth-instance.ts +4 -4
  45. package/corpus/core/src/server/email-templates.ts +70 -14
  46. package/corpus/core/src/server/email.ts +66 -3
  47. package/corpus/core/src/server/index.ts +10 -0
  48. package/corpus/core/src/sharing/index.ts +5 -0
  49. package/corpus/core/src/sharing/recipients.ts +67 -0
  50. package/corpus/core/src/triggers/actions/list-automations.ts +27 -8
  51. package/corpus/core/src/triggers/actions/manage-automation.ts +17 -6
  52. package/corpus/core/src/triggers/actions.ts +16 -4
  53. package/corpus/core/src/triggers/dispatcher.ts +44 -30
  54. package/corpus/core/src/triggers/routes.ts +19 -6
  55. package/corpus/core/src/vitest-config.ts +68 -0
  56. package/corpus/core/vitest.config.ts +5 -0
  57. package/corpus/templates/analytics/app/pages/Settings.tsx +37 -53
  58. package/corpus/templates/analytics/changelog/2026-08-01-new-error-alerts-now-reach-you-by-email-and-a-scheduled-dash.md +6 -0
  59. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +43 -0
  60. package/corpus/templates/analytics/server/lib/error-capture.ts +5 -1
  61. package/corpus/templates/analytics/vitest.config.ts +16 -12
  62. package/corpus/templates/assets/actions/refresh-generation-run.ts +3 -0
  63. package/corpus/templates/assets/app/components/ui/switch.tsx +1 -0
  64. package/corpus/templates/assets/app/hooks/use-assets-prefs.ts +55 -0
  65. package/corpus/templates/assets/app/i18n-data.ts +30 -0
  66. package/corpus/templates/assets/app/routes/settings.tsx +58 -55
  67. package/corpus/templates/assets/changelog/2026-08-01-get-an-email-when-a-generation-you-started-finishes-or-fails.md +6 -0
  68. package/corpus/templates/assets/server/lib/generation-run-notifications.ts +89 -0
  69. package/corpus/templates/assets/server/lib/video-runs.ts +8 -1
  70. package/corpus/templates/assets/server/routes/_agent-native/assets/user-prefs.get.ts +17 -0
  71. package/corpus/templates/assets/server/routes/_agent-native/assets/user-prefs.put.ts +36 -0
  72. package/corpus/templates/assets/shared/assets-user-prefs.ts +10 -0
  73. package/corpus/templates/assets/vitest.config.ts +16 -12
  74. package/corpus/templates/brain/app/routes/settings.tsx +15 -15
  75. package/corpus/templates/brain/vitest.config.ts +16 -12
  76. package/corpus/templates/calendar/app/pages/Settings.tsx +32 -40
  77. package/corpus/templates/calendar/changelog/2026-08-01-language-and-appearance-now-sit-together-in-one-preferences-.md +6 -0
  78. package/corpus/templates/calendar/vitest.config.ts +16 -12
  79. package/corpus/templates/chat/app/routes/settings.tsx +14 -22
  80. package/corpus/templates/chat/vitest.config.ts +9 -0
  81. package/corpus/templates/clips/.agents/skills/video-editing/SKILL.md +31 -0
  82. package/corpus/templates/clips/AGENTS.md +1 -0
  83. package/corpus/templates/clips/actions/add-comment.ts +12 -1
  84. package/corpus/templates/clips/actions/create-meeting.ts +2 -2
  85. package/corpus/templates/clips/actions/create-recording.ts +2 -2
  86. package/corpus/templates/clips/actions/finalize-recording.ts +42 -6
  87. package/corpus/templates/clips/actions/generate-filmstrip.ts +154 -0
  88. package/corpus/templates/clips/actions/get-recording-player-data.ts +6 -0
  89. package/corpus/templates/clips/actions/import-loom-recording.ts +2 -2
  90. package/corpus/templates/clips/actions/lib/ensure-recording-filmstrip.ts +258 -0
  91. package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +11 -3
  92. package/corpus/templates/clips/actions/react-to-comment.ts +13 -0
  93. package/corpus/templates/clips/actions/react-to-recording.ts +10 -1
  94. package/corpus/templates/clips/actions/reply-to-comment.ts +12 -1
  95. package/corpus/templates/clips/actions/stitch-recordings.ts +2 -2
  96. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +152 -23
  97. package/corpus/templates/clips/app/components/editor/waveform.tsx +237 -75
  98. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +23 -1
  99. package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +441 -0
  100. package/corpus/templates/clips/app/components/settings/slack-section.tsx +329 -0
  101. package/corpus/templates/clips/app/components/settings/types.ts +14 -0
  102. package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +443 -0
  103. package/corpus/templates/clips/app/hooks/use-secret-status.ts +69 -0
  104. package/corpus/templates/clips/app/i18n/en-US.ts +9 -1
  105. package/corpus/templates/clips/app/lib/video-filmstrip.ts +262 -0
  106. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +165 -1351
  107. package/corpus/templates/clips/changelog/2026-07-27-saved-clips-now-resume-from-the-last-uploaded-byte-after-an-.md +6 -0
  108. package/corpus/templates/clips/changelog/2026-07-29-meeting-notes-no-longer-transcribe-the-other-side-twice-when.md +6 -0
  109. package/corpus/templates/clips/changelog/2026-07-31-editor-timeline-now-shows-video-frames-behind-the-waveform-g.md +6 -0
  110. package/corpus/templates/clips/changelog/2026-07-31-email-notifications-now-go-out-when-someone-comments-on-or-r.md +6 -0
  111. package/corpus/templates/clips/changelog/2026-07-31-you-can-now-set-a-default-visibility-for-new-recordings-in-s.md +6 -0
  112. package/corpus/templates/clips/changelog/2026-08-01-email-notifications-for-comments-and-reactions-now-actually-.md +6 -0
  113. package/corpus/templates/clips/changelog/2026-08-03-the-desktop-app-now-opens-directly-beneath-its-tray-icon-on-.md +6 -0
  114. package/corpus/templates/clips/chrome-extension/package.json +1 -0
  115. package/corpus/templates/clips/chrome-extension/vitest.config.ts +9 -0
  116. package/corpus/templates/clips/desktop/package.json +1 -0
  117. package/corpus/templates/clips/desktop/src/app.tsx +17 -1
  118. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +37 -48
  119. package/corpus/templates/clips/desktop/src/lib/recorder.ts +331 -36
  120. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +7 -5
  121. package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +182 -106
  122. package/corpus/templates/clips/desktop/src/lib/upload-recovery.ts +129 -0
  123. package/corpus/templates/clips/desktop/src/overlays/live-transcript.tsx +43 -14
  124. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +3 -3
  125. package/corpus/templates/clips/desktop/src-tauri/src/echo_guard.rs +443 -0
  126. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -0
  127. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +815 -15
  128. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +61 -11
  129. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +125 -16
  130. package/corpus/templates/clips/desktop/vitest.config.ts +9 -0
  131. package/corpus/templates/clips/server/db/schema.ts +17 -0
  132. package/corpus/templates/clips/server/jobs/media-verification.ts +4 -0
  133. package/corpus/templates/clips/server/lib/activity-notifications.ts +185 -0
  134. package/corpus/templates/clips/server/lib/recording-media-cleanup.ts +2 -0
  135. package/corpus/templates/clips/server/lib/recording-upload-state.ts +46 -9
  136. package/corpus/templates/clips/server/lib/recordings.ts +24 -0
  137. package/corpus/templates/clips/server/lib/resumable-session.ts +10 -4
  138. package/corpus/templates/clips/server/lib/transactional-email-templates.ts +109 -0
  139. package/corpus/templates/clips/server/lib/upload-interruption.ts +8 -0
  140. package/corpus/templates/clips/server/lib/upload-lease.ts +50 -4
  141. package/corpus/templates/clips/server/lib/video-filmstrip-sprite.ts +207 -0
  142. package/corpus/templates/clips/server/lib/video-remux.ts +13 -4
  143. package/corpus/templates/clips/server/plugins/db.ts +16 -0
  144. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +4 -0
  145. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +123 -36
  146. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +159 -29
  147. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +197 -0
  148. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +193 -39
  149. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/resume.get.ts +191 -12
  150. package/corpus/templates/clips/shared/clips-ai-prefs.ts +6 -0
  151. package/corpus/templates/clips/shared/feature-flags.ts +12 -0
  152. package/corpus/templates/clips/shared/recording-core.ts +4 -0
  153. package/corpus/templates/clips/vitest.config.ts +23 -19
  154. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +6 -4
  155. package/corpus/templates/content/actions/_database-membership-lock.ts +25 -0
  156. package/corpus/templates/content/actions/_database-row-batch.ts +6 -2
  157. package/corpus/templates/content/actions/_database-source-utils.ts +289 -129
  158. package/corpus/templates/content/actions/_database-utils.ts +12 -3
  159. package/corpus/templates/content/actions/add-comment.ts +15 -1
  160. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +39 -21
  161. package/corpus/templates/content/actions/attach-content-database-source.ts +4 -1
  162. package/corpus/templates/content/actions/change-content-database-source-role.ts +3 -5
  163. package/corpus/templates/content/actions/duplicate-document-property.ts +59 -46
  164. package/corpus/templates/content/actions/execute-builder-source-execution.ts +77 -71
  165. package/corpus/templates/content/actions/list-documents.ts +1 -0
  166. package/corpus/templates/content/actions/materialize-builder-required-fields.ts +7 -0
  167. package/corpus/templates/content/actions/remove-database-items.ts +183 -0
  168. package/corpus/templates/content/actions/set-document-property.ts +57 -39
  169. package/corpus/templates/content/actions/sync-local-folder-source.ts +7 -0
  170. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +5 -2
  171. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +50 -1
  172. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +471 -329
  173. package/corpus/templates/content/app/components/editor/database/row-access.ts +45 -0
  174. package/corpus/templates/content/app/components/editor/database/shared.tsx +141 -38
  175. package/corpus/templates/content/app/components/ui/switch.tsx +1 -0
  176. package/corpus/templates/content/app/hooks/use-content-database.ts +2 -2
  177. package/corpus/templates/content/app/hooks/use-content-prefs.ts +55 -0
  178. package/corpus/templates/content/app/i18n-data.ts +170 -0
  179. package/corpus/templates/content/app/routes/_app.settings.tsx +47 -18
  180. package/corpus/templates/content/changelog/2026-07-30-breadcrumb-menus-now-hide-internal-system-pages.md +6 -0
  181. package/corpus/templates/content/changelog/2026-07-30-database-rows-can-now-be-removed-without-deleting-their-page.md +6 -0
  182. package/corpus/templates/content/changelog/2026-08-01-get-an-email-when-someone-comments-on-replies-in-or-mentions.md +6 -0
  183. package/corpus/templates/content/parity/eval-scenarios.ts +2 -2
  184. package/corpus/templates/content/parity/matrix.md +1 -1
  185. package/corpus/templates/content/parity/matrix.ts +4 -5
  186. package/corpus/templates/content/server/lib/comment-notifications.ts +146 -0
  187. package/corpus/templates/content/server/routes/_agent-native/content/user-prefs.get.ts +17 -0
  188. package/corpus/templates/content/server/routes/_agent-native/content/user-prefs.put.ts +36 -0
  189. package/corpus/templates/content/shared/api.ts +4 -0
  190. package/corpus/templates/content/shared/content-user-prefs.ts +11 -0
  191. package/corpus/templates/content/vitest.config.ts +20 -16
  192. package/corpus/templates/crm/app/routes/settings.tsx +14 -22
  193. package/corpus/templates/crm/vitest.config.ts +8 -4
  194. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +26 -11
  195. package/corpus/templates/design/actions/take-design-screenshot.ts +7 -0
  196. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +11 -3
  197. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +4 -1
  198. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +54 -17
  199. package/corpus/templates/design/app/components/design/design-canvas/local-runtime.ts +126 -0
  200. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +2 -0
  201. package/corpus/templates/design/app/pages/Index.tsx +3 -1
  202. package/corpus/templates/design/app/pages/Present.tsx +2 -1
  203. package/corpus/templates/design/app/routes/settings.tsx +14 -22
  204. package/corpus/templates/design/changelog/2026-07-30-a-broken-inline-script-in-a-generated-screen-is-now-caught-o.md +6 -0
  205. package/corpus/templates/design/changelog/2026-07-30-design-html-is-now-validated-with-a-spec-grade-html-parser-i.md +6 -0
  206. package/corpus/templates/design/changelog/2026-07-30-designs-now-load-their-tailwind-and-alpine-runtimes-from-the.md +6 -0
  207. package/corpus/templates/design/changelog/2026-07-30-designs-with-a-broken-alpine-expression-are-now-caught-on-sa.md +6 -0
  208. package/corpus/templates/design/changelog/2026-07-30-editing-a-design-no-longer-strips-its-styling-the-canvas-kep.md +6 -0
  209. package/corpus/templates/design/changelog/2026-08-01-review-comments-replies-and-mentions-now-send-an-email-to-th.md +6 -0
  210. package/corpus/templates/design/package.json +4 -0
  211. package/corpus/templates/design/shared/html-integrity.ts +802 -556
  212. package/corpus/templates/design/vitest.config.ts +18 -12
  213. package/corpus/templates/dispatch/app/routes/settings.tsx +26 -40
  214. package/corpus/templates/dispatch/vitest.config.ts +11 -7
  215. package/corpus/templates/factory/app/routes/settings.tsx +14 -22
  216. package/corpus/templates/factory/vitest.config.ts +9 -0
  217. package/corpus/templates/forms/app/routes/_app.settings.tsx +14 -22
  218. package/corpus/templates/forms/vitest.config.ts +27 -23
  219. package/corpus/templates/macros/app/routes/settings.tsx +14 -22
  220. package/corpus/templates/macros/vitest.config.ts +16 -12
  221. package/corpus/templates/mail/app/pages/SettingsPage.tsx +14 -16
  222. package/corpus/templates/mail/vitest.config.ts +16 -12
  223. package/corpus/templates/plan/app/routes/settings.tsx +30 -44
  224. package/corpus/templates/plan/vitest.config.ts +24 -20
  225. package/corpus/templates/slides/actions/add-slide-comment.ts +12 -1
  226. package/corpus/templates/slides/app/components/ui/switch.tsx +1 -0
  227. package/corpus/templates/slides/app/hooks/use-slides-prefs.ts +55 -0
  228. package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
  229. package/corpus/templates/slides/app/routes/settings.tsx +45 -22
  230. package/corpus/templates/slides/changelog/2026-08-01-get-an-email-when-someone-comments-on-or-replies-in-your-dec.md +6 -0
  231. package/corpus/templates/slides/server/lib/comment-notifications.ts +182 -0
  232. package/corpus/templates/slides/server/routes/_agent-native/slides/user-prefs.get.ts +16 -0
  233. package/corpus/templates/slides/server/routes/_agent-native/slides/user-prefs.put.ts +36 -0
  234. package/corpus/templates/slides/shared/slides-user-prefs.ts +11 -0
  235. package/corpus/templates/slides/vitest.config.ts +17 -13
  236. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +2 -0
  237. package/corpus/templates/tasks/app/routes/settings.tsx +14 -22
  238. package/corpus/templates/tasks/vitest.config.ts +17 -13
  239. package/corpus/toolkit/CHANGELOG.md +9 -0
  240. package/corpus/toolkit/package.json +1 -1
  241. package/corpus/toolkit/vitest.config.ts +3 -0
  242. package/dist/automations/service.d.ts +2 -0
  243. package/dist/automations/service.d.ts.map +1 -1
  244. package/dist/automations/service.js +29 -4
  245. package/dist/automations/service.js.map +1 -1
  246. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  247. package/dist/cli/mcp-config-writers.js +24 -23
  248. package/dist/cli/mcp-config-writers.js.map +1 -1
  249. package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
  250. package/dist/client/agent-page/AgentJobsTab.js +86 -29
  251. package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
  252. package/dist/client/agent-page/AutomationDetailsDialog.d.ts +21 -0
  253. package/dist/client/agent-page/AutomationDetailsDialog.d.ts.map +1 -0
  254. package/dist/client/agent-page/AutomationDetailsDialog.js +33 -0
  255. package/dist/client/agent-page/AutomationDetailsDialog.js.map +1 -0
  256. package/dist/client/agent-page/AutomationScheduleDialog.d.ts +15 -0
  257. package/dist/client/agent-page/AutomationScheduleDialog.d.ts.map +1 -0
  258. package/dist/client/agent-page/AutomationScheduleDialog.js +46 -0
  259. package/dist/client/agent-page/AutomationScheduleDialog.js.map +1 -0
  260. package/dist/client/agent-page/TimezoneSelect.d.ts +17 -0
  261. package/dist/client/agent-page/TimezoneSelect.d.ts.map +1 -0
  262. package/dist/client/agent-page/TimezoneSelect.js +107 -0
  263. package/dist/client/agent-page/TimezoneSelect.js.map +1 -0
  264. package/dist/client/agent-page/use-jobs.d.ts +20 -7
  265. package/dist/client/agent-page/use-jobs.d.ts.map +1 -1
  266. package/dist/client/agent-page/use-jobs.js +24 -4
  267. package/dist/client/agent-page/use-jobs.js.map +1 -1
  268. package/dist/client/org/OrgSwitcher.d.ts +8 -1
  269. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  270. package/dist/client/org/OrgSwitcher.js +8 -2
  271. package/dist/client/org/OrgSwitcher.js.map +1 -1
  272. package/dist/client/settings/AccountSettingsCard.d.ts.map +1 -1
  273. package/dist/client/settings/AccountSettingsCard.js +10 -9
  274. package/dist/client/settings/AccountSettingsCard.js.map +1 -1
  275. package/dist/client/settings/SchedulingTimezoneField.d.ts +10 -0
  276. package/dist/client/settings/SchedulingTimezoneField.d.ts.map +1 -0
  277. package/dist/client/settings/SchedulingTimezoneField.js +30 -0
  278. package/dist/client/settings/SchedulingTimezoneField.js.map +1 -0
  279. package/dist/client/settings/SettingsRow.d.ts +36 -0
  280. package/dist/client/settings/SettingsRow.d.ts.map +1 -0
  281. package/dist/client/settings/SettingsRow.js +15 -0
  282. package/dist/client/settings/SettingsRow.js.map +1 -0
  283. package/dist/client/settings/agent-settings-search.d.ts.map +1 -1
  284. package/dist/client/settings/agent-settings-search.js +1 -1
  285. package/dist/client/settings/agent-settings-search.js.map +1 -1
  286. package/dist/client/settings/index.d.ts +1 -0
  287. package/dist/client/settings/index.d.ts.map +1 -1
  288. package/dist/client/settings/index.js +1 -0
  289. package/dist/client/settings/index.js.map +1 -1
  290. package/dist/collab/struct-routes.d.ts +1 -1
  291. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  292. package/dist/integrations/identity.d.ts.map +1 -1
  293. package/dist/integrations/identity.js +2 -11
  294. package/dist/integrations/identity.js.map +1 -1
  295. package/dist/jobs/actions/list-automation-runs.d.ts +8 -0
  296. package/dist/jobs/actions/list-automation-runs.d.ts.map +1 -0
  297. package/dist/jobs/actions/list-automation-runs.js +29 -0
  298. package/dist/jobs/actions/list-automation-runs.js.map +1 -0
  299. package/dist/jobs/actions/list-recurring-jobs.d.ts +2 -0
  300. package/dist/jobs/actions/list-recurring-jobs.d.ts.map +1 -1
  301. package/dist/jobs/actions/list-recurring-jobs.js +20 -7
  302. package/dist/jobs/actions/list-recurring-jobs.js.map +1 -1
  303. package/dist/jobs/actions/manage-recurring-job.d.ts +2 -0
  304. package/dist/jobs/actions/manage-recurring-job.js +30 -9
  305. package/dist/jobs/actions/manage-recurring-job.js.map +1 -1
  306. package/dist/jobs/background-automation-runner.d.ts.map +1 -1
  307. package/dist/jobs/background-automation-runner.js +60 -0
  308. package/dist/jobs/background-automation-runner.js.map +1 -1
  309. package/dist/jobs/cron.d.ts +16 -2
  310. package/dist/jobs/cron.d.ts.map +1 -1
  311. package/dist/jobs/cron.js +43 -6
  312. package/dist/jobs/cron.js.map +1 -1
  313. package/dist/jobs/frontmatter.d.ts +12 -0
  314. package/dist/jobs/frontmatter.d.ts.map +1 -1
  315. package/dist/jobs/frontmatter.js +8 -0
  316. package/dist/jobs/frontmatter.js.map +1 -1
  317. package/dist/jobs/run-history.d.ts +56 -0
  318. package/dist/jobs/run-history.d.ts.map +1 -0
  319. package/dist/jobs/run-history.js +169 -0
  320. package/dist/jobs/run-history.js.map +1 -0
  321. package/dist/jobs/scheduler.d.ts.map +1 -1
  322. package/dist/jobs/scheduler.js +51 -18
  323. package/dist/jobs/scheduler.js.map +1 -1
  324. package/dist/jobs/tools.d.ts.map +1 -1
  325. package/dist/jobs/tools.js +37 -6
  326. package/dist/jobs/tools.js.map +1 -1
  327. package/dist/localization/actions/get-localization-preference.d.ts +1 -2
  328. package/dist/localization/actions/get-localization-preference.d.ts.map +1 -1
  329. package/dist/localization/actions/get-localization-preference.js.map +1 -1
  330. package/dist/localization/actions/set-localization-preference.d.ts +3 -3
  331. package/dist/localization/actions/set-localization-preference.d.ts.map +1 -1
  332. package/dist/localization/actions/set-localization-preference.js +33 -8
  333. package/dist/localization/actions/set-localization-preference.js.map +1 -1
  334. package/dist/localization/default-messages.d.ts +25 -0
  335. package/dist/localization/default-messages.d.ts.map +1 -1
  336. package/dist/localization/default-messages.js +25 -0
  337. package/dist/localization/default-messages.js.map +1 -1
  338. package/dist/localization/shared.d.ts +16 -1
  339. package/dist/localization/shared.d.ts.map +1 -1
  340. package/dist/localization/shared.js +22 -4
  341. package/dist/localization/shared.js.map +1 -1
  342. package/dist/localization/user-timezone.d.ts +11 -0
  343. package/dist/localization/user-timezone.d.ts.map +1 -0
  344. package/dist/localization/user-timezone.js +31 -0
  345. package/dist/localization/user-timezone.js.map +1 -0
  346. package/dist/notifications/routes.d.ts +2 -2
  347. package/dist/observability/routes.d.ts +1 -1
  348. package/dist/org/app-roles-handlers.d.ts.map +1 -1
  349. package/dist/org/app-roles-handlers.js +1 -8
  350. package/dist/org/app-roles-handlers.js.map +1 -1
  351. package/dist/org/index.d.ts +1 -0
  352. package/dist/org/index.d.ts.map +1 -1
  353. package/dist/org/index.js +1 -0
  354. package/dist/org/index.js.map +1 -1
  355. package/dist/org/membership.d.ts +6 -0
  356. package/dist/org/membership.d.ts.map +1 -0
  357. package/dist/org/membership.js +16 -0
  358. package/dist/org/membership.js.map +1 -0
  359. package/dist/provider-api/actions/custom-provider-registration.d.ts +10 -10
  360. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  361. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  362. package/dist/resources/handlers.d.ts +1 -1
  363. package/dist/review/actions/create-review-comment.d.ts +32 -1
  364. package/dist/review/actions/create-review-comment.d.ts.map +1 -1
  365. package/dist/review/actions/create-review-comment.js +3 -1
  366. package/dist/review/actions/create-review-comment.js.map +1 -1
  367. package/dist/review/actions/reply-review-comment.d.ts +32 -1
  368. package/dist/review/actions/reply-review-comment.d.ts.map +1 -1
  369. package/dist/review/actions/reply-review-comment.js +3 -1
  370. package/dist/review/actions/reply-review-comment.js.map +1 -1
  371. package/dist/review/index.d.ts +1 -0
  372. package/dist/review/index.d.ts.map +1 -1
  373. package/dist/review/index.js +1 -0
  374. package/dist/review/index.js.map +1 -1
  375. package/dist/review/notifications.d.ts +24 -0
  376. package/dist/review/notifications.d.ts.map +1 -0
  377. package/dist/review/notifications.js +123 -0
  378. package/dist/review/notifications.js.map +1 -0
  379. package/dist/review/types.d.ts +5 -0
  380. package/dist/review/types.d.ts.map +1 -1
  381. package/dist/review/types.js.map +1 -1
  382. package/dist/server/action-discovery.d.ts.map +1 -1
  383. package/dist/server/action-discovery.js +4 -0
  384. package/dist/server/action-discovery.js.map +1 -1
  385. package/dist/server/activity-notifications.d.ts +61 -0
  386. package/dist/server/activity-notifications.d.ts.map +1 -0
  387. package/dist/server/activity-notifications.js +103 -0
  388. package/dist/server/activity-notifications.js.map +1 -0
  389. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  390. package/dist/server/app-name.d.ts +18 -0
  391. package/dist/server/app-name.d.ts.map +1 -1
  392. package/dist/server/app-name.js +31 -0
  393. package/dist/server/app-name.js.map +1 -1
  394. package/dist/server/better-auth-instance.js +4 -4
  395. package/dist/server/better-auth-instance.js.map +1 -1
  396. package/dist/server/email-templates.d.ts +12 -0
  397. package/dist/server/email-templates.d.ts.map +1 -1
  398. package/dist/server/email-templates.js +57 -14
  399. package/dist/server/email-templates.js.map +1 -1
  400. package/dist/server/email.d.ts +12 -0
  401. package/dist/server/email.d.ts.map +1 -1
  402. package/dist/server/email.js +52 -5
  403. package/dist/server/email.js.map +1 -1
  404. package/dist/server/index.d.ts +1 -0
  405. package/dist/server/index.d.ts.map +1 -1
  406. package/dist/server/index.js +1 -0
  407. package/dist/server/index.js.map +1 -1
  408. package/dist/sharing/index.d.ts +1 -0
  409. package/dist/sharing/index.d.ts.map +1 -1
  410. package/dist/sharing/index.js +1 -0
  411. package/dist/sharing/index.js.map +1 -1
  412. package/dist/sharing/recipients.d.ts +31 -0
  413. package/dist/sharing/recipients.d.ts.map +1 -0
  414. package/dist/sharing/recipients.js +40 -0
  415. package/dist/sharing/recipients.js.map +1 -0
  416. package/dist/templates/chat/app/routes/settings.tsx +14 -22
  417. package/dist/templates/chat/vitest.config.ts +9 -0
  418. package/dist/triggers/actions/list-automations.d.ts +2 -0
  419. package/dist/triggers/actions/list-automations.d.ts.map +1 -1
  420. package/dist/triggers/actions/list-automations.js +19 -8
  421. package/dist/triggers/actions/list-automations.js.map +1 -1
  422. package/dist/triggers/actions/manage-automation.d.ts +6 -0
  423. package/dist/triggers/actions/manage-automation.js +12 -6
  424. package/dist/triggers/actions/manage-automation.js.map +1 -1
  425. package/dist/triggers/actions.d.ts.map +1 -1
  426. package/dist/triggers/actions.js +15 -4
  427. package/dist/triggers/actions.js.map +1 -1
  428. package/dist/triggers/dispatcher.d.ts.map +1 -1
  429. package/dist/triggers/dispatcher.js +19 -17
  430. package/dist/triggers/dispatcher.js.map +1 -1
  431. package/dist/triggers/routes.d.ts.map +1 -1
  432. package/dist/triggers/routes.js +6 -6
  433. package/dist/triggers/routes.js.map +1 -1
  434. package/dist/vitest-config.d.ts +10 -0
  435. package/dist/vitest-config.d.ts.map +1 -0
  436. package/dist/vitest-config.js +55 -0
  437. package/dist/vitest-config.js.map +1 -0
  438. package/docs/content/template-content-developers.mdx +1 -1
  439. package/package.json +5 -4
  440. package/src/automations/service.ts +41 -4
  441. package/src/cli/mcp-config-writers.ts +27 -21
  442. package/src/client/agent-page/AgentJobsTab.tsx +187 -85
  443. package/src/client/agent-page/AutomationDetailsDialog.tsx +208 -0
  444. package/src/client/agent-page/AutomationScheduleDialog.tsx +180 -0
  445. package/src/client/agent-page/TimezoneSelect.tsx +241 -0
  446. package/src/client/agent-page/use-jobs.ts +50 -10
  447. package/src/client/org/OrgSwitcher.tsx +26 -0
  448. package/src/client/settings/AccountSettingsCard.tsx +35 -31
  449. package/src/client/settings/SchedulingTimezoneField.tsx +71 -0
  450. package/src/client/settings/SettingsRow.tsx +113 -0
  451. package/src/client/settings/agent-settings-search.ts +2 -1
  452. package/src/client/settings/index.ts +6 -0
  453. package/src/integrations/identity.ts +2 -12
  454. package/src/jobs/actions/list-automation-runs.ts +33 -0
  455. package/src/jobs/actions/list-recurring-jobs.ts +27 -6
  456. package/src/jobs/actions/manage-recurring-job.ts +41 -9
  457. package/src/jobs/background-automation-runner.ts +88 -0
  458. package/src/jobs/cron.ts +52 -6
  459. package/src/jobs/frontmatter.ts +20 -0
  460. package/src/jobs/run-history.ts +242 -0
  461. package/src/jobs/scheduler.ts +73 -18
  462. package/src/jobs/tools.ts +54 -6
  463. package/src/localization/actions/get-localization-preference.ts +2 -2
  464. package/src/localization/actions/set-localization-preference.ts +49 -11
  465. package/src/localization/default-messages.ts +27 -0
  466. package/src/localization/shared.ts +39 -6
  467. package/src/localization/user-timezone.ts +36 -0
  468. package/src/org/app-roles-handlers.ts +1 -9
  469. package/src/org/index.ts +2 -0
  470. package/src/org/membership.ts +18 -0
  471. package/src/review/actions/create-review-comment.ts +4 -1
  472. package/src/review/actions/reply-review-comment.ts +4 -1
  473. package/src/review/index.ts +5 -0
  474. package/src/review/notifications.ts +163 -0
  475. package/src/review/types.ts +7 -0
  476. package/src/server/action-discovery.ts +4 -0
  477. package/src/server/activity-notifications.ts +174 -0
  478. package/src/server/app-name.ts +31 -0
  479. package/src/server/better-auth-instance.ts +4 -4
  480. package/src/server/email-templates.ts +70 -14
  481. package/src/server/email.ts +66 -3
  482. package/src/server/index.ts +10 -0
  483. package/src/sharing/index.ts +5 -0
  484. package/src/sharing/recipients.ts +67 -0
  485. package/src/templates/chat/app/routes/settings.tsx +14 -22
  486. package/src/templates/chat/vitest.config.ts +9 -0
  487. package/src/triggers/actions/list-automations.ts +27 -8
  488. package/src/triggers/actions/manage-automation.ts +17 -6
  489. package/src/triggers/actions.ts +16 -4
  490. package/src/triggers/dispatcher.ts +44 -30
  491. package/src/triggers/routes.ts +19 -6
  492. package/src/vitest-config.ts +68 -0
  493. package/corpus/templates/content/actions/delete-database-items.ts +0 -89
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Email notifications for document comments, replies, and mentions.
3
+ *
4
+ * Recipient resolution, preference filtering, and delivery reporting come from
5
+ * `@agent-native/core/server`; this module owns only the Documents rows and the
6
+ * email copy. Share invites are not routed through the `emailNotifications`
7
+ * preference — they have their own delivery path.
8
+ */
9
+
10
+ import {
11
+ emailStrong,
12
+ getAppProductionUrl,
13
+ notifyActivity,
14
+ renderEmail,
15
+ runActivityNotification,
16
+ sendEmail,
17
+ type ActivityNotificationResult,
18
+ } from "@agent-native/core/server";
19
+ import { filterRecipientsByResourceAccess } from "@agent-native/core/sharing";
20
+ import { and, eq } from "drizzle-orm";
21
+
22
+ import { CONTENT_USER_PREFS_KEY } from "../../shared/content-user-prefs.js";
23
+ import { getDb, schema } from "../db/index.js";
24
+
25
+ export type DocumentCommentNotificationResult = ActivityNotificationResult;
26
+
27
+ const LOG_LABEL = "[content] comment notification";
28
+ const EXCERPT_LIMIT = 240;
29
+
30
+ function excerpt(content: string): string {
31
+ const collapsed = content.replace(/\s+/g, " ").trim();
32
+ return collapsed.length > EXCERPT_LIMIT
33
+ ? `${collapsed.slice(0, EXCERPT_LIMIT - 1)}…`
34
+ : collapsed;
35
+ }
36
+
37
+ function documentUrl(documentId: string): string {
38
+ const base = getAppProductionUrl().replace(/\/+$/, "");
39
+ return `${base}/page/${encodeURIComponent(documentId)}`;
40
+ }
41
+
42
+ async function threadParticipants(
43
+ documentId: string,
44
+ threadId: string,
45
+ ): Promise<string[]> {
46
+ const rows = await getDb()
47
+ .select({ authorEmail: schema.documentComments.authorEmail })
48
+ .from(schema.documentComments)
49
+ .where(
50
+ and(
51
+ eq(schema.documentComments.documentId, documentId),
52
+ eq(schema.documentComments.threadId, threadId),
53
+ ),
54
+ );
55
+ return rows.map((row) => row.authorEmail);
56
+ }
57
+
58
+ export interface DocumentCommentNotificationInput {
59
+ documentId: string;
60
+ /** Read from the access-checked resource by the caller, never re-queried. */
61
+ documentTitle: string;
62
+ /** The document's org, so `org` visibility resolves for its members. */
63
+ orgId?: string | null;
64
+ threadId: string;
65
+ ownerEmail: string;
66
+ authorEmail: string;
67
+ authorName?: string | null;
68
+ content: string;
69
+ mentions: { email: string; name: string }[];
70
+ isReply: boolean;
71
+ }
72
+
73
+ export async function notifyDocumentComment(
74
+ input: DocumentCommentNotificationInput,
75
+ ): Promise<DocumentCommentNotificationResult> {
76
+ return runActivityNotification(LOG_LABEL, () =>
77
+ deliverDocumentCommentEmails(input),
78
+ );
79
+ }
80
+
81
+ async function deliverDocumentCommentEmails(
82
+ input: DocumentCommentNotificationInput,
83
+ ): Promise<DocumentCommentNotificationResult> {
84
+ const title = input.documentTitle.trim() || "Untitled";
85
+ const mentioned = new Set(
86
+ input.mentions.map((mention) => mention.email.trim().toLowerCase()),
87
+ );
88
+
89
+ const candidates = [input.ownerEmail, ...mentioned];
90
+ if (input.isReply) {
91
+ candidates.push(
92
+ ...(await threadParticipants(input.documentId, input.threadId)),
93
+ );
94
+ }
95
+
96
+ // Mentions are caller-supplied and thread rows are historical; re-check both
97
+ // against the document's live ACL before mailing anyone its contents.
98
+ const allowed = await filterRecipientsByResourceAccess({
99
+ resourceType: "document",
100
+ resourceId: input.documentId,
101
+ emails: candidates,
102
+ orgId: input.orgId,
103
+ });
104
+
105
+ const actor = input.authorName?.trim() || input.authorEmail;
106
+ const url = documentUrl(input.documentId);
107
+
108
+ return notifyActivity({
109
+ candidates: allowed,
110
+ actorEmail: input.authorEmail,
111
+ preferenceKey: CONTENT_USER_PREFS_KEY,
112
+ logLabel: LOG_LABEL,
113
+ send: async (to) => {
114
+ const wasMentioned = mentioned.has(to);
115
+ const lead = wasMentioned
116
+ ? `${emailStrong(actor)} mentioned you in a comment on ${emailStrong(title)}.`
117
+ : input.isReply
118
+ ? `${emailStrong(actor)} replied in a comment thread on ${emailStrong(title)}.`
119
+ : `${emailStrong(actor)} commented on ${emailStrong(title)}.`;
120
+
121
+ const { html, text } = renderEmail({
122
+ preheader: `${actor} commented on ${title}.`,
123
+ heading: wasMentioned
124
+ ? "You were mentioned"
125
+ : input.isReply
126
+ ? "New reply on your document"
127
+ : "New comment",
128
+ paragraphs: [lead, `"${excerpt(input.content)}"`],
129
+ cta: { label: "Open document", url },
130
+ footer:
131
+ "You received this because you own, were mentioned in, or participated in this thread. Turn these off in Documents settings.",
132
+ });
133
+
134
+ await sendEmail({
135
+ to,
136
+ subject: wasMentioned
137
+ ? `${actor} mentioned you on "${title}"`
138
+ : input.isReply
139
+ ? `${actor} replied to a comment on "${title}"`
140
+ : `${actor} commented on "${title}"`,
141
+ html,
142
+ text,
143
+ });
144
+ },
145
+ });
146
+ }
@@ -0,0 +1,17 @@
1
+ import { getSession } from "@agent-native/core/server";
2
+ import { getUserSetting } from "@agent-native/core/settings";
3
+ import { defineEventHandler, setResponseStatus } from "h3";
4
+
5
+ import { CONTENT_USER_PREFS_KEY } from "../../../../shared/content-user-prefs.js";
6
+
7
+ export default defineEventHandler(async (event) => {
8
+ const session = await getSession(event);
9
+ if (!session?.email) {
10
+ setResponseStatus(event, 401);
11
+ return { error: "unauthorized" };
12
+ }
13
+
14
+ const stored = await getUserSetting(session.email, CONTENT_USER_PREFS_KEY);
15
+ // coercion-ok: a null read means this user has no preferences yet, which is a real state.
16
+ return stored ?? {};
17
+ });
@@ -0,0 +1,36 @@
1
+ import { getSession } from "@agent-native/core/server";
2
+ import { getUserSetting, putUserSetting } from "@agent-native/core/settings";
3
+ import { defineEventHandler, getHeader, readBody, setResponseStatus } from "h3";
4
+
5
+ import { CONTENT_USER_PREFS_KEY } from "../../../../shared/content-user-prefs.js";
6
+
7
+ export default defineEventHandler(async (event) => {
8
+ const session = await getSession(event);
9
+ if (!session?.email) {
10
+ setResponseStatus(event, 401);
11
+ return { error: "unauthorized" };
12
+ }
13
+
14
+ // coercion-ok: an unparsable body is rejected with 400 immediately below.
15
+ const body = await readBody(event).catch(() => null);
16
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
17
+ setResponseStatus(event, 400);
18
+ return { error: "Invalid settings payload" };
19
+ }
20
+
21
+ // Merge so a partial save never wipes preferences written elsewhere.
22
+ const stored = await getUserSetting(session.email, CONTENT_USER_PREFS_KEY);
23
+ // coercion-ok: a null read means this user has no preferences yet, which is a real state.
24
+ const existing = stored ?? {};
25
+ const next = {
26
+ ...(typeof existing === "object" && !Array.isArray(existing)
27
+ ? existing
28
+ : {}),
29
+ ...(body as Record<string, unknown>),
30
+ };
31
+
32
+ await putUserSetting(session.email, CONTENT_USER_PREFS_KEY, next, {
33
+ requestSource: getHeader(event, "x-request-source") || undefined,
34
+ });
35
+ return next;
36
+ });
@@ -29,6 +29,7 @@ export interface Document {
29
29
  notionPageUrl?: string | null;
30
30
  visibility?: "private" | "org" | "public";
31
31
  accessRole?: DocumentAccessRole;
32
+ canView?: boolean;
32
33
  canEdit?: boolean;
33
34
  canManage?: boolean;
34
35
  source?: DocumentSourceInfo;
@@ -795,6 +796,9 @@ export interface ContentDatabaseResponse {
795
796
  duplicatedDocumentIds?: string[];
796
797
  deletedItemIds?: string[];
797
798
  deletedDocumentIds?: string[];
799
+ removedItemIds?: string[];
800
+ removedDocumentIds?: string[];
801
+ removedCount?: number;
798
802
  timings?: BuilderActionTiming[];
799
803
  tableQueryMode?: "server" | "client-required";
800
804
  /** Client-only optimistic state while real provider rows are being attached. */
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Per-user Documents preferences, stored under one user-setting key so
3
+ * Settings and the notification senders read and write the same object.
4
+ */
5
+
6
+ export const CONTENT_USER_PREFS_KEY = "content-user-prefs";
7
+
8
+ export type ContentUserPrefs = {
9
+ /** Comment, reply, and mention emails only — never share invites. */
10
+ emailNotifications?: boolean;
11
+ };
@@ -1,21 +1,25 @@
1
1
  import path from "node:path";
2
2
 
3
+ import baseConfig from "@agent-native/core/vitest-config";
3
4
  import react from "@vitejs/plugin-react-swc";
4
- import { defineConfig } from "vitest/config";
5
+ import { defineConfig, mergeConfig } from "vitest/config";
5
6
 
6
- export default defineConfig({
7
- plugins: [react()],
8
- resolve: {
9
- alias: {
10
- "@": path.resolve(__dirname, "./app"),
11
- "@shared": path.resolve(__dirname, "./shared"),
7
+ export default mergeConfig(
8
+ baseConfig,
9
+ defineConfig({
10
+ plugins: [react()],
11
+ resolve: {
12
+ alias: {
13
+ "@": path.resolve(__dirname, "./app"),
14
+ "@shared": path.resolve(__dirname, "./shared"),
15
+ },
12
16
  },
13
- },
14
- test: {
15
- include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
16
- exclude: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/e2e/**"],
17
- hookTimeout: 60_000,
18
- testTimeout: 60_000,
19
- maxWorkers: "50%",
20
- },
21
- });
17
+ test: {
18
+ include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
19
+ exclude: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/e2e/**"],
20
+ hookTimeout: 60_000,
21
+ testTimeout: 60_000,
22
+ maxWorkers: "50%",
23
+ },
24
+ }),
25
+ );
@@ -1,6 +1,8 @@
1
1
  import { ChangelogSettingsCard } from "@agent-native/core/client/changelog";
2
2
  import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
3
3
  import {
4
+ SettingsGroup,
5
+ SettingsRow,
4
6
  SettingsTabsPage,
5
7
  useAgentSettingsTabs,
6
8
  type SettingsTabItem,
@@ -20,14 +22,6 @@ import { AdvancedSettings } from "@/components/crm/settings/AdvancedSettings";
20
22
  import { ConnectionSettings } from "@/components/crm/settings/ConnectionSettings";
21
23
  import { FieldsSettings } from "@/components/crm/settings/FieldsSettings";
22
24
  import { ListsSettings } from "@/components/crm/settings/ListsSettings";
23
- import {
24
- Card,
25
- CardContent,
26
- CardDescription,
27
- CardHeader,
28
- CardTitle,
29
- } from "@/components/ui/card";
30
- import { Label } from "@/components/ui/label";
31
25
 
32
26
  import changelog from "../../CHANGELOG.md?raw";
33
27
 
@@ -117,20 +111,18 @@ export default function SettingsRoute() {
117
111
  </p>
118
112
  </div>
119
113
 
120
- <Card id="language" className="scroll-mt-16">
121
- <CardHeader>
122
- <CardTitle className="text-base">
123
- {t("settings.languageTitle")}
124
- </CardTitle>
125
- <CardDescription>
126
- {t("settings.languageDescription")}
127
- </CardDescription>
128
- </CardHeader>
129
- <CardContent className="max-w-xs space-y-1.5">
130
- <Label>{t("settings.languageLabel")}</Label>
131
- <LanguagePicker label={t("settings.languageLabel")} />
132
- </CardContent>
133
- </Card>
114
+ <SettingsGroup>
115
+ <SettingsRow
116
+ id="language"
117
+ label={t("settings.languageTitle")}
118
+ description={t("settings.languageDescription")}
119
+ control={
120
+ <div className="w-56">
121
+ <LanguagePicker label={t("settings.languageLabel")} />
122
+ </div>
123
+ }
124
+ />
125
+ </SettingsGroup>
134
126
  </div>
135
127
  }
136
128
  whatsNew={
@@ -1,5 +1,9 @@
1
- import { defineConfig } from "vitest/config";
1
+ import baseConfig from "@agent-native/core/vitest-config";
2
+ import { defineConfig, mergeConfig } from "vitest/config";
2
3
 
3
- export default defineConfig({
4
- test: { include: ["**/*.test.ts"], environment: "node" },
5
- });
4
+ export default mergeConfig(
5
+ baseConfig,
6
+ defineConfig({
7
+ test: { include: ["**/*.test.ts"], environment: "node" },
8
+ }),
9
+ );
@@ -560,17 +560,28 @@ export const editorChromeBridgeScript: string = `"use strict";
560
560
  }
561
561
  renderRuntimeInteractionStatePreviews();
562
562
  }
563
- function runtimeHeadHtmlWithoutEditorChrome() {
564
- if (!document.head) return "";
565
- var clone = document.head.cloneNode(true);
566
- Array.prototype.slice.call(
567
- clone.querySelectorAll(
568
- "[data-agent-native-editor-chrome-style], [data-agent-native-editing-safety-style]"
569
- )
570
- ).forEach(function(node) {
563
+ var lastSourceHeadHtml = null;
564
+ function replaceSourceHeadNodes(previousSourceHtml, nextSourceHtml) {
565
+ if (!document.head) return;
566
+ var stale = document.createElement("head");
567
+ stale.innerHTML = previousSourceHtml || "";
568
+ var staleCounts = {};
569
+ Array.prototype.forEach.call(stale.children, function(node) {
570
+ var key = node.outerHTML;
571
+ staleCounts[key] = (staleCounts[key] || 0) + 1;
572
+ });
573
+ Array.prototype.slice.call(document.head.children).forEach(function(node) {
574
+ var key = node.outerHTML;
575
+ if (!staleCounts[key]) return;
576
+ staleCounts[key] -= 1;
571
577
  if (node.parentNode) node.parentNode.removeChild(node);
572
578
  });
573
- return clone.innerHTML;
579
+ var next = document.createElement("head");
580
+ next.innerHTML = nextSourceHtml || "";
581
+ var anchor = document.head.firstChild;
582
+ Array.prototype.slice.call(next.children).forEach(function(node) {
583
+ document.head.insertBefore(document.importNode(node, true), anchor);
584
+ });
574
585
  }
575
586
  function chromeScaleX() {
576
587
  return 1 / Math.max(0.05, editorChromeScaleX);
@@ -2536,7 +2547,10 @@ export const editorChromeBridgeScript: string = `"use strict";
2536
2547
  }
2537
2548
  var nextHeadHtml = nextDoc.head ? nextDoc.head.innerHTML : "";
2538
2549
  ensureEditorChromeStyle();
2539
- var currentHeadHtml = runtimeHeadHtmlWithoutEditorChrome();
2550
+ if (lastSourceHeadHtml === null) {
2551
+ lastSourceHeadHtml = nextHeadHtml;
2552
+ }
2553
+ var currentHeadHtml = lastSourceHeadHtml;
2540
2554
  if (nextHeadHtml === currentHeadHtml && activeCandidates.length > 0) {
2541
2555
  var currentMatch = null;
2542
2556
  var nextMatch = null;
@@ -2598,8 +2612,9 @@ export const editorChromeBridgeScript: string = `"use strict";
2598
2612
  }
2599
2613
  }
2600
2614
  if (currentHeadHtml !== nextHeadHtml) {
2601
- document.head.innerHTML = nextHeadHtml;
2615
+ replaceSourceHeadNodes(currentHeadHtml, nextHeadHtml);
2602
2616
  ensureEditorChromeStyle();
2617
+ lastSourceHeadHtml = nextHeadHtml;
2603
2618
  }
2604
2619
  Array.prototype.slice.call(document.body.attributes).forEach(function(attribute) {
2605
2620
  document.body.removeAttribute(attribute.name);
@@ -588,8 +588,15 @@ export default defineAction({
588
588
  const consoleErrors: string[] = [];
589
589
  const fontLoadFailures: string[] = [];
590
590
  page.on("console", (msg) => {
591
+ // Alpine reports failed expressions at warn level, and that warning
592
+ // is the only place the expression and element appear — its paired
593
+ // `pageerror` is a bare "Invalid or unexpected token".
591
594
  if (msg.type() === "error") {
592
595
  consoleErrors.push(msg.text().slice(0, 300));
596
+ return;
597
+ }
598
+ if (msg.type() === "warning" && /Alpine/.test(msg.text())) {
599
+ consoleErrors.push(msg.text().slice(0, 300));
593
600
  }
594
601
  });
595
602
  page.on("pageerror", (err) => {
@@ -106,6 +106,7 @@ import {
106
106
  forwardEmbeddedCanvasPanMessage,
107
107
  type EmbeddedCanvasPanSession,
108
108
  } from "./design-canvas/iframe-pan";
109
+ import { withLocalRuntimes } from "./design-canvas/local-runtime";
109
110
  import type { MotionTrackWire } from "./design-canvas/motion-types";
110
111
  import {
111
112
  PENDING_TEXT_EDIT_TIMEOUT_MS,
@@ -1018,7 +1019,14 @@ function runtimeDocumentNeedsReload(
1018
1019
  Array.from(html.matchAll(SCRIPT_ELEMENT_RE), (match) => match[0]).join(
1019
1020
  "\n",
1020
1021
  );
1021
- return scriptSignature(previousContent) !== scriptSignature(nextContent);
1022
+ // A changed <head> is replaced wholesale, which drops whatever the page's own
1023
+ // runtime injected there and cannot re-run the scripts that produced it.
1024
+ const headSignature = (html: string) =>
1025
+ /<head\b[^>]*>([\s\S]*?)<\/head\s*>/i.exec(html)?.[1] ?? "";
1026
+ return (
1027
+ scriptSignature(previousContent) !== scriptSignature(nextContent) ||
1028
+ headSignature(previousContent) !== headSignature(nextContent)
1029
+ );
1022
1030
  }
1023
1031
 
1024
1032
  /**
@@ -2261,7 +2269,7 @@ export function DesignCanvas({
2261
2269
  editorChromeBridge +
2262
2270
  imageDiagBridge;
2263
2271
  const frameContent = getEmbeddedFrameDocumentContent({
2264
- content: iframeRenderContent,
2272
+ content: withLocalRuntimes(iframeRenderContent),
2265
2273
  embeddedFrameBackground,
2266
2274
  transparentBackground,
2267
2275
  contentOffsetX: embeddedFrame?.contentOffsetX ?? 0,
@@ -2282,7 +2290,7 @@ export function DesignCanvas({
2282
2290
  embeddedFrame?.contentOffsetY ?? 0,
2283
2291
  ),
2284
2292
  ].join("");
2285
- frameDocument = `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">${frameStyle}</head><body>${iframeRenderContent}${bridgeToInject}</body></html>`;
2293
+ frameDocument = `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">${frameStyle}</head><body>${withLocalRuntimes(iframeRenderContent)}${bridgeToInject}</body></html>`;
2286
2294
  }
2287
2295
  // Overview frames report their own content height so the canvas can
2288
2296
  // content-fit them (Framer-style). Embedded (overview) frames only — a
@@ -88,6 +88,7 @@ import {
88
88
  type ContentSizeSample,
89
89
  } from "./design-canvas/content-size-report";
90
90
  import { appendHitTestResponder } from "./design-canvas/hit-test";
91
+ import { withLocalRuntimes } from "./design-canvas/local-runtime";
91
92
  import { DesignCanvas } from "./DesignCanvas";
92
93
  import { dndHostLog } from "./dnd-debug";
93
94
  import {
@@ -9499,7 +9500,9 @@ const Screen = memo(function Screen({
9499
9500
  // editable DesignCanvas is supplied) still report their own height and
9500
9501
  // content-fit. The editable DesignCanvas path injects its own reporter.
9501
9502
  return injectSessionReplayIframeBootstrap(
9502
- appendContentSizeReporter(appendHitTestResponder(screen.content)),
9503
+ appendContentSizeReporter(
9504
+ appendHitTestResponder(withLocalRuntimes(screen.content)),
9505
+ ),
9503
9506
  );
9504
9507
  // eslint-disable-next-line react-hooks/exhaustive-deps
9505
9508
  }, [screen.content]);
@@ -315,19 +315,49 @@ declare var __SELECTED_LAYER_DRAG_PRIORITY__: boolean;
315
315
  renderRuntimeInteractionStatePreviews();
316
316
  }
317
317
 
318
- function runtimeHeadHtmlWithoutEditorChrome(): string {
319
- if (!document.head) return "";
320
- var clone = document.head.cloneNode(true) as HTMLElement;
321
- Array.prototype.slice
322
- .call(
323
- clone.querySelectorAll(
324
- "[data-agent-native-editor-chrome-style], [data-agent-native-editing-safety-style]",
325
- ),
326
- )
327
- .forEach(function (node) {
328
- if (node.parentNode) node.parentNode.removeChild(node);
329
- });
330
- return clone.innerHTML;
318
+ /**
319
+ * The last source <head> this bridge applied. Compared against instead of the
320
+ * live head, which also carries nodes the page's own runtime injected —
321
+ * @tailwindcss/browser's compiled sheet above all. Against the live head the
322
+ * comparison always differs, the head gets wiped, the compiled CSS goes with
323
+ * it, and the re-inserted `<script src>` cannot rebuild it because innerHTML
324
+ * never executes scripts. The screen then renders unstyled for good.
325
+ */
326
+ var lastSourceHeadHtml: string | null = null;
327
+
328
+ /**
329
+ * Swaps only the nodes the previous source head contributed. Assigning
330
+ * `document.head.innerHTML` instead destroys whatever the page's own runtime
331
+ * injected — @tailwindcss/browser's compiled sheet above all — and the
332
+ * `<script src>` re-inserted in its place can never rebuild it, because
333
+ * innerHTML does not execute scripts.
334
+ */
335
+ function replaceSourceHeadNodes(
336
+ previousSourceHtml: string | null,
337
+ nextSourceHtml: string,
338
+ ): void {
339
+ if (!document.head) return;
340
+ var stale = document.createElement("head");
341
+ stale.innerHTML = previousSourceHtml || "";
342
+ var staleCounts: Record<string, number> = {};
343
+ Array.prototype.forEach.call(stale.children, function (node: Element) {
344
+ var key = node.outerHTML;
345
+ staleCounts[key] = (staleCounts[key] || 0) + 1;
346
+ });
347
+ Array.prototype.slice.call(document.head.children).forEach(function (
348
+ node: Element,
349
+ ) {
350
+ var key = node.outerHTML;
351
+ if (!staleCounts[key]) return;
352
+ staleCounts[key] -= 1;
353
+ if (node.parentNode) node.parentNode.removeChild(node);
354
+ });
355
+ var next = document.createElement("head");
356
+ next.innerHTML = nextSourceHtml || "";
357
+ var anchor = document.head.firstChild;
358
+ Array.prototype.slice.call(next.children).forEach(function (node: Element) {
359
+ document.head.insertBefore(document.importNode(node, true), anchor);
360
+ });
331
361
  }
332
362
 
333
363
  function chromeScaleX(): number {
@@ -3123,8 +3153,8 @@ declare var __SELECTED_LAYER_DRAG_PRIORITY__: boolean;
3123
3153
  // Both layer states are painted here, from the one `layer-states` message,
3124
3154
  // so every call site that re-runs after a runtime document swap restores
3125
3155
  // hide AND lock together. Locked paints an attribute only; the hairline
3126
- // treatment lives in the editor chrome stylesheet so it is stripped from
3127
- // runtimeHeadHtmlWithoutEditorChrome and never reaches source or export.
3156
+ // treatment lives in the editor chrome stylesheet, which is never part of
3157
+ // the source head and so never reaches source or export.
3128
3158
  function applyLayerStateSelectors(): void {
3129
3159
  document
3130
3160
  .querySelectorAll("[data-agent-native-runtime-hidden]")
@@ -3248,7 +3278,13 @@ declare var __SELECTED_LAYER_DRAG_PRIORITY__: boolean;
3248
3278
 
3249
3279
  var nextHeadHtml = nextDoc.head ? nextDoc.head.innerHTML : "";
3250
3280
  ensureEditorChromeStyle();
3251
- var currentHeadHtml = runtimeHeadHtmlWithoutEditorChrome();
3281
+ if (lastSourceHeadHtml === null) {
3282
+ // First patch after a srcdoc build, so the document already carries this
3283
+ // source head. Forced replacements adopt too: treating the live head as
3284
+ // the baseline is what wipes the runtime's own nodes.
3285
+ lastSourceHeadHtml = nextHeadHtml;
3286
+ }
3287
+ var currentHeadHtml = lastSourceHeadHtml;
3252
3288
  if (nextHeadHtml === currentHeadHtml && activeCandidates.length > 0) {
3253
3289
  var currentMatch = null;
3254
3290
  var nextMatch = null;
@@ -3326,8 +3362,9 @@ declare var __SELECTED_LAYER_DRAG_PRIORITY__: boolean;
3326
3362
  }
3327
3363
  }
3328
3364
  if (currentHeadHtml !== nextHeadHtml) {
3329
- document.head.innerHTML = nextHeadHtml;
3365
+ replaceSourceHeadNodes(currentHeadHtml, nextHeadHtml);
3330
3366
  ensureEditorChromeStyle();
3367
+ lastSourceHeadHtml = nextHeadHtml;
3331
3368
  }
3332
3369
  Array.prototype.slice.call(document.body.attributes).forEach(function (
3333
3370
  attribute: Attr,