@agent-native/core 0.134.1 → 0.135.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/corpus/README.md +3 -3
  2. package/corpus/core/CHANGELOG.md +113 -0
  3. package/corpus/core/package.json +3 -2
  4. package/corpus/core/src/automations/service.ts +41 -4
  5. package/corpus/core/src/cli/mcp-config-writers.ts +27 -21
  6. package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +187 -85
  7. package/corpus/core/src/client/agent-page/AutomationDetailsDialog.tsx +208 -0
  8. package/corpus/core/src/client/agent-page/AutomationScheduleDialog.tsx +180 -0
  9. package/corpus/core/src/client/agent-page/TimezoneSelect.tsx +241 -0
  10. package/corpus/core/src/client/agent-page/use-jobs.ts +50 -10
  11. package/corpus/core/src/client/org/OrgSwitcher.tsx +26 -0
  12. package/corpus/core/src/client/settings/AccountSettingsCard.tsx +35 -31
  13. package/corpus/core/src/client/settings/SchedulingTimezoneField.tsx +71 -0
  14. package/corpus/core/src/client/settings/SettingsRow.tsx +113 -0
  15. package/corpus/core/src/client/settings/agent-settings-search.ts +2 -1
  16. package/corpus/core/src/client/settings/index.ts +6 -0
  17. package/corpus/core/src/integrations/identity.ts +2 -12
  18. package/corpus/core/src/jobs/actions/list-automation-runs.ts +33 -0
  19. package/corpus/core/src/jobs/actions/list-recurring-jobs.ts +27 -6
  20. package/corpus/core/src/jobs/actions/manage-recurring-job.ts +41 -9
  21. package/corpus/core/src/jobs/background-automation-runner.ts +88 -0
  22. package/corpus/core/src/jobs/cron.ts +52 -6
  23. package/corpus/core/src/jobs/frontmatter.ts +20 -0
  24. package/corpus/core/src/jobs/run-history.ts +242 -0
  25. package/corpus/core/src/jobs/scheduler.ts +73 -18
  26. package/corpus/core/src/jobs/tools.ts +54 -6
  27. package/corpus/core/src/localization/actions/get-localization-preference.ts +2 -2
  28. package/corpus/core/src/localization/actions/set-localization-preference.ts +49 -11
  29. package/corpus/core/src/localization/default-messages.ts +27 -0
  30. package/corpus/core/src/localization/shared.ts +39 -6
  31. package/corpus/core/src/localization/user-timezone.ts +36 -0
  32. package/corpus/core/src/org/app-roles-handlers.ts +1 -9
  33. package/corpus/core/src/org/index.ts +2 -0
  34. package/corpus/core/src/org/membership.ts +18 -0
  35. package/corpus/core/src/review/actions/create-review-comment.ts +4 -1
  36. package/corpus/core/src/review/actions/reply-review-comment.ts +4 -1
  37. package/corpus/core/src/review/index.ts +5 -0
  38. package/corpus/core/src/review/notifications.ts +163 -0
  39. package/corpus/core/src/review/types.ts +7 -0
  40. package/corpus/core/src/server/action-discovery.ts +4 -0
  41. package/corpus/core/src/server/activity-notifications.ts +174 -0
  42. package/corpus/core/src/server/app-name.ts +31 -0
  43. package/corpus/core/src/server/better-auth-instance.ts +4 -4
  44. package/corpus/core/src/server/email-templates.ts +70 -14
  45. package/corpus/core/src/server/email.ts +66 -3
  46. package/corpus/core/src/server/index.ts +10 -0
  47. package/corpus/core/src/sharing/access.ts +44 -2
  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-31-editor-timeline-now-shows-video-frames-behind-the-waveform-g.md +6 -0
  109. package/corpus/templates/clips/changelog/2026-07-31-email-notifications-now-go-out-when-someone-comments-on-or-r.md +6 -0
  110. package/corpus/templates/clips/changelog/2026-07-31-you-can-now-set-a-default-visibility-for-new-recordings-in-s.md +6 -0
  111. package/corpus/templates/clips/changelog/2026-08-01-email-notifications-for-comments-and-reactions-now-actually-.md +6 -0
  112. package/corpus/templates/clips/changelog/2026-08-03-the-desktop-app-now-opens-directly-beneath-its-tray-icon-on-.md +6 -0
  113. package/corpus/templates/clips/chrome-extension/package.json +1 -0
  114. package/corpus/templates/clips/chrome-extension/vitest.config.ts +9 -0
  115. package/corpus/templates/clips/desktop/package.json +1 -0
  116. package/corpus/templates/clips/desktop/src/app.tsx +17 -1
  117. package/corpus/templates/clips/desktop/src/lib/recorder.ts +331 -36
  118. package/corpus/templates/clips/desktop/src/lib/upload-recovery.ts +129 -0
  119. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +815 -15
  120. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +61 -11
  121. package/corpus/templates/clips/desktop/vitest.config.ts +9 -0
  122. package/corpus/templates/clips/server/db/schema.ts +17 -0
  123. package/corpus/templates/clips/server/jobs/media-verification.ts +4 -0
  124. package/corpus/templates/clips/server/lib/activity-notifications.ts +185 -0
  125. package/corpus/templates/clips/server/lib/recording-media-cleanup.ts +2 -0
  126. package/corpus/templates/clips/server/lib/recording-upload-state.ts +46 -9
  127. package/corpus/templates/clips/server/lib/recordings.ts +24 -0
  128. package/corpus/templates/clips/server/lib/resumable-session.ts +10 -4
  129. package/corpus/templates/clips/server/lib/transactional-email-templates.ts +109 -0
  130. package/corpus/templates/clips/server/lib/upload-interruption.ts +8 -0
  131. package/corpus/templates/clips/server/lib/upload-lease.ts +50 -4
  132. package/corpus/templates/clips/server/lib/video-filmstrip-sprite.ts +207 -0
  133. package/corpus/templates/clips/server/lib/video-remux.ts +13 -4
  134. package/corpus/templates/clips/server/plugins/db.ts +16 -0
  135. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +4 -0
  136. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +123 -36
  137. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +159 -29
  138. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +197 -0
  139. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +193 -39
  140. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/resume.get.ts +191 -12
  141. package/corpus/templates/clips/shared/clips-ai-prefs.ts +6 -0
  142. package/corpus/templates/clips/shared/feature-flags.ts +12 -0
  143. package/corpus/templates/clips/shared/recording-core.ts +4 -0
  144. package/corpus/templates/clips/vitest.config.ts +23 -19
  145. package/corpus/templates/content/actions/_database-utils.ts +113 -4
  146. package/corpus/templates/content/actions/add-comment.ts +15 -1
  147. package/corpus/templates/content/actions/get-document.ts +84 -3
  148. package/corpus/templates/content/actions/list-documents.ts +1 -0
  149. package/corpus/templates/content/app/components/editor/BuilderBodySyncingNotice.tsx +9 -2
  150. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +34 -15
  151. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +55 -13
  152. package/corpus/templates/content/app/components/editor/body-hydration.ts +12 -6
  153. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +2 -3
  154. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +5 -12
  155. package/corpus/templates/content/app/components/ui/switch.tsx +1 -0
  156. package/corpus/templates/content/app/hooks/use-content-database.ts +16 -27
  157. package/corpus/templates/content/app/hooks/use-content-prefs.ts +55 -0
  158. package/corpus/templates/content/app/hooks/use-create-page.ts +3 -6
  159. package/corpus/templates/content/app/hooks/use-document-properties.ts +9 -16
  160. package/corpus/templates/content/app/hooks/use-document-versions.ts +3 -3
  161. package/corpus/templates/content/app/hooks/use-documents.ts +85 -29
  162. package/corpus/templates/content/app/hooks/use-notion.ts +15 -13
  163. package/corpus/templates/content/app/i18n-data.ts +72 -1
  164. package/corpus/templates/content/app/lib/document-query.ts +36 -0
  165. package/corpus/templates/content/app/routes/_app.settings.tsx +47 -18
  166. package/corpus/templates/content/changelog/2026-07-30-breadcrumb-menus-now-hide-internal-system-pages.md +6 -0
  167. package/corpus/templates/content/changelog/2026-08-01-get-an-email-when-someone-comments-on-replies-in-or-mentions.md +6 -0
  168. package/corpus/templates/content/changelog/2026-08-02-pages-opened-from-a-database-now-keep-that-database-s-fields.md +6 -0
  169. package/corpus/templates/content/server/lib/comment-notifications.ts +146 -0
  170. package/corpus/templates/content/server/lib/document-context.ts +11 -6
  171. package/corpus/templates/content/server/routes/_agent-native/content/user-prefs.get.ts +17 -0
  172. package/corpus/templates/content/server/routes/_agent-native/content/user-prefs.put.ts +36 -0
  173. package/corpus/templates/content/shared/api.ts +8 -0
  174. package/corpus/templates/content/shared/content-user-prefs.ts +11 -0
  175. package/corpus/templates/content/vitest.config.ts +20 -16
  176. package/corpus/templates/crm/app/routes/settings.tsx +14 -22
  177. package/corpus/templates/crm/vitest.config.ts +8 -4
  178. package/corpus/templates/design/app/routes/settings.tsx +14 -22
  179. package/corpus/templates/design/changelog/2026-08-01-review-comments-replies-and-mentions-now-send-an-email-to-th.md +6 -0
  180. package/corpus/templates/design/vitest.config.ts +18 -12
  181. package/corpus/templates/dispatch/app/routes/settings.tsx +26 -40
  182. package/corpus/templates/dispatch/vitest.config.ts +11 -7
  183. package/corpus/templates/factory/app/routes/settings.tsx +14 -22
  184. package/corpus/templates/factory/vitest.config.ts +9 -0
  185. package/corpus/templates/forms/app/routes/_app.settings.tsx +14 -22
  186. package/corpus/templates/forms/vitest.config.ts +27 -23
  187. package/corpus/templates/macros/app/routes/settings.tsx +14 -22
  188. package/corpus/templates/macros/vitest.config.ts +16 -12
  189. package/corpus/templates/mail/app/pages/SettingsPage.tsx +14 -16
  190. package/corpus/templates/mail/vitest.config.ts +16 -12
  191. package/corpus/templates/plan/app/routes/settings.tsx +30 -44
  192. package/corpus/templates/plan/vitest.config.ts +24 -20
  193. package/corpus/templates/slides/actions/add-slide-comment.ts +12 -1
  194. package/corpus/templates/slides/app/components/ui/switch.tsx +1 -0
  195. package/corpus/templates/slides/app/hooks/use-slides-prefs.ts +55 -0
  196. package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
  197. package/corpus/templates/slides/app/routes/settings.tsx +45 -22
  198. package/corpus/templates/slides/changelog/2026-08-01-get-an-email-when-someone-comments-on-or-replies-in-your-dec.md +6 -0
  199. package/corpus/templates/slides/server/lib/comment-notifications.ts +182 -0
  200. package/corpus/templates/slides/server/routes/_agent-native/slides/user-prefs.get.ts +16 -0
  201. package/corpus/templates/slides/server/routes/_agent-native/slides/user-prefs.put.ts +36 -0
  202. package/corpus/templates/slides/shared/slides-user-prefs.ts +11 -0
  203. package/corpus/templates/slides/vitest.config.ts +17 -13
  204. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +2 -0
  205. package/corpus/templates/tasks/app/routes/settings.tsx +14 -22
  206. package/corpus/templates/tasks/vitest.config.ts +17 -13
  207. package/corpus/toolkit/CHANGELOG.md +9 -0
  208. package/corpus/toolkit/package.json +1 -1
  209. package/corpus/toolkit/vitest.config.ts +3 -0
  210. package/dist/automations/service.d.ts +2 -0
  211. package/dist/automations/service.d.ts.map +1 -1
  212. package/dist/automations/service.js +29 -4
  213. package/dist/automations/service.js.map +1 -1
  214. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  215. package/dist/cli/mcp-config-writers.js +24 -23
  216. package/dist/cli/mcp-config-writers.js.map +1 -1
  217. package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
  218. package/dist/client/agent-page/AgentJobsTab.js +86 -29
  219. package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
  220. package/dist/client/agent-page/AutomationDetailsDialog.d.ts +21 -0
  221. package/dist/client/agent-page/AutomationDetailsDialog.d.ts.map +1 -0
  222. package/dist/client/agent-page/AutomationDetailsDialog.js +33 -0
  223. package/dist/client/agent-page/AutomationDetailsDialog.js.map +1 -0
  224. package/dist/client/agent-page/AutomationScheduleDialog.d.ts +15 -0
  225. package/dist/client/agent-page/AutomationScheduleDialog.d.ts.map +1 -0
  226. package/dist/client/agent-page/AutomationScheduleDialog.js +46 -0
  227. package/dist/client/agent-page/AutomationScheduleDialog.js.map +1 -0
  228. package/dist/client/agent-page/TimezoneSelect.d.ts +17 -0
  229. package/dist/client/agent-page/TimezoneSelect.d.ts.map +1 -0
  230. package/dist/client/agent-page/TimezoneSelect.js +107 -0
  231. package/dist/client/agent-page/TimezoneSelect.js.map +1 -0
  232. package/dist/client/agent-page/use-jobs.d.ts +20 -7
  233. package/dist/client/agent-page/use-jobs.d.ts.map +1 -1
  234. package/dist/client/agent-page/use-jobs.js +24 -4
  235. package/dist/client/agent-page/use-jobs.js.map +1 -1
  236. package/dist/client/org/OrgSwitcher.d.ts +8 -1
  237. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  238. package/dist/client/org/OrgSwitcher.js +8 -2
  239. package/dist/client/org/OrgSwitcher.js.map +1 -1
  240. package/dist/client/settings/AccountSettingsCard.d.ts.map +1 -1
  241. package/dist/client/settings/AccountSettingsCard.js +10 -9
  242. package/dist/client/settings/AccountSettingsCard.js.map +1 -1
  243. package/dist/client/settings/SchedulingTimezoneField.d.ts +10 -0
  244. package/dist/client/settings/SchedulingTimezoneField.d.ts.map +1 -0
  245. package/dist/client/settings/SchedulingTimezoneField.js +30 -0
  246. package/dist/client/settings/SchedulingTimezoneField.js.map +1 -0
  247. package/dist/client/settings/SettingsRow.d.ts +36 -0
  248. package/dist/client/settings/SettingsRow.d.ts.map +1 -0
  249. package/dist/client/settings/SettingsRow.js +15 -0
  250. package/dist/client/settings/SettingsRow.js.map +1 -0
  251. package/dist/client/settings/agent-settings-search.d.ts.map +1 -1
  252. package/dist/client/settings/agent-settings-search.js +1 -1
  253. package/dist/client/settings/agent-settings-search.js.map +1 -1
  254. package/dist/client/settings/index.d.ts +1 -0
  255. package/dist/client/settings/index.d.ts.map +1 -1
  256. package/dist/client/settings/index.js +1 -0
  257. package/dist/client/settings/index.js.map +1 -1
  258. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  259. package/dist/integrations/identity.d.ts.map +1 -1
  260. package/dist/integrations/identity.js +2 -11
  261. package/dist/integrations/identity.js.map +1 -1
  262. package/dist/jobs/actions/list-automation-runs.d.ts +8 -0
  263. package/dist/jobs/actions/list-automation-runs.d.ts.map +1 -0
  264. package/dist/jobs/actions/list-automation-runs.js +29 -0
  265. package/dist/jobs/actions/list-automation-runs.js.map +1 -0
  266. package/dist/jobs/actions/list-recurring-jobs.d.ts +2 -0
  267. package/dist/jobs/actions/list-recurring-jobs.d.ts.map +1 -1
  268. package/dist/jobs/actions/list-recurring-jobs.js +20 -7
  269. package/dist/jobs/actions/list-recurring-jobs.js.map +1 -1
  270. package/dist/jobs/actions/manage-recurring-job.d.ts +2 -0
  271. package/dist/jobs/actions/manage-recurring-job.js +30 -9
  272. package/dist/jobs/actions/manage-recurring-job.js.map +1 -1
  273. package/dist/jobs/background-automation-runner.d.ts.map +1 -1
  274. package/dist/jobs/background-automation-runner.js +60 -0
  275. package/dist/jobs/background-automation-runner.js.map +1 -1
  276. package/dist/jobs/cron.d.ts +16 -2
  277. package/dist/jobs/cron.d.ts.map +1 -1
  278. package/dist/jobs/cron.js +43 -6
  279. package/dist/jobs/cron.js.map +1 -1
  280. package/dist/jobs/frontmatter.d.ts +12 -0
  281. package/dist/jobs/frontmatter.d.ts.map +1 -1
  282. package/dist/jobs/frontmatter.js +8 -0
  283. package/dist/jobs/frontmatter.js.map +1 -1
  284. package/dist/jobs/run-history.d.ts +56 -0
  285. package/dist/jobs/run-history.d.ts.map +1 -0
  286. package/dist/jobs/run-history.js +169 -0
  287. package/dist/jobs/run-history.js.map +1 -0
  288. package/dist/jobs/scheduler.d.ts.map +1 -1
  289. package/dist/jobs/scheduler.js +51 -18
  290. package/dist/jobs/scheduler.js.map +1 -1
  291. package/dist/jobs/tools.d.ts.map +1 -1
  292. package/dist/jobs/tools.js +37 -6
  293. package/dist/jobs/tools.js.map +1 -1
  294. package/dist/localization/actions/get-localization-preference.d.ts +1 -2
  295. package/dist/localization/actions/get-localization-preference.d.ts.map +1 -1
  296. package/dist/localization/actions/get-localization-preference.js.map +1 -1
  297. package/dist/localization/actions/set-localization-preference.d.ts +3 -3
  298. package/dist/localization/actions/set-localization-preference.d.ts.map +1 -1
  299. package/dist/localization/actions/set-localization-preference.js +33 -8
  300. package/dist/localization/actions/set-localization-preference.js.map +1 -1
  301. package/dist/localization/default-messages.d.ts +25 -0
  302. package/dist/localization/default-messages.d.ts.map +1 -1
  303. package/dist/localization/default-messages.js +25 -0
  304. package/dist/localization/default-messages.js.map +1 -1
  305. package/dist/localization/shared.d.ts +16 -1
  306. package/dist/localization/shared.d.ts.map +1 -1
  307. package/dist/localization/shared.js +22 -4
  308. package/dist/localization/shared.js.map +1 -1
  309. package/dist/localization/user-timezone.d.ts +11 -0
  310. package/dist/localization/user-timezone.d.ts.map +1 -0
  311. package/dist/localization/user-timezone.js +31 -0
  312. package/dist/localization/user-timezone.js.map +1 -0
  313. package/dist/notifications/routes.d.ts +4 -4
  314. package/dist/observability/routes.d.ts +3 -3
  315. package/dist/org/app-roles-handlers.d.ts.map +1 -1
  316. package/dist/org/app-roles-handlers.js +1 -8
  317. package/dist/org/app-roles-handlers.js.map +1 -1
  318. package/dist/org/index.d.ts +1 -0
  319. package/dist/org/index.d.ts.map +1 -1
  320. package/dist/org/index.js +1 -0
  321. package/dist/org/index.js.map +1 -1
  322. package/dist/org/membership.d.ts +6 -0
  323. package/dist/org/membership.d.ts.map +1 -0
  324. package/dist/org/membership.js +16 -0
  325. package/dist/org/membership.js.map +1 -0
  326. package/dist/progress/routes.d.ts +1 -1
  327. package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
  328. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  329. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  330. package/dist/review/actions/create-review-comment.d.ts +32 -1
  331. package/dist/review/actions/create-review-comment.d.ts.map +1 -1
  332. package/dist/review/actions/create-review-comment.js +3 -1
  333. package/dist/review/actions/create-review-comment.js.map +1 -1
  334. package/dist/review/actions/reply-review-comment.d.ts +32 -1
  335. package/dist/review/actions/reply-review-comment.d.ts.map +1 -1
  336. package/dist/review/actions/reply-review-comment.js +3 -1
  337. package/dist/review/actions/reply-review-comment.js.map +1 -1
  338. package/dist/review/index.d.ts +1 -0
  339. package/dist/review/index.d.ts.map +1 -1
  340. package/dist/review/index.js +1 -0
  341. package/dist/review/index.js.map +1 -1
  342. package/dist/review/notifications.d.ts +24 -0
  343. package/dist/review/notifications.d.ts.map +1 -0
  344. package/dist/review/notifications.js +123 -0
  345. package/dist/review/notifications.js.map +1 -0
  346. package/dist/review/types.d.ts +5 -0
  347. package/dist/review/types.d.ts.map +1 -1
  348. package/dist/review/types.js.map +1 -1
  349. package/dist/server/action-discovery.d.ts.map +1 -1
  350. package/dist/server/action-discovery.js +4 -0
  351. package/dist/server/action-discovery.js.map +1 -1
  352. package/dist/server/activity-notifications.d.ts +61 -0
  353. package/dist/server/activity-notifications.d.ts.map +1 -0
  354. package/dist/server/activity-notifications.js +103 -0
  355. package/dist/server/activity-notifications.js.map +1 -0
  356. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  357. package/dist/server/app-name.d.ts +18 -0
  358. package/dist/server/app-name.d.ts.map +1 -1
  359. package/dist/server/app-name.js +31 -0
  360. package/dist/server/app-name.js.map +1 -1
  361. package/dist/server/better-auth-instance.js +4 -4
  362. package/dist/server/better-auth-instance.js.map +1 -1
  363. package/dist/server/email-templates.d.ts +12 -0
  364. package/dist/server/email-templates.d.ts.map +1 -1
  365. package/dist/server/email-templates.js +57 -14
  366. package/dist/server/email-templates.js.map +1 -1
  367. package/dist/server/email.d.ts +12 -0
  368. package/dist/server/email.d.ts.map +1 -1
  369. package/dist/server/email.js +52 -5
  370. package/dist/server/email.js.map +1 -1
  371. package/dist/server/index.d.ts +1 -0
  372. package/dist/server/index.d.ts.map +1 -1
  373. package/dist/server/index.js +1 -0
  374. package/dist/server/index.js.map +1 -1
  375. package/dist/server/transcribe-voice.d.ts +1 -1
  376. package/dist/sharing/access.d.ts.map +1 -1
  377. package/dist/sharing/access.js +32 -2
  378. package/dist/sharing/access.js.map +1 -1
  379. package/dist/sharing/index.d.ts +1 -0
  380. package/dist/sharing/index.d.ts.map +1 -1
  381. package/dist/sharing/index.js +1 -0
  382. package/dist/sharing/index.js.map +1 -1
  383. package/dist/sharing/recipients.d.ts +31 -0
  384. package/dist/sharing/recipients.d.ts.map +1 -0
  385. package/dist/sharing/recipients.js +40 -0
  386. package/dist/sharing/recipients.js.map +1 -0
  387. package/dist/templates/chat/app/routes/settings.tsx +14 -22
  388. package/dist/templates/chat/vitest.config.ts +9 -0
  389. package/dist/triggers/actions/list-automations.d.ts +2 -0
  390. package/dist/triggers/actions/list-automations.d.ts.map +1 -1
  391. package/dist/triggers/actions/list-automations.js +19 -8
  392. package/dist/triggers/actions/list-automations.js.map +1 -1
  393. package/dist/triggers/actions/manage-automation.d.ts +6 -0
  394. package/dist/triggers/actions/manage-automation.js +12 -6
  395. package/dist/triggers/actions/manage-automation.js.map +1 -1
  396. package/dist/triggers/actions.d.ts.map +1 -1
  397. package/dist/triggers/actions.js +15 -4
  398. package/dist/triggers/actions.js.map +1 -1
  399. package/dist/triggers/dispatcher.d.ts.map +1 -1
  400. package/dist/triggers/dispatcher.js +19 -17
  401. package/dist/triggers/dispatcher.js.map +1 -1
  402. package/dist/triggers/routes.d.ts.map +1 -1
  403. package/dist/triggers/routes.js +6 -6
  404. package/dist/triggers/routes.js.map +1 -1
  405. package/dist/vitest-config.d.ts +10 -0
  406. package/dist/vitest-config.d.ts.map +1 -0
  407. package/dist/vitest-config.js +55 -0
  408. package/dist/vitest-config.js.map +1 -0
  409. package/package.json +5 -4
  410. package/src/automations/service.ts +41 -4
  411. package/src/cli/mcp-config-writers.ts +27 -21
  412. package/src/client/agent-page/AgentJobsTab.tsx +187 -85
  413. package/src/client/agent-page/AutomationDetailsDialog.tsx +208 -0
  414. package/src/client/agent-page/AutomationScheduleDialog.tsx +180 -0
  415. package/src/client/agent-page/TimezoneSelect.tsx +241 -0
  416. package/src/client/agent-page/use-jobs.ts +50 -10
  417. package/src/client/org/OrgSwitcher.tsx +26 -0
  418. package/src/client/settings/AccountSettingsCard.tsx +35 -31
  419. package/src/client/settings/SchedulingTimezoneField.tsx +71 -0
  420. package/src/client/settings/SettingsRow.tsx +113 -0
  421. package/src/client/settings/agent-settings-search.ts +2 -1
  422. package/src/client/settings/index.ts +6 -0
  423. package/src/integrations/identity.ts +2 -12
  424. package/src/jobs/actions/list-automation-runs.ts +33 -0
  425. package/src/jobs/actions/list-recurring-jobs.ts +27 -6
  426. package/src/jobs/actions/manage-recurring-job.ts +41 -9
  427. package/src/jobs/background-automation-runner.ts +88 -0
  428. package/src/jobs/cron.ts +52 -6
  429. package/src/jobs/frontmatter.ts +20 -0
  430. package/src/jobs/run-history.ts +242 -0
  431. package/src/jobs/scheduler.ts +73 -18
  432. package/src/jobs/tools.ts +54 -6
  433. package/src/localization/actions/get-localization-preference.ts +2 -2
  434. package/src/localization/actions/set-localization-preference.ts +49 -11
  435. package/src/localization/default-messages.ts +27 -0
  436. package/src/localization/shared.ts +39 -6
  437. package/src/localization/user-timezone.ts +36 -0
  438. package/src/org/app-roles-handlers.ts +1 -9
  439. package/src/org/index.ts +2 -0
  440. package/src/org/membership.ts +18 -0
  441. package/src/review/actions/create-review-comment.ts +4 -1
  442. package/src/review/actions/reply-review-comment.ts +4 -1
  443. package/src/review/index.ts +5 -0
  444. package/src/review/notifications.ts +163 -0
  445. package/src/review/types.ts +7 -0
  446. package/src/server/action-discovery.ts +4 -0
  447. package/src/server/activity-notifications.ts +174 -0
  448. package/src/server/app-name.ts +31 -0
  449. package/src/server/better-auth-instance.ts +4 -4
  450. package/src/server/email-templates.ts +70 -14
  451. package/src/server/email.ts +66 -3
  452. package/src/server/index.ts +10 -0
  453. package/src/sharing/access.ts +44 -2
  454. package/src/sharing/index.ts +5 -0
  455. package/src/sharing/recipients.ts +67 -0
  456. package/src/templates/chat/app/routes/settings.tsx +14 -22
  457. package/src/templates/chat/vitest.config.ts +9 -0
  458. package/src/triggers/actions/list-automations.ts +27 -8
  459. package/src/triggers/actions/manage-automation.ts +17 -6
  460. package/src/triggers/actions.ts +16 -4
  461. package/src/triggers/dispatcher.ts +44 -30
  462. package/src/triggers/routes.ts +19 -6
  463. package/src/vitest-config.ts +68 -0
@@ -204,6 +204,7 @@ import {
204
204
  } from "@/hooks/use-document-properties";
205
205
  import {
206
206
  isDocumentUpdateConflict,
207
+ documentQueryFilter,
207
208
  type DocumentUpdateResult,
208
209
  useDeleteDocument,
209
210
  useDocument,
@@ -4853,9 +4854,7 @@ function DatabaseItemPreview({
4853
4854
  void queryClient.invalidateQueries({
4854
4855
  queryKey: contentDatabaseQueryKey(databaseDocumentId),
4855
4856
  });
4856
- void queryClient.invalidateQueries({
4857
- queryKey: ["action", "get-document", { id: document.id }],
4858
- });
4857
+ void queryClient.invalidateQueries(documentQueryFilter(document.id));
4859
4858
  void queryClient.invalidateQueries({
4860
4859
  queryKey: ["action", "list-documents"],
4861
4860
  });
@@ -126,6 +126,7 @@ import {
126
126
  useUpdateDocument,
127
127
  buildDocumentTree,
128
128
  filterDocumentTreeDocuments,
129
+ documentQueryFilter,
129
130
  } from "@/hooks/use-documents";
130
131
  import { useLocalStorage } from "@/hooks/use-local-storage";
131
132
  import {
@@ -1191,16 +1192,12 @@ export function DocumentSidebar({
1191
1192
  created,
1192
1193
  );
1193
1194
  if (nextId !== id) {
1194
- queryClient.removeQueries({
1195
- queryKey: ["action", "get-document", { id }],
1196
- });
1195
+ queryClient.removeQueries(documentQueryFilter(id));
1197
1196
  navigateToDocument(nextId);
1198
1197
  }
1199
1198
  // Replace optimistic doc with real server doc + clear any 404 error
1200
1199
  // state from the in-flight fetch that ran before create completed.
1201
- queryClient.invalidateQueries({
1202
- queryKey: ["action", "get-document", { id: nextId }],
1203
- });
1200
+ queryClient.invalidateQueries(documentQueryFilter(nextId));
1204
1201
  queryClient.invalidateQueries({
1205
1202
  queryKey: ["action", "list-documents"],
1206
1203
  });
@@ -1214,9 +1211,7 @@ export function DocumentSidebar({
1214
1211
  queryClient.invalidateQueries({
1215
1212
  queryKey: ["action", "list-documents"],
1216
1213
  });
1217
- queryClient.removeQueries({
1218
- queryKey: ["action", "get-document", { id }],
1219
- });
1214
+ queryClient.removeQueries(documentQueryFilter(id));
1220
1215
  if (rootFilesDatabaseId) {
1221
1216
  queryClient.setQueryData<ContentDatabaseResponse>(
1222
1217
  contentDatabaseByIdQueryKey(rootFilesDatabaseId),
@@ -1300,9 +1295,7 @@ export function DocumentSidebar({
1300
1295
  );
1301
1296
  });
1302
1297
  for (const deletedId of deletedIds) {
1303
- queryClient.removeQueries({
1304
- queryKey: ["action", "get-document", { id: deletedId }],
1305
- });
1298
+ queryClient.removeQueries(documentQueryFilter(deletedId));
1306
1299
  }
1307
1300
 
1308
1301
  if (activeDeleted) {
@@ -0,0 +1 @@
1
+ export * from "@agent-native/toolkit/ui/switch";
@@ -57,6 +57,8 @@ import type {
57
57
  import type { Query, QueryClient } from "@tanstack/react-query";
58
58
  import { useQueryClient } from "@tanstack/react-query";
59
59
 
60
+ import { documentQueryFilter } from "../lib/document-query";
61
+
60
62
  export function contentDatabaseQueryKey(documentId: string) {
61
63
  return ["action", "get-content-database", { documentId }] as const;
62
64
  }
@@ -421,9 +423,7 @@ export function clearDeletedContentDatabaseFromCache(
421
423
  documentId: string,
422
424
  ) {
423
425
  queryClient.removeQueries(contentDatabaseQueryFilter(documentId));
424
- queryClient.removeQueries({
425
- queryKey: ["action", "get-document", { id: documentId }],
426
- });
426
+ queryClient.removeQueries(documentQueryFilter(documentId));
427
427
  queryClient.invalidateQueries({
428
428
  queryKey: ["action", "get-content-database"],
429
429
  });
@@ -713,20 +713,14 @@ export function useCreateContentDatabase(documentId: string | null) {
713
713
  {
714
714
  onSuccess: (data) => {
715
715
  if (documentId) {
716
- queryClient.invalidateQueries({
717
- queryKey: ["action", "get-document", { id: documentId }],
718
- });
716
+ queryClient.invalidateQueries(documentQueryFilter(documentId));
719
717
  queryClient.invalidateQueries({
720
718
  queryKey: contentDatabaseQueryKey(documentId),
721
719
  });
722
720
  }
723
- queryClient.invalidateQueries({
724
- queryKey: [
725
- "action",
726
- "get-document",
727
- { id: data.database.documentId },
728
- ],
729
- });
721
+ queryClient.invalidateQueries(
722
+ documentQueryFilter(data.database.documentId),
723
+ );
730
724
  queryClient.invalidateQueries({
731
725
  queryKey: ["action", "list-documents"],
732
726
  });
@@ -743,17 +737,11 @@ export function useCreateInlineContentDatabase(hostDocumentId: string | null) {
743
737
  >("create-inline-content-database", {
744
738
  onSuccess: (data) => {
745
739
  if (hostDocumentId) {
746
- queryClient.invalidateQueries({
747
- queryKey: ["action", "get-document", { id: hostDocumentId }],
748
- });
740
+ queryClient.invalidateQueries(documentQueryFilter(hostDocumentId));
749
741
  }
750
- queryClient.invalidateQueries({
751
- queryKey: [
752
- "action",
753
- "get-document",
754
- { id: data.block.databaseDocumentId },
755
- ],
756
- });
742
+ queryClient.invalidateQueries(
743
+ documentQueryFilter(data.block.databaseDocumentId),
744
+ );
757
745
  queryClient.invalidateQueries({
758
746
  queryKey: contentDatabaseQueryKey(data.block.databaseDocumentId),
759
747
  });
@@ -1488,7 +1476,10 @@ export function useProcessBuilderBodyHydration(documentId: string) {
1488
1476
 
1489
1477
  export function invalidateBuilderBodyHydrationQueries(
1490
1478
  queryClient: {
1491
- invalidateQueries: (filters: { queryKey: readonly unknown[] }) => unknown;
1479
+ invalidateQueries: (filters: {
1480
+ queryKey?: readonly unknown[];
1481
+ predicate?: (query: { queryKey: readonly unknown[] }) => boolean;
1482
+ }) => unknown;
1492
1483
  },
1493
1484
  documentId: string,
1494
1485
  variables?: Pick<ProcessBuilderBodyHydrationRequest, "documentId"> | null,
@@ -1501,9 +1492,7 @@ export function invalidateBuilderBodyHydrationQueries(
1501
1492
  queryKey: ["action", "get-content-database-source", { documentId }],
1502
1493
  });
1503
1494
  if (variables?.documentId) {
1504
- queryClient.invalidateQueries({
1505
- queryKey: ["action", "get-document", { id: variables.documentId }],
1506
- });
1495
+ queryClient.invalidateQueries(documentQueryFilter(variables.documentId));
1507
1496
  }
1508
1497
  }
1509
1498
 
@@ -0,0 +1,55 @@
1
+ import { agentNativePath } from "@agent-native/core/client/api-path";
2
+ import type { ContentUserPrefs } from "@shared/content-user-prefs";
3
+ import { useCallback, useEffect, useState } from "react";
4
+
5
+ const PREFS_PATH = "/_agent-native/content/user-prefs";
6
+
7
+ export interface ContentPrefsState {
8
+ prefs: ContentUserPrefs;
9
+ loading: boolean;
10
+ /** Applies the patch optimistically and rolls back if the write fails. */
11
+ save: (patch: ContentUserPrefs) => Promise<void>;
12
+ }
13
+
14
+ export function useContentPrefs(): ContentPrefsState {
15
+ const [prefs, setPrefs] = useState<ContentUserPrefs>({});
16
+ const [loading, setLoading] = useState(true);
17
+
18
+ useEffect(() => {
19
+ let cancelled = false;
20
+ void (async () => {
21
+ try {
22
+ const res = await fetch(agentNativePath(PREFS_PATH));
23
+ const json = res.ok ? await res.json() : null;
24
+ if (cancelled) return;
25
+ if (json && typeof json === "object" && !("error" in json)) {
26
+ setPrefs(json as ContentUserPrefs);
27
+ }
28
+ } finally {
29
+ if (!cancelled) setLoading(false);
30
+ }
31
+ })();
32
+ return () => {
33
+ cancelled = true;
34
+ };
35
+ }, []);
36
+
37
+ const save = useCallback(
38
+ async (patch: ContentUserPrefs) => {
39
+ const previous = prefs;
40
+ setPrefs((current) => ({ ...current, ...patch }));
41
+ const res = await fetch(agentNativePath(PREFS_PATH), {
42
+ method: "PUT",
43
+ headers: { "Content-Type": "application/json" },
44
+ body: JSON.stringify(patch),
45
+ });
46
+ if (!res.ok) {
47
+ setPrefs(previous);
48
+ throw new Error(`Save failed (${res.status})`);
49
+ }
50
+ },
51
+ [prefs],
52
+ );
53
+
54
+ return { prefs, loading, save };
55
+ }
@@ -12,6 +12,7 @@ import {
12
12
  import { useContentSpaces } from "@/hooks/use-content-spaces";
13
13
  import { useCreateDocument } from "@/hooks/use-documents";
14
14
  import { useLocalStorage } from "@/hooks/use-local-storage";
15
+ import { documentQueryFilter } from "@/lib/document-query";
15
16
  import { markDocumentCreationPending } from "@/lib/optimistic-document";
16
17
 
17
18
  const LIST_DOCUMENTS_QUERY_KEY = [
@@ -103,9 +104,7 @@ export function useCreatePage(opts?: {
103
104
  );
104
105
  // Replace optimistic doc with real server doc + clear any 404 error
105
106
  // state from the in-flight fetch that ran before create completed.
106
- queryClient.invalidateQueries({
107
- queryKey: ["action", "get-document", { id }],
108
- });
107
+ queryClient.invalidateQueries(documentQueryFilter(id));
109
108
  queryClient.invalidateQueries({
110
109
  queryKey: ["action", "list-documents"],
111
110
  });
@@ -115,9 +114,7 @@ export function useCreatePage(opts?: {
115
114
  queryClient.invalidateQueries({
116
115
  queryKey: ["action", "list-documents"],
117
116
  });
118
- queryClient.removeQueries({
119
- queryKey: ["action", "get-document", { id }],
120
- });
117
+ queryClient.removeQueries(documentQueryFilter(id));
121
118
  if (shouldNavigate) navigate("/");
122
119
  toast.error("Failed to create page", {
123
120
  description:
@@ -22,7 +22,10 @@ import {
22
22
  contentDatabaseQueryKey,
23
23
  removeDocumentPropertyFromDatabaseResponse,
24
24
  } from "./use-content-database";
25
- import { documentPropertiesQueryKey } from "./use-documents";
25
+ import {
26
+ documentPropertiesQueryKey,
27
+ documentQueryFilter,
28
+ } from "./use-documents";
26
29
 
27
30
  type DatabaseScopedRequest = { databaseId: string };
28
31
 
@@ -91,9 +94,7 @@ export function useConfigureDocumentProperty(
91
94
  queryClient.invalidateQueries({
92
95
  queryKey: documentPropertiesQueryKey(documentId, databaseId),
93
96
  });
94
- queryClient.invalidateQueries({
95
- queryKey: ["action", "get-document", { id: documentId }],
96
- });
97
+ queryClient.invalidateQueries(documentQueryFilter(documentId));
97
98
  queryClient.invalidateQueries(
98
99
  contentDatabaseConstrainedQueryFilter(databaseDocumentId),
99
100
  );
@@ -158,9 +159,7 @@ export function useSetDocumentProperty(
158
159
  queryClient.invalidateQueries({
159
160
  queryKey: documentPropertiesQueryKey(variables.documentId, databaseId),
160
161
  });
161
- queryClient.invalidateQueries({
162
- queryKey: ["action", "get-document", { id: variables.documentId }],
163
- });
162
+ queryClient.invalidateQueries(documentQueryFilter(variables.documentId));
164
163
  queryClient.invalidateQueries(
165
164
  contentDatabaseConstrainedQueryFilter(databaseDocumentId),
166
165
  );
@@ -195,9 +194,7 @@ export function useDuplicateDocumentProperty(
195
194
  queryClient.invalidateQueries({
196
195
  queryKey: documentPropertiesQueryKey(documentId, databaseId),
197
196
  });
198
- queryClient.invalidateQueries({
199
- queryKey: ["action", "get-document", { id: documentId }],
200
- });
197
+ queryClient.invalidateQueries(documentQueryFilter(documentId));
201
198
  queryClient.invalidateQueries({
202
199
  ...contentDatabaseQueryFilter(databaseDocumentId),
203
200
  });
@@ -220,9 +217,7 @@ export function useReorderDocumentProperty(
220
217
  queryClient.invalidateQueries({
221
218
  queryKey: documentPropertiesQueryKey(documentId, databaseId),
222
219
  });
223
- queryClient.invalidateQueries({
224
- queryKey: ["action", "get-document", { id: documentId }],
225
- });
220
+ queryClient.invalidateQueries(documentQueryFilter(documentId));
226
221
  queryClient.invalidateQueries({
227
222
  queryKey: contentDatabaseQueryKey(databaseDocumentId),
228
223
  });
@@ -277,9 +272,7 @@ export function useDeleteDocumentProperty(
277
272
  queryClient.invalidateQueries({
278
273
  queryKey: documentPropertiesQueryKey(documentId, databaseId),
279
274
  });
280
- queryClient.invalidateQueries({
281
- queryKey: ["action", "get-document", { id: documentId }],
282
- });
275
+ queryClient.invalidateQueries(documentQueryFilter(documentId));
283
276
  queryClient.invalidateQueries({
284
277
  ...contentDatabaseQueryFilter(databaseDocumentId),
285
278
  });
@@ -5,6 +5,8 @@ import {
5
5
  import type { Document, DocumentVersion } from "@shared/api";
6
6
  import { useQueryClient } from "@tanstack/react-query";
7
7
 
8
+ import { documentQueryFilter } from "./use-documents";
9
+
8
10
  export function useDocumentVersions(documentId: string | null) {
9
11
  return useActionQuery<DocumentVersion[]>(
10
12
  "list-document-versions",
@@ -29,9 +31,7 @@ export function useRestoreDocumentVersion(documentId: string) {
29
31
  queryClient.invalidateQueries({
30
32
  queryKey: ["action", "list-document-versions", { documentId }],
31
33
  });
32
- queryClient.invalidateQueries({
33
- queryKey: ["action", "get-document", { id: documentId }],
34
- });
34
+ queryClient.invalidateQueries(documentQueryFilter(documentId));
35
35
  },
36
36
  },
37
37
  );
@@ -19,23 +19,50 @@ import { useQueryClient } from "@tanstack/react-query";
19
19
  import { toast } from "sonner";
20
20
 
21
21
  import type { DocumentUpdateConflictResponse } from "../../actions/update-document";
22
+ import {
23
+ documentQueryFilter,
24
+ documentQueryKey,
25
+ type DocumentQueryContext,
26
+ } from "../lib/document-query";
22
27
  import {
23
28
  removeOptimisticItemFromContentDatabase,
24
29
  useRestoreContentDatabase,
25
30
  } from "./use-content-database";
26
31
 
32
+ export {
33
+ documentQueryFilter,
34
+ documentQueryKey,
35
+ type DocumentQueryContext,
36
+ } from "../lib/document-query";
37
+
27
38
  export type { DocumentUpdateConflictResponse };
28
39
 
40
+ export type PageOwnedDocumentCachePatch = Pick<
41
+ Partial<Document>,
42
+ | "id"
43
+ | "parentId"
44
+ | "title"
45
+ | "content"
46
+ | "description"
47
+ | "icon"
48
+ | "position"
49
+ | "isFavorite"
50
+ | "hideFromSearch"
51
+ | "visibility"
52
+ | "accessRole"
53
+ | "canEdit"
54
+ | "canManage"
55
+ | "source"
56
+ | "createdAt"
57
+ | "updatedAt"
58
+ >;
59
+
29
60
  export const LIST_DOCUMENTS_QUERY_KEY = [
30
61
  "action",
31
62
  "list-documents",
32
63
  undefined,
33
64
  ] as const;
34
65
 
35
- export function documentQueryKey(documentId: string) {
36
- return ["action", "get-document", { id: documentId }] as const;
37
- }
38
-
39
66
  export function documentPropertiesQueryKey(
40
67
  documentId: string,
41
68
  databaseId: string,
@@ -74,7 +101,27 @@ export function mergeDocumentIntoDocumentCache(
74
101
  old: unknown,
75
102
  document: Document,
76
103
  ) {
77
- return old && typeof old === "object" ? { ...old, ...document } : document;
104
+ const pageOwnedPatch: PageOwnedDocumentCachePatch = {
105
+ id: document.id,
106
+ parentId: document.parentId,
107
+ title: document.title,
108
+ content: document.content,
109
+ description: document.description,
110
+ icon: document.icon,
111
+ position: document.position,
112
+ isFavorite: document.isFavorite,
113
+ hideFromSearch: document.hideFromSearch,
114
+ visibility: document.visibility,
115
+ accessRole: document.accessRole,
116
+ canEdit: document.canEdit,
117
+ canManage: document.canManage,
118
+ source: document.source,
119
+ createdAt: document.createdAt,
120
+ updatedAt: document.updatedAt,
121
+ };
122
+ return old && typeof old === "object"
123
+ ? { ...old, ...pageOwnedPatch }
124
+ : pageOwnedPatch;
78
125
  }
79
126
 
80
127
  export function mergeDocumentIntoListDocumentsCache(
@@ -157,9 +204,9 @@ function patchDocumentWithFavoriteMembershipInDatabaseCache(
157
204
  export function patchDocumentCaches(
158
205
  queryClient: Pick<QueryClient, "setQueryData" | "setQueriesData">,
159
206
  documentId: string,
160
- patch: Partial<Document>,
207
+ patch: PageOwnedDocumentCachePatch,
161
208
  ) {
162
- queryClient.setQueryData(documentQueryKey(documentId), (old: unknown) =>
209
+ queryClient.setQueriesData(documentQueryFilter(documentId), (old: unknown) =>
163
210
  old && typeof old === "object" ? { ...old, ...patch } : old,
164
211
  );
165
212
  queryClient.setQueryData(LIST_DOCUMENTS_QUERY_KEY, (old: unknown) =>
@@ -219,7 +266,7 @@ export function patchContentSpaceNameCaches(
219
266
  export function documentUpdateSuccessPatch(
220
267
  data: DocumentUpdateResponse,
221
268
  variables: DocumentUpdateRequestWithCas,
222
- ): Partial<Document> {
269
+ ): PageOwnedDocumentCachePatch {
223
270
  return {
224
271
  updatedAt: data.updatedAt,
225
272
  ...(variables.title !== undefined ? { title: data.title } : {}),
@@ -289,13 +336,28 @@ export const DOCUMENT_QUERY_FRESHNESS_OPTIONS = {
289
336
  retry: false,
290
337
  };
291
338
 
292
- export function useDocument(id: string | null) {
293
- return useActionQuery<Document>("get-document", id ? { id } : undefined, {
294
- enabled: !!id,
295
- // Doc-not-found / no-access errors are deterministic — retrying just keeps
296
- // the spinner up for ~7s before the UI can render "Not found".
297
- ...DOCUMENT_QUERY_FRESHNESS_OPTIONS,
298
- });
339
+ export function useDocument(
340
+ id: string | null,
341
+ context: DocumentQueryContext = {},
342
+ ) {
343
+ return useActionQuery<Document>(
344
+ "get-document",
345
+ id
346
+ ? {
347
+ id,
348
+ ...(context.databaseId ? { databaseId: context.databaseId } : {}),
349
+ ...(context.databaseDocumentId
350
+ ? { databaseDocumentId: context.databaseDocumentId }
351
+ : {}),
352
+ }
353
+ : undefined,
354
+ {
355
+ enabled: !!id,
356
+ // Doc-not-found / no-access errors are deterministic — retrying just keeps
357
+ // the spinner up for ~7s before the UI can render "Not found".
358
+ ...DOCUMENT_QUERY_FRESHNESS_OPTIONS,
359
+ },
360
+ );
299
361
  }
300
362
 
301
363
  export interface PreviewDocumentDraftRecord {
@@ -368,7 +430,7 @@ export function useUpdateDocument() {
368
430
  };
369
431
  if (Object.keys(optimisticPatch).length === 0) return undefined;
370
432
 
371
- const documentKey = documentQueryKey(variables.id);
433
+ const documentFilter = documentQueryFilter(variables.id);
372
434
  const databaseFilter = {
373
435
  queryKey: ["action", "get-content-database"],
374
436
  } as const;
@@ -376,14 +438,14 @@ export function useUpdateDocument() {
376
438
  queryKey: ["action", "list-content-spaces"],
377
439
  } as const;
378
440
  await Promise.all([
379
- queryClient.cancelQueries({ queryKey: documentKey }),
441
+ queryClient.cancelQueries(documentFilter),
380
442
  queryClient.cancelQueries({ queryKey: LIST_DOCUMENTS_QUERY_KEY }),
381
443
  queryClient.cancelQueries(databaseFilter),
382
444
  queryClient.cancelQueries(contentSpacesFilter),
383
445
  ]);
384
446
 
385
447
  const previous: Array<[readonly unknown[], unknown]> = [
386
- [documentKey, queryClient.getQueryData(documentKey)],
448
+ ...queryClient.getQueriesData(documentFilter),
387
449
  [
388
450
  LIST_DOCUMENTS_QUERY_KEY,
389
451
  queryClient.getQueryData(LIST_DOCUMENTS_QUERY_KEY),
@@ -423,8 +485,8 @@ export function useUpdateDocument() {
423
485
  // just-applied write.
424
486
  if (isDocumentUpdateConflict(data)) {
425
487
  const serverDocument = data.document;
426
- queryClient.setQueryData(
427
- ["action", "get-document", { id: variables.id }],
488
+ queryClient.setQueriesData(
489
+ documentQueryFilter(variables.id),
428
490
  (old: unknown) =>
429
491
  mergeDocumentIntoDocumentCache(old, serverDocument),
430
492
  );
@@ -453,9 +515,7 @@ export function useUpdateDocument() {
453
515
  queryKey: ["action", "get-content-database"],
454
516
  });
455
517
  }
456
- queryClient.invalidateQueries({
457
- queryKey: ["action", "get-document", { id: variables.id }],
458
- });
518
+ queryClient.invalidateQueries(documentQueryFilter(variables.id));
459
519
  queryClient.invalidateQueries({
460
520
  queryKey: ["action", "list-documents"],
461
521
  });
@@ -525,9 +585,7 @@ export function useDeleteDocument() {
525
585
  queryClient.invalidateQueries({
526
586
  queryKey: ["action", "list-documents"],
527
587
  });
528
- queryClient.invalidateQueries({
529
- queryKey: ["action", "get-document", { id: variables.id }],
530
- });
588
+ queryClient.invalidateQueries(documentQueryFilter(variables.id));
531
589
  queryClient.invalidateQueries({
532
590
  queryKey: ["action", "get-content-database"],
533
591
  });
@@ -606,9 +664,7 @@ export function useMoveDocument() {
606
664
  queryClient.invalidateQueries({
607
665
  queryKey: ["action", "list-documents"],
608
666
  });
609
- queryClient.invalidateQueries({
610
- queryKey: ["action", "get-document", { id: variables.id }],
611
- });
667
+ queryClient.invalidateQueries(documentQueryFilter(variables.id));
612
668
  },
613
669
  },
614
670
  );
@@ -16,6 +16,8 @@ import type {
16
16
  import { useQuery, useQueryClient } from "@tanstack/react-query";
17
17
  import { useEffect, useRef } from "react";
18
18
 
19
+ import { documentQueryFilter } from "./use-documents";
20
+
19
21
  // The server signs a `redirect` query param into the OAuth `state` and the
20
22
  // callback route sends the user back there once the connection completes. If
21
23
  // we never send it, `state.redirectPath` defaults to "/" server-side and
@@ -55,9 +57,7 @@ export function invalidateDocumentQueries(
55
57
  // path after every debounced editor save). Invalidating the bare ["action"]
56
58
  // key would refetch every mounted query app-wide (sidebar tree, comments,
57
59
  // database views, search, connection status, ...) on each cycle.
58
- queryClient.invalidateQueries({
59
- queryKey: ["action", "get-document", { id: documentId }],
60
- });
60
+ queryClient.invalidateQueries(documentQueryFilter(documentId));
61
61
  queryClient.invalidateQueries({
62
62
  queryKey: ["action", "list-documents"],
63
63
  });
@@ -155,21 +155,23 @@ export function useDocumentSyncStatus(
155
155
 
156
156
  lastObservedSyncedAtRef.current = query.data.lastSyncedAt;
157
157
 
158
- const cachedDocument = queryClient.getQueryData<Document>([
159
- "action",
160
- "get-document",
161
- { id: normalizedDocumentId },
162
- ]);
158
+ const cachedDocuments = queryClient
159
+ .getQueriesData<Document>(documentQueryFilter(normalizedDocumentId))
160
+ .map(([, document]) => document)
161
+ .filter((document): document is Document => !!document);
163
162
  const syncedLocalUpdatedAt = query.data.lastPushedLocalUpdatedAt;
164
163
 
165
164
  if (
166
- cachedDocument?.updatedAt &&
165
+ cachedDocuments.some(
166
+ (cachedDocument) =>
167
+ !!cachedDocument.updatedAt &&
168
+ !!syncedLocalUpdatedAt &&
169
+ syncedLocalUpdatedAt > cachedDocument.updatedAt,
170
+ ) &&
167
171
  syncedLocalUpdatedAt &&
168
- syncedLocalUpdatedAt > cachedDocument.updatedAt
172
+ cachedDocuments.length > 0
169
173
  ) {
170
- queryClient.invalidateQueries({
171
- queryKey: ["action", "get-document", { id: normalizedDocumentId }],
172
- });
174
+ queryClient.invalidateQueries(documentQueryFilter(normalizedDocumentId));
173
175
  queryClient.invalidateQueries({ queryKey: ["action", "list-documents"] });
174
176
  }
175
177
  }, [