@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
@@ -11,17 +11,25 @@
11
11
  * Route: GET /api/uploads/:recordingId/resume
12
12
  */
13
13
 
14
+ import {
15
+ compareAndSetAppState,
16
+ readAppState,
17
+ writeAppState,
18
+ } from "@agent-native/core/application-state";
19
+ import { isFeatureFlagEnabled } from "@agent-native/core/feature-flags";
14
20
  import { runWithRequestContext } from "@agent-native/core/server";
15
- import { and, eq } from "drizzle-orm";
21
+ import { and, eq, isNull } from "drizzle-orm";
16
22
  import {
17
23
  createError,
18
24
  defineEventHandler,
19
25
  getRouterParam,
26
+ getQuery,
20
27
  setResponseHeader,
21
28
  setResponseStatus,
22
29
  type H3Event,
23
30
  } from "h3";
24
31
 
32
+ import { UPLOAD_RETRY_RESUME_FLAG } from "../../../../../shared/feature-flags.js";
25
33
  import { getDb, schema } from "../../../../db/index.js";
26
34
  import {
27
35
  listRecordingChunkKeys,
@@ -33,7 +41,11 @@ import {
33
41
  ownerEmailMatches,
34
42
  } from "../../../../lib/recordings.js";
35
43
  import { getResumableSession } from "../../../../lib/resumable-session.js";
36
- import { renewUploadLease } from "../../../../lib/upload-lease.js";
44
+ import {
45
+ isRetryableUploadInterruption,
46
+ RETRYABLE_UPLOAD_INTERRUPTION_REASON,
47
+ } from "../../../../lib/upload-interruption.js";
48
+ import { uploadLeaseExpiry } from "../../../../lib/upload-lease.js";
37
49
 
38
50
  export default defineEventHandler(async (event: H3Event) => {
39
51
  setResponseHeader(event, "Cache-Control", "private, max-age=0, no-store");
@@ -41,6 +53,21 @@ export default defineEventHandler(async (event: H3Event) => {
41
53
  if (!recordingId) {
42
54
  throw createError({ statusCode: 400, message: "Missing recordingId" });
43
55
  }
56
+ const requestedAttemptIdValue = getQuery(event).attemptId;
57
+ const requestedAttemptId = Array.isArray(requestedAttemptIdValue)
58
+ ? requestedAttemptIdValue[0]
59
+ : requestedAttemptIdValue;
60
+ if (
61
+ typeof requestedAttemptId !== "string" ||
62
+ requestedAttemptId.length < 16 ||
63
+ requestedAttemptId.length > 128 ||
64
+ !/^[A-Za-z0-9_-]+$/.test(requestedAttemptId)
65
+ ) {
66
+ throw createError({
67
+ statusCode: 400,
68
+ message: "A valid upload retry attemptId is required",
69
+ });
70
+ }
44
71
 
45
72
  let ownerEmail: string;
46
73
  let orgId: string | undefined;
@@ -52,6 +79,21 @@ export default defineEventHandler(async (event: H3Event) => {
52
79
  throw createError({ statusCode: 401, message: "Unauthorized" });
53
80
  }
54
81
 
82
+ const recoveryEnabled = await isFeatureFlagEnabled(UPLOAD_RETRY_RESUME_FLAG, {
83
+ userEmail: ownerEmail,
84
+ userKey: ownerEmail,
85
+ orgId,
86
+ });
87
+ if (!recoveryEnabled) {
88
+ return {
89
+ recoveryEnabled: false,
90
+ resumable: false,
91
+ recordingId,
92
+ status: null,
93
+ reason: "feature_disabled",
94
+ };
95
+ }
96
+
55
97
  return runWithRequestContext({ userEmail: ownerEmail, orgId }, async () => {
56
98
  const [recording] = await getDb()
57
99
  .select({
@@ -59,6 +101,9 @@ export default defineEventHandler(async (event: H3Event) => {
59
101
  status: schema.recordings.status,
60
102
  failureReason: schema.recordings.failureReason,
61
103
  videoUrl: schema.recordings.videoUrl,
104
+ uploadProgress: schema.recordings.uploadProgress,
105
+ uploadAttemptId: schema.recordings.uploadAttemptId,
106
+ uploadGenerationId: schema.recordings.uploadGenerationId,
62
107
  })
63
108
  .from(schema.recordings)
64
109
  .where(
@@ -73,31 +118,160 @@ export default defineEventHandler(async (event: H3Event) => {
73
118
  return { error: "Recording not found" };
74
119
  }
75
120
 
76
- const lease = await renewUploadLease(recordingId);
77
- if (!lease.held) {
121
+ // Legacy rows keep their null generation and unscoped scratch. A reset
122
+ // upgrades them by installing a fresh generation before it deletes data.
123
+ const existingGenerationId = recording.uploadGenerationId ?? null;
124
+ const generationId = existingGenerationId;
125
+ const session = generationId
126
+ ? await getResumableSession(recordingId, generationId)
127
+ : await getResumableSession(recordingId);
128
+ const retryableFailure =
129
+ recording.status === "failed" &&
130
+ isRetryableUploadInterruption(recording.failureReason);
131
+ const existingAttemptId = recording.uploadAttemptId ?? null;
132
+ if (
133
+ recording.status === "uploading" &&
134
+ existingAttemptId !== null &&
135
+ existingAttemptId !== requestedAttemptId
136
+ ) {
137
+ setResponseStatus(event, 409);
138
+ return {
139
+ resumable: false,
140
+ recoveryEnabled: true,
141
+ recordingId,
142
+ status: "uploading",
143
+ reason: "retry_already_active",
144
+ };
145
+ }
146
+ if (recording.status !== "uploading" && !retryableFailure) {
147
+ return {
148
+ resumable: false,
149
+ recoveryEnabled: true,
150
+ recordingId,
151
+ status: recording.status,
152
+ failureReason: recording.failureReason,
153
+ videoUrl: recording.videoUrl,
154
+ };
155
+ }
156
+
157
+ const uploadStateKey = `recording-upload-${recordingId}`;
158
+ const uploadStateRaw = await readAppState(uploadStateKey);
159
+ const uploadState = uploadStateRaw ?? {};
160
+ const attemptId = requestedAttemptId;
161
+ const now = new Date().toISOString();
162
+ const claimed = await getDb()
163
+ .update(schema.recordings)
164
+ .set({
165
+ status: "uploading",
166
+ failureReason: null,
167
+ uploadAttemptId: attemptId,
168
+ ...(generationId ? { uploadGenerationId: generationId } : {}),
169
+ uploadLeaseExpiresAt: uploadLeaseExpiry(),
170
+ updatedAt: now,
171
+ })
172
+ .where(
173
+ and(
174
+ eq(schema.recordings.id, recordingId),
175
+ ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
176
+ retryableFailure
177
+ ? eq(schema.recordings.status, "failed")
178
+ : eq(schema.recordings.status, "uploading"),
179
+ retryableFailure
180
+ ? eq(
181
+ schema.recordings.failureReason,
182
+ RETRYABLE_UPLOAD_INTERRUPTION_REASON,
183
+ )
184
+ : undefined,
185
+ existingAttemptId === null
186
+ ? isNull(schema.recordings.uploadAttemptId)
187
+ : eq(schema.recordings.uploadAttemptId, existingAttemptId),
188
+ existingGenerationId === null
189
+ ? isNull(schema.recordings.uploadGenerationId)
190
+ : eq(schema.recordings.uploadGenerationId, existingGenerationId),
191
+ ),
192
+ )
193
+ .returning({ id: schema.recordings.id });
194
+
195
+ if (claimed.length !== 1) {
196
+ setResponseStatus(event, 409);
78
197
  return {
79
198
  resumable: false,
199
+ recoveryEnabled: true,
80
200
  recordingId,
81
- status: lease.status,
82
- failureReason: lease.failureReason,
83
- videoUrl: lease.videoUrl,
201
+ status: "uploading",
202
+ reason: "retry_already_active",
84
203
  };
85
204
  }
86
205
 
87
- const session = await getResumableSession(recordingId).catch(() => null);
206
+ const uploadStateUpdated = await compareAndSetAppState(
207
+ uploadStateKey,
208
+ uploadStateRaw,
209
+ {
210
+ ...uploadState,
211
+ recordingId,
212
+ status: "uploading",
213
+ failureReason: null,
214
+ retryableInterruption: false,
215
+ progress: recording.uploadProgress,
216
+ uploadAttemptId: attemptId,
217
+ uploadGenerationId: generationId,
218
+ ...(session ? { bytesReceived: session.bytesUploaded } : {}),
219
+ updatedAt: now,
220
+ },
221
+ );
222
+ if (!uploadStateUpdated) {
223
+ const [current] = await getDb()
224
+ .select({
225
+ status: schema.recordings.status,
226
+ uploadAttemptId: schema.recordings.uploadAttemptId,
227
+ uploadGenerationId: schema.recordings.uploadGenerationId,
228
+ })
229
+ .from(schema.recordings)
230
+ .where(
231
+ and(
232
+ eq(schema.recordings.id, recordingId),
233
+ ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
234
+ ),
235
+ );
236
+ if (
237
+ current?.status !== "uploading" ||
238
+ (current.uploadAttemptId ?? null) !== attemptId ||
239
+ (current.uploadGenerationId ?? null) !== generationId
240
+ ) {
241
+ setResponseStatus(event, 409);
242
+ return {
243
+ resumable: false,
244
+ recoveryEnabled: true,
245
+ recordingId,
246
+ status: current?.status ?? null,
247
+ reason: "upload_state_changed",
248
+ };
249
+ }
250
+ console.info(
251
+ `[upload-resume] upload state advanced under the same claim; preserving newer progress for ${recordingId}`,
252
+ );
253
+ }
254
+ await writeAppState("refresh-signal", { ts: Date.now() });
255
+
88
256
  if (session) {
89
257
  return {
90
258
  resumable: true,
259
+ recoveryEnabled: true,
91
260
  recordingId,
92
- status: recording.status,
261
+ status: "uploading",
93
262
  uploadMode: "streaming" as const,
263
+ attemptId,
264
+ ...(generationId ? { uploadGenerationId: generationId } : {}),
94
265
  bytesReceived: session.bytesUploaded,
95
266
  nextChunkIndex: (session.lastCommittedIndex ?? -1) + 1,
96
267
  };
97
268
  }
98
269
 
99
270
  const stored = new Set(
100
- (await listRecordingChunkKeys(ownerEmail, recordingId))
271
+ (generationId
272
+ ? await listRecordingChunkKeys(ownerEmail, recordingId, generationId)
273
+ : await listRecordingChunkKeys(ownerEmail, recordingId)
274
+ )
101
275
  .map(recordingChunkIndexFromKey)
102
276
  .filter((index): index is number => index !== null),
103
277
  );
@@ -108,10 +282,15 @@ export default defineEventHandler(async (event: H3Event) => {
108
282
 
109
283
  return {
110
284
  resumable: true,
285
+ recoveryEnabled: true,
111
286
  recordingId,
112
- status: recording.status,
287
+ status: "uploading",
113
288
  uploadMode: "buffered" as const,
114
- bytesReceived: await sumRecordingChunkBytes(ownerEmail, recordingId),
289
+ attemptId,
290
+ ...(generationId ? { uploadGenerationId: generationId } : {}),
291
+ bytesReceived: generationId
292
+ ? await sumRecordingChunkBytes(ownerEmail, recordingId, generationId)
293
+ : await sumRecordingChunkBytes(ownerEmail, recordingId),
115
294
  nextChunkIndex,
116
295
  };
117
296
  });
@@ -27,10 +27,16 @@ export type ClipsAiPrefs = {
27
27
 
28
28
  export type ClipsUserPrefs = ClipsAiPrefs & {
29
29
  defaultPlaybackSpeed?: string;
30
+ /** Activity emails (comments, replies, reactions) only — never share invites. */
30
31
  emailNotifications?: boolean;
31
32
  transcriptCleanupEnabled?: boolean;
33
+ /** Overrides the organization default visibility for new recordings. */
34
+ defaultRecordingVisibility?: ClipsDefaultVisibility;
32
35
  };
33
36
 
37
+ /** Visibility applied to new recordings unless the creator picks another. */
38
+ export type ClipsDefaultVisibility = "private" | "org" | "public";
39
+
34
40
  export function isIncludeFullVideoInAiEnabled(
35
41
  prefs: ClipsAiPrefs | Record<string, unknown> | null | undefined,
36
42
  ): boolean {
@@ -28,7 +28,19 @@ export const CUSTOM_SCK_LIVE_UPLOAD_FLAG = defineFeatureFlag({
28
28
  "Upload recording chunks while capture is still in progress. Requires the custom ScreenCaptureKit pipeline.",
29
29
  });
30
30
 
31
+ /**
32
+ * Desktop app and hosted upload routes: preserve interrupted resumable
33
+ * sessions and continue saved retries from the provider-confirmed offset.
34
+ */
35
+ export const UPLOAD_RETRY_RESUME_FLAG = defineFeatureFlag({
36
+ key: "uploadRetryResume",
37
+ displayName: "Resumable upload retry",
38
+ description:
39
+ "Resume interrupted desktop uploads from their last confirmed byte instead of replaying the full local backup.",
40
+ });
41
+
31
42
  export const CLIPS_FEATURE_FLAGS = defineFeatureFlags([
32
43
  USE_CUSTOM_SCK_PIPELINE_FLAG,
33
44
  CUSTOM_SCK_LIVE_UPLOAD_FLAG,
45
+ UPLOAD_RETRY_RESUME_FLAG,
34
46
  ]);
@@ -76,6 +76,7 @@ export type ChunkUploadParams = {
76
76
  height?: number | null;
77
77
  hasAudio?: boolean;
78
78
  hasCamera?: boolean;
79
+ uploadGenerationId?: string;
79
80
  };
80
81
 
81
82
  export function normalizeChunkUploadNumber(value: unknown): number | undefined {
@@ -115,6 +116,9 @@ export function chunkUploadQuery(params: ChunkUploadParams): string {
115
116
  if (params.hasCamera !== undefined) {
116
117
  q.set("hasCamera", params.hasCamera ? "1" : "0");
117
118
  }
119
+ if (params.uploadGenerationId) {
120
+ q.set("uploadGenerationId", params.uploadGenerationId);
121
+ }
118
122
  return q.toString();
119
123
  }
120
124
 
@@ -1,23 +1,27 @@
1
1
  import path from "node:path";
2
2
 
3
- import { defineConfig } from "vitest/config";
3
+ import baseConfig from "@agent-native/core/vitest-config";
4
+ import { defineConfig, mergeConfig } from "vitest/config";
4
5
 
5
- export default defineConfig({
6
- resolve: {
7
- alias: {
8
- "@": path.resolve(__dirname, "./app"),
9
- "@shared": path.resolve(__dirname, "./shared"),
6
+ export default mergeConfig(
7
+ baseConfig,
8
+ defineConfig({
9
+ resolve: {
10
+ alias: {
11
+ "@": path.resolve(__dirname, "./app"),
12
+ "@shared": path.resolve(__dirname, "./shared"),
13
+ },
10
14
  },
11
- },
12
- test: {
13
- include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
14
- exclude: [
15
- "**/node_modules/**",
16
- "**/.git/**",
17
- "**/dist/**",
18
- "**/.output/**",
19
- "**/.react-router/**",
20
- "**/e2e/**",
21
- ],
22
- },
23
- });
15
+ test: {
16
+ include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
17
+ exclude: [
18
+ "**/node_modules/**",
19
+ "**/.git/**",
20
+ "**/dist/**",
21
+ "**/.output/**",
22
+ "**/.react-router/**",
23
+ "**/e2e/**",
24
+ ],
25
+ },
26
+ }),
27
+ );
@@ -132,7 +132,7 @@ filters for that column, hide property columns in the current view without
132
132
  changing other views, and resize column widths. Column headers show compact
133
133
  sort/filter indicators when that column has active view constraints. Table
134
134
  rows can be selected with row checkboxes, and the table shows a compact
135
- selected-row bar with clear, duplicate, confirmed delete, and bulk property
135
+ selected-row bar with clear, duplicate, confirmed membership removal, and bulk property
136
136
  set actions for editable non-computed fields. Empty table cells stay
137
137
  visually blank while remaining clickable for editing, and checkbox table
138
138
  cells render as compact checkbox glyphs instead of "Checked"/"Unchecked"
@@ -228,16 +228,18 @@ property definition.
228
228
  Use `create-content-database`, `create-inline-content-database`,
229
229
  `get-content-database`, `list-trashed-content-databases`,
230
230
  `restore-content-database`, `add-database-item`, `duplicate-database-item`,
231
- `duplicate-database-items`, `delete-database-items`, `move-database-item`,
231
+ `duplicate-database-items`, `remove-database-items`, `move-database-item`,
232
232
  `update-content-database-view`, `list-document-properties`,
233
233
  `configure-document-property`, `set-document-property`,
234
234
  `duplicate-document-property`, and `delete-document-property`; do not edit
235
235
  property rows or view config via raw SQL when an action can do it.
236
236
 
237
237
  When targeting more than one database row, call `duplicate-database-items` or
238
- `delete-database-items` once with a native JSON array of `itemIds` or
238
+ `remove-database-items` once with a native JSON array of `itemIds` or
239
239
  `documentIds`. Do not loop `duplicate-database-item` or `delete-document` for
240
- multi-row duplicate/delete requests.
240
+ multi-row duplicate or membership-removal requests. Removing a row from a
241
+ database preserves its Page, descendants, other database memberships, and
242
+ unrelated property values.
241
243
 
242
244
  Database views follow Notion-style tab labels. When creating or duplicating
243
245
  views in `viewConfig`, use unique default names (`Table 2`, `SEO copy 2`,
@@ -0,0 +1,25 @@
1
+ import { inArray, sql } from "drizzle-orm";
2
+
3
+ import { schema } from "../server/db/index.js";
4
+ import { chunks } from "./_batch-utils.js";
5
+
6
+ export async function lockDatabaseMemberships(db: any, itemIds: string[]) {
7
+ const uniqueItemIds = [...new Set(itemIds)].sort();
8
+ if (uniqueItemIds.length === 0) return;
9
+ const lockedIds = new Set<string>();
10
+ for (const itemIdChunk of chunks(uniqueItemIds, 90)) {
11
+ const lockedRows = await db
12
+ .update(schema.contentDatabaseItems)
13
+ .set({
14
+ updatedAt: sql`${schema.contentDatabaseItems.updatedAt}`,
15
+ })
16
+ .where(inArray(schema.contentDatabaseItems.id, itemIdChunk))
17
+ .returning({ id: schema.contentDatabaseItems.id });
18
+ for (const row of lockedRows) lockedIds.add(row.id);
19
+ }
20
+ if (lockedIds.size !== uniqueItemIds.length) {
21
+ throw new Error(
22
+ "Database memberships changed before the operation completed.",
23
+ );
24
+ }
25
+ }
@@ -79,6 +79,7 @@ function positionCaseSql(
79
79
 
80
80
  export async function resolveDatabaseRowsForBatch(
81
81
  input: DatabaseRowBatchInput,
82
+ options: { includeTrashed?: boolean } = {},
82
83
  ): Promise<{
83
84
  database: typeof schema.contentDatabases.$inferSelect;
84
85
  rows: DatabaseRowBatchRow[];
@@ -151,7 +152,7 @@ export async function resolveDatabaseRowsForBatch(
151
152
  eq(schema.contentDatabaseItems.databaseId, database.id),
152
153
  rowPredicates.length === 1 ? rowPredicates[0] : or(...rowPredicates),
153
154
  isNull(schema.contentDatabases.deletedAt),
154
- isNull(schema.documents.trashedAt),
155
+ options.includeTrashed ? undefined : isNull(schema.documents.trashedAt),
155
156
  ),
156
157
  )
157
158
  .orderBy(asc(schema.contentDatabaseItems.position));
@@ -177,7 +178,10 @@ export async function resolveDatabaseRowsForBatch(
177
178
  throw new Error("Duplicate database row references are not allowed.");
178
179
  }
179
180
 
180
- return { database, rows: requestedRows };
181
+ return {
182
+ database,
183
+ rows: requestedRows,
184
+ };
181
185
  }
182
186
 
183
187
  export async function renumberDatabaseRows(