@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
@@ -1,8 +1,9 @@
1
1
  import { z } from "zod";
2
2
  import { defineAction } from "../../action.js";
3
3
  import { organizationResourceOwner, resourceDelete, resourceGetByPath, resourcePut, } from "../../resources/store.js";
4
- import { isValidCron, nextOccurrence } from "../cron.js";
4
+ import { isValidCron, isValidTimezone, nextOccurrence } from "../cron.js";
5
5
  import { classifyJobResource } from "../frontmatter.js";
6
+ import { deleteAutomationRuns } from "../run-history.js";
6
7
  import { buildJobContent, parseJobFrontmatter } from "../scheduler.js";
7
8
  import { authorizeJobMutation } from "../tools.js";
8
9
  const scopeSchema = z.enum(["personal", "organization"]);
@@ -14,8 +15,10 @@ export default defineAction({
14
15
  name: z.string().min(1),
15
16
  scope: scopeSchema.default("personal"),
16
17
  enabled: z.boolean().optional(),
18
+ schedule: z.string().min(1).optional(),
19
+ timezone: z.string().min(1).optional(),
17
20
  }),
18
- run: async ({ operation, name, scope, enabled }, ctx) => {
21
+ run: async ({ operation, name, scope, enabled, schedule, timezone }, ctx) => {
19
22
  const userEmail = ctx?.userEmail;
20
23
  if (!userEmail)
21
24
  throw new Error("Not authenticated.");
@@ -43,16 +46,34 @@ export default defineAction({
43
46
  throw Object.assign(new Error(denied), { statusCode: 403 });
44
47
  if (operation === "delete") {
45
48
  await resourceDelete(resource.id);
49
+ // Names are reusable; history left behind would surface as the run
50
+ // history of whatever job is next created under this name.
51
+ await deleteAutomationRuns(resource.owner, name);
46
52
  return { deleted: true, name };
47
53
  }
48
- if (enabled === undefined) {
49
- throw Object.assign(new Error("enabled is required for update."), {
50
- statusCode: 400,
51
- });
54
+ if (timezone !== undefined) {
55
+ if (!isValidTimezone(timezone)) {
56
+ throw Object.assign(new Error(`Unknown timezone "${timezone}".`), {
57
+ statusCode: 400,
58
+ });
59
+ }
60
+ meta.timezone = timezone;
61
+ }
62
+ if (enabled === undefined &&
63
+ schedule === undefined &&
64
+ timezone === undefined) {
65
+ throw Object.assign(new Error("enabled, schedule, or timezone is required for update."), { statusCode: 400 });
66
+ }
67
+ if (schedule !== undefined) {
68
+ if (!isValidCron(schedule)) {
69
+ throw Object.assign(new Error(`Invalid cron expression "${schedule}".`), { statusCode: 400 });
70
+ }
71
+ meta.schedule = schedule;
52
72
  }
53
- meta.enabled = enabled;
54
- if (enabled && meta.schedule && isValidCron(meta.schedule)) {
55
- meta.nextRun = nextOccurrence(meta.schedule).toISOString();
73
+ if (enabled !== undefined)
74
+ meta.enabled = enabled;
75
+ if (meta.enabled && meta.schedule && isValidCron(meta.schedule)) {
76
+ meta.nextRun = nextOccurrence(meta.schedule, undefined, meta.timezone).toISOString();
56
77
  }
57
78
  await resourcePut(resource.owner, resource.path, buildJobContent(meta, body));
58
79
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"manage-recurring-job.js","sourceRoot":"","sources":["../../../src/jobs/actions/manage-recurring-job.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport {\n organizationResourceOwner,\n resourceDelete,\n resourceGetByPath,\n resourcePut,\n} from \"../../resources/store.js\";\nimport { isValidCron, nextOccurrence } from \"../cron.js\";\nimport { classifyJobResource } from \"../frontmatter.js\";\nimport { buildJobContent, parseJobFrontmatter } from \"../scheduler.js\";\nimport { authorizeJobMutation } from \"../tools.js\";\n\nconst scopeSchema = z.enum([\"personal\", \"organization\"]);\n\nexport default defineAction({\n description:\n \"Enable, pause, or delete one legacy recurring cron job from the Agent Automations page.\",\n agentTool: false,\n schema: z.object({\n operation: z.enum([\"update\", \"delete\"]),\n name: z.string().min(1),\n scope: scopeSchema.default(\"personal\"),\n enabled: z.boolean().optional(),\n }),\n run: async ({ operation, name, scope, enabled }, ctx) => {\n const userEmail = ctx?.userEmail;\n if (!userEmail) throw new Error(\"Not authenticated.\");\n if (scope === \"organization\" && !ctx?.orgId) {\n throw new Error(\"An organization is required for organization jobs.\");\n }\n\n const owner =\n scope === \"organization\"\n ? organizationResourceOwner(ctx.orgId as string)\n : userEmail;\n const path = `jobs/${name}.md`;\n const resource = await resourceGetByPath(owner, path);\n if (!resource) {\n throw Object.assign(new Error(`Job \"${name}\" not found.`), {\n statusCode: 404,\n });\n }\n\n const { meta, body } = parseJobFrontmatter(resource.content);\n if (classifyJobResource(resource.content).kind === \"automation\") {\n throw Object.assign(new Error(`Job \"${name}\" is an automation.`), {\n statusCode: 400,\n });\n }\n const denied = await authorizeJobMutation(resource.owner, meta);\n if (denied) throw Object.assign(new Error(denied), { statusCode: 403 });\n\n if (operation === \"delete\") {\n await resourceDelete(resource.id);\n return { deleted: true, name };\n }\n\n if (enabled === undefined) {\n throw Object.assign(new Error(\"enabled is required for update.\"), {\n statusCode: 400,\n });\n }\n meta.enabled = enabled;\n if (enabled && meta.schedule && isValidCron(meta.schedule)) {\n meta.nextRun = nextOccurrence(meta.schedule).toISOString();\n }\n await resourcePut(\n resource.owner,\n resource.path,\n buildJobContent(meta, body),\n );\n\n return {\n name,\n enabled: meta.enabled,\n nextRun: meta.nextRun ?? null,\n };\n },\n});\n"]}
1
+ {"version":3,"file":"manage-recurring-job.js","sourceRoot":"","sources":["../../../src/jobs/actions/manage-recurring-job.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport {\n organizationResourceOwner,\n resourceDelete,\n resourceGetByPath,\n resourcePut,\n} from \"../../resources/store.js\";\nimport { isValidCron, isValidTimezone, nextOccurrence } from \"../cron.js\";\nimport { classifyJobResource } from \"../frontmatter.js\";\nimport { deleteAutomationRuns } from \"../run-history.js\";\nimport { buildJobContent, parseJobFrontmatter } from \"../scheduler.js\";\nimport { authorizeJobMutation } from \"../tools.js\";\n\nconst scopeSchema = z.enum([\"personal\", \"organization\"]);\n\nexport default defineAction({\n description:\n \"Enable, pause, or delete one legacy recurring cron job from the Agent Automations page.\",\n agentTool: false,\n schema: z.object({\n operation: z.enum([\"update\", \"delete\"]),\n name: z.string().min(1),\n scope: scopeSchema.default(\"personal\"),\n enabled: z.boolean().optional(),\n schedule: z.string().min(1).optional(),\n timezone: z.string().min(1).optional(),\n }),\n run: async ({ operation, name, scope, enabled, schedule, timezone }, ctx) => {\n const userEmail = ctx?.userEmail;\n if (!userEmail) throw new Error(\"Not authenticated.\");\n if (scope === \"organization\" && !ctx?.orgId) {\n throw new Error(\"An organization is required for organization jobs.\");\n }\n\n const owner =\n scope === \"organization\"\n ? organizationResourceOwner(ctx.orgId as string)\n : userEmail;\n const path = `jobs/${name}.md`;\n const resource = await resourceGetByPath(owner, path);\n if (!resource) {\n throw Object.assign(new Error(`Job \"${name}\" not found.`), {\n statusCode: 404,\n });\n }\n\n const { meta, body } = parseJobFrontmatter(resource.content);\n if (classifyJobResource(resource.content).kind === \"automation\") {\n throw Object.assign(new Error(`Job \"${name}\" is an automation.`), {\n statusCode: 400,\n });\n }\n const denied = await authorizeJobMutation(resource.owner, meta);\n if (denied) throw Object.assign(new Error(denied), { statusCode: 403 });\n\n if (operation === \"delete\") {\n await resourceDelete(resource.id);\n // Names are reusable; history left behind would surface as the run\n // history of whatever job is next created under this name.\n await deleteAutomationRuns(resource.owner, name);\n return { deleted: true, name };\n }\n\n if (timezone !== undefined) {\n if (!isValidTimezone(timezone)) {\n throw Object.assign(new Error(`Unknown timezone \"${timezone}\".`), {\n statusCode: 400,\n });\n }\n meta.timezone = timezone;\n }\n if (\n enabled === undefined &&\n schedule === undefined &&\n timezone === undefined\n ) {\n throw Object.assign(\n new Error(\"enabled, schedule, or timezone is required for update.\"),\n { statusCode: 400 },\n );\n }\n if (schedule !== undefined) {\n if (!isValidCron(schedule)) {\n throw Object.assign(\n new Error(`Invalid cron expression \"${schedule}\".`),\n { statusCode: 400 },\n );\n }\n meta.schedule = schedule;\n }\n if (enabled !== undefined) meta.enabled = enabled;\n if (meta.enabled && meta.schedule && isValidCron(meta.schedule)) {\n meta.nextRun = nextOccurrence(\n meta.schedule,\n undefined,\n meta.timezone,\n ).toISOString();\n }\n await resourcePut(\n resource.owner,\n resource.path,\n buildJobContent(meta, body),\n );\n\n return {\n name,\n enabled: meta.enabled,\n nextRun: meta.nextRun ?? null,\n };\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"background-automation-runner.d.ts","sourceRoot":"","sources":["../../src/jobs/background-automation-runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"background-automation-runner.d.ts","sourceRoot":"","sources":["../../src/jobs/background-automation-runner.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import { createThread } from "../chat-threads/store.js";
10
10
  import { queryOrgMembers } from "../org/context.js";
11
11
  import { organizationIdFromResourceOwner, } from "../resources/store.js";
12
12
  import { runWithRequestContext, } from "../server/request-context.js";
13
+ import { attachAutomationRunThread, finishAutomationRun, startAutomationRun, } from "./run-history.js";
13
14
  const BACKGROUND_RUN_STUCK_MS = 10 * 60_000;
14
15
  const BACKGROUND_RUN_HARD_TIMEOUT_MS = 5 * 60_000;
15
16
  /**
@@ -146,6 +147,64 @@ function createRunId(prefix) {
146
147
  return `${safePrefix}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
147
148
  }
148
149
  export async function runBackgroundAutomation(options, deps) {
150
+ const { automation } = options;
151
+ // Bookkeeping, so it must not gate the work it describes: a history table
152
+ // that cannot be written should cost us the record, not the automation.
153
+ // Everything downstream tolerates a null id by skipping its own write.
154
+ let historyId = null;
155
+ try {
156
+ historyId = await startAutomationRun({
157
+ owner: automation.resource.owner,
158
+ automation: automation.name,
159
+ path: automation.resource.path,
160
+ scope: organizationIdFromResourceOwner(automation.resource.owner)
161
+ ? "organization"
162
+ : "personal",
163
+ orgId: options.orgId ?? null,
164
+ });
165
+ }
166
+ catch (err) {
167
+ console.error(`[automations] Could not open a history record for "${automation.name}"; running anyway:`, err);
168
+ }
169
+ let result;
170
+ try {
171
+ result = await executeBackgroundAutomation(options, deps, historyId);
172
+ }
173
+ catch (err) {
174
+ await recordRunOutcome(historyId, "error", err instanceof Error ? err.message : String(err));
175
+ throw err;
176
+ }
177
+ // Outside the try: history is bookkeeping about the run, so a failure to
178
+ // write it must not turn a completed automation into a reported failure.
179
+ await recordRunOutcome(historyId, "success");
180
+ return result;
181
+ }
182
+ /**
183
+ * Link the run to its agent thread. Bookkeeping again: the automation is
184
+ * already executing by this point, so a failed write costs the cross-reference
185
+ * in the history view, not the run.
186
+ */
187
+ async function recordRunThread(historyId, threadId, runId) {
188
+ if (!historyId)
189
+ return;
190
+ try {
191
+ await attachAutomationRunThread(historyId, threadId, runId);
192
+ }
193
+ catch (err) {
194
+ console.error(`[automations] Could not attach thread ${threadId} to run ${historyId}:`, err);
195
+ }
196
+ }
197
+ async function recordRunOutcome(historyId, status, error) {
198
+ if (!historyId)
199
+ return;
200
+ try {
201
+ await finishAutomationRun(historyId, status, error);
202
+ }
203
+ catch (err) {
204
+ console.error(`[automations] Could not record run ${historyId} as ${status}:`, err);
205
+ }
206
+ }
207
+ async function executeBackgroundAutomation(options, deps, historyId) {
149
208
  const { automation, ownerEmail, orgId, prompt, threadTitle, usageLabel } = options;
150
209
  return runWithRequestContext({
151
210
  ...options.requestContext,
@@ -180,6 +239,7 @@ export async function runBackgroundAutomation(options, deps) {
180
239
  const systemPrompt = await deps.getSystemPrompt(ownerEmail);
181
240
  const thread = await createThread(ownerEmail, { title: threadTitle });
182
241
  const runId = createRunId(options.runIdPrefix);
242
+ await recordRunThread(historyId, thread.id, runId);
183
243
  // Scheduled work is background work: it has no synchronous serverless
184
244
  // caller waiting on it, so it must not inherit the interactive clamp
185
245
  // (40s soft timeout, a 30s no-progress backstop at 0.75x that, and 6
@@ -1 +1 @@
1
- {"version":3,"file":"background-automation-runner.js","sourceRoot":"","sources":["../../src/jobs/background-automation-runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { collectFinalResponseTextFromAgentEvents } from \"../a2a/response-text.js\";\nimport type { ActionAutomationContext, ActionCaller } from \"../action.js\";\nimport {\n getStoredModelForEngine,\n normalizeModelForEngine,\n resolveEngine,\n} from \"../agent/engine/index.js\";\nimport type { AgentEngine } from \"../agent/engine/types.js\";\nimport {\n actionsToEngineTools,\n filterInitialEngineTools,\n getOwnerActiveApiKey,\n runAgentLoop,\n type ActionEntry,\n} from \"../agent/production-agent.js\";\nimport { runAgentLoopDirectWithSoftTimeout } from \"../agent/run-loop-with-resume.js\";\nimport { resolveRunSoftTimeoutMs, startRun } from \"../agent/run-manager.js\";\nimport { claimBackgroundRun, insertRun } from \"../agent/run-store.js\";\nimport { attachToolSearch } from \"../agent/tool-search.js\";\nimport {\n resolveAutomationExecutionIdentity,\n type AutomationExecutionIdentity,\n} from \"../automations/service.js\";\nimport { createThread } from \"../chat-threads/store.js\";\nimport { queryOrgMembers } from \"../org/context.js\";\nimport {\n organizationIdFromResourceOwner,\n type Resource,\n} from \"../resources/store.js\";\nimport {\n runWithRequestContext,\n type RequestContext,\n} from \"../server/request-context.js\";\nimport type { JobFrontmatter } from \"./frontmatter.js\";\n\nconst BACKGROUND_RUN_STUCK_MS = 10 * 60_000;\nconst BACKGROUND_RUN_HARD_TIMEOUT_MS = 5 * 60_000;\n\nexport interface BackgroundAutomationContext {\n name: string;\n meta: JobFrontmatter;\n body: string;\n resource: Resource;\n}\n\nexport interface BackgroundAutomationDeps {\n getActions: (\n automation?: BackgroundAutomationContext,\n ) => Record<string, ActionEntry>;\n getSystemPrompt: (owner: string) => Promise<string>;\n getInitialToolNames?: (\n automation?: BackgroundAutomationContext,\n ) => string[] | undefined;\n engine?: AgentEngine;\n apiKey?: string;\n model?: string;\n appId?: string;\n}\n\nexport interface BackgroundAutomationRunOptions {\n automation: BackgroundAutomationContext;\n ownerEmail: string;\n orgId?: string;\n prompt: string;\n threadTitle: string;\n runIdPrefix: string;\n usageLabel: string;\n usageRefId?: string;\n requestContext?: Omit<RequestContext, \"userEmail\" | \"orgId\">;\n actionCaller?: ActionCaller;\n actionAutomation?: ActionAutomationContext;\n}\n\nexport interface BackgroundAutomationRunResult {\n responseText: string;\n runId: string;\n}\n\nexport type AutomationIdentityValidation =\n | { ok: true }\n | { ok: false; reason: string };\n\nexport type BackgroundAutomationIdentityResult =\n | { ok: true; identity: AutomationExecutionIdentity }\n | { ok: false; reason: string };\n\n/**\n * A persisted background run must not outlive its execution identity.\n * Organization runs fail closed when membership state cannot be read. A\n * brand-new personal install without auth tables remains a distinct\n * not-applicable case so local/CLI jobs keep working before auth is configured.\n */\nexport async function validateAutomationRunIdentity(\n ownerEmail: string,\n orgId?: string,\n): Promise<AutomationIdentityValidation> {\n if (\n ownerEmail === \"__shared__\" ||\n organizationIdFromResourceOwner(ownerEmail)\n ) {\n return { ok: true };\n }\n\n try {\n const { getDbExec } = await import(\"../db/client.js\");\n const userResult = await getDbExec().execute({\n sql: `SELECT 1 FROM \"user\" WHERE email = ? LIMIT 1`,\n args: [ownerEmail],\n });\n if (!userResult.rows || userResult.rows.length === 0) {\n return { ok: false, reason: `user \"${ownerEmail}\" no longer exists` };\n }\n } catch (error) {\n const message =\n error instanceof Error ? error.message.toLowerCase() : String(error);\n const authTablesAreUnconfigured =\n !orgId &&\n (message.includes(\"does not exist\") ||\n message.includes(\"no such table\") ||\n message.includes(\"undefined table\"));\n if (authTablesAreUnconfigured) return { ok: true };\n return {\n ok: false,\n reason: `could not verify user \"${ownerEmail}\" for this run`,\n };\n }\n\n if (!orgId) return { ok: true };\n\n try {\n const memberRows = await queryOrgMembers({\n sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = LOWER(?) LIMIT 1`,\n args: [orgId, ownerEmail],\n });\n if (memberRows === null) {\n return {\n ok: false,\n reason: `could not verify membership in org \"${orgId}\"`,\n };\n }\n if (memberRows.length === 0) {\n return {\n ok: false,\n reason: `user \"${ownerEmail}\" is no longer a member of org \"${orgId}\"`,\n };\n }\n return { ok: true };\n } catch {\n return {\n ok: false,\n reason: `could not verify membership in org \"${orgId}\"`,\n };\n }\n}\n\nexport async function resolveBackgroundAutomationIdentity(\n automation: BackgroundAutomationContext,\n): Promise<BackgroundAutomationIdentityResult> {\n if (automation.meta.triggerType) {\n try {\n return await resolveAutomationExecutionIdentity(\n automation.resource.owner,\n automation.meta,\n );\n } catch {\n return {\n ok: false,\n reason: \"Could not verify the automation execution identity.\",\n };\n }\n }\n\n const effectiveRunAs = automation.meta.runAs ?? \"creator\";\n const userEmail =\n effectiveRunAs === \"creator\"\n ? automation.meta.createdBy || automation.resource.owner\n : automation.resource.owner;\n const orgId = automation.meta.orgId ?? undefined;\n const validity = await validateAutomationRunIdentity(userEmail, orgId);\n return validity.ok\n ? {\n ok: true,\n identity: {\n userEmail,\n orgId,\n eventOwner: userEmail.toLowerCase(),\n },\n }\n : validity;\n}\n\nexport function isBackgroundAutomationRunActive(\n meta: Pick<JobFrontmatter, \"lastRun\" | \"lastStatus\">,\n now = new Date(),\n): boolean {\n if (meta.lastStatus !== \"running\") return false;\n if (!meta.lastRun) return false;\n const startedAt = new Date(meta.lastRun).getTime();\n return (\n Number.isFinite(startedAt) &&\n now.getTime() - startedAt < BACKGROUND_RUN_STUCK_MS\n );\n}\n\n/**\n * A soft-timeout/no-progress checkpoint is a continuation boundary, not a\n * successful finish. Only the last terminal event decides whether an\n * in-invocation resume recovered from the boundary.\n */\nexport function backgroundRunCutOffReason(run: {\n events?: readonly { event: { type: string; reason?: string } }[];\n}): string | null {\n const events = run.events ?? [];\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i].event;\n if (event.type === \"auto_continue\") {\n return event.reason === \"run_timeout\" || event.reason === \"no_progress\"\n ? event.reason\n : null;\n }\n if (event.type === \"done\" || event.type === \"error\") return null;\n }\n return null;\n}\n\nfunction uniqueToolNames(names: readonly string[]): string[] {\n return [...new Set(names)];\n}\n\nfunction assertRequestedMcpToolsAvailable(\n automation: BackgroundAutomationContext,\n actions: Record<string, ActionEntry>,\n): void {\n const requested = automation.meta.mcpTools ?? [];\n const missing = requested.filter((toolName) => !actions[toolName]);\n if (missing.length > 0) {\n throw new Error(\n `Configured MCP tools are unavailable in this run: ${missing.join(\", \")}. Reconnect the MCP server or update the automation's capability list.`,\n );\n }\n}\n\nfunction createRunId(prefix: string): string {\n const safePrefix = prefix.replace(/[^a-zA-Z0-9._-]/g, \"-\");\n return `${safePrefix}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n}\n\nexport async function runBackgroundAutomation(\n options: BackgroundAutomationRunOptions,\n deps: BackgroundAutomationDeps,\n): Promise<BackgroundAutomationRunResult> {\n const { automation, ownerEmail, orgId, prompt, threadTitle, usageLabel } =\n options;\n\n return runWithRequestContext(\n {\n ...options.requestContext,\n userEmail: ownerEmail,\n orgId,\n },\n async () => {\n const baseActions = deps.getActions(automation);\n assertRequestedMcpToolsAvailable(automation, baseActions);\n\n const configuredInitialTools = deps.getInitialToolNames?.(automation);\n const initialToolNames = configuredInitialTools\n ? uniqueToolNames([\n ...configuredInitialTools,\n ...(automation.meta.mcpTools ?? []),\n ])\n : undefined;\n const actions = initialToolNames\n ? attachToolSearch({ ...baseActions })\n : baseActions;\n const availableTools = actionsToEngineTools(actions);\n const tools = filterInitialEngineTools(availableTools, initialToolNames);\n\n const userApiKey = await getOwnerActiveApiKey(ownerEmail);\n const engine =\n deps.engine ??\n (await resolveEngine({\n apiKey: userApiKey ?? deps.apiKey,\n appId: deps.appId,\n }));\n const modelCandidate =\n automation.meta.model ??\n deps.model ??\n (await getStoredModelForEngine(engine, { appId: deps.appId })) ??\n engine.defaultModel;\n const model = normalizeModelForEngine(engine, modelCandidate);\n const systemPrompt = await deps.getSystemPrompt(ownerEmail);\n const thread = await createThread(ownerEmail, { title: threadTitle });\n const runId = createRunId(options.runIdPrefix);\n // Scheduled work is background work: it has no synchronous serverless\n // caller waiting on it, so it must not inherit the interactive clamp\n // (40s soft timeout, a 30s no-progress backstop at 0.75x that, and 6\n // continuations). A dashboard render or digest legitimately spends\n // minutes across many tool calls, and dies the first time any gap\n // between two of them exceeds 30s — recorded as `no_progress` after\n // several minutes of real work, because the backstop is suspended\n // while a tool is in flight but not between tools.\n //\n // Hardcoded rather than `isInBackgroundFunctionRuntime()` (what\n // webhook-handler.ts uses): a webhook can arrive on either runtime, but\n // a scheduler tick never serves a synchronous request, so the\n // interactive clamp never applies to it. The wider soft ceiling stays\n // bounded by this runner's own BACKGROUND_RUN_HARD_TIMEOUT_MS abort.\n const softTimeoutMs = resolveRunSoftTimeoutMs(undefined, {\n useHostedDefault: true,\n backgroundFunction: true,\n });\n\n const usageRef: {\n current: Awaited<ReturnType<typeof runAgentLoop>> | null;\n } = { current: null };\n let responseText = \"\";\n let hardAbortTimer: ReturnType<typeof setTimeout> | null = null;\n\n // This runner executes in-process, synchronously — there is no HTTP\n // self-dispatch to a separate worker. Self-claim the row into\n // 'background-processing' right away, exactly like a genuine HTTP\n // background worker does immediately after its own insert (see\n // production-agent.ts's `claimBackgroundWorkerRunEarly`). Without this,\n // the row sits at dispatch_mode='background' for its whole life with no\n // worker ever claiming it, which is indistinguishable from a lost HTTP\n // handoff to the unclaimed-background-run sweep — it gets reaped as\n // \"background_worker_never_started\" out from under a still-executing\n // job the moment any single tool call runs past the 25s grace window.\n await insertRun(runId, thread.id, undefined, {\n dispatchMode: \"background\",\n });\n const claimedOwnRun = await claimBackgroundRun(runId);\n if (!claimedOwnRun) {\n throw new Error(\n `Background automation \"${automation.name}\" (run \"${runId}\") could not claim its own freshly-inserted run row`,\n );\n }\n\n await new Promise<void>((resolve, reject) => {\n const activeRun = startRun(\n runId,\n thread.id,\n async (send, signal) => {\n usageRef.current = await runAgentLoopDirectWithSoftTimeout(\n {\n engine,\n model,\n systemPrompt,\n tools,\n availableTools,\n messages: [\n {\n role: \"user\",\n content: [{ type: \"text\", text: prompt }],\n },\n ],\n actions,\n send,\n signal,\n threadId: thread.id,\n ownerEmail,\n orgId,\n actionCaller: options.actionCaller,\n automation: options.actionAutomation,\n runId,\n },\n softTimeoutMs,\n { backgroundFunction: true },\n );\n },\n async (run) => {\n if (hardAbortTimer) {\n clearTimeout(hardAbortTimer);\n hardAbortTimer = null;\n }\n const cutOffReason = backgroundRunCutOffReason(run);\n if (cutOffReason) {\n reject(\n new Error(\n `Background automation was cut off before finishing (${cutOffReason})`,\n ),\n );\n return;\n }\n if (run.status !== \"completed\") {\n reject(\n new Error(\n `Background automation ended with status: ${run.status}`,\n ),\n );\n return;\n }\n responseText = collectFinalResponseTextFromAgentEvents(\n (run.events ?? []).map((entry) => entry.event),\n );\n resolve();\n },\n {\n softTimeoutMs,\n backgroundFunction: true,\n model,\n engineName: engine.name,\n },\n );\n\n hardAbortTimer = setTimeout(() => {\n hardAbortTimer = null;\n if (activeRun.status === \"running\") {\n activeRun.abort.abort(\"background_automation_hard_timeout\");\n reject(\n new Error(\"Background automation timed out after 5 minutes\"),\n );\n }\n }, BACKGROUND_RUN_HARD_TIMEOUT_MS);\n }).finally(() => {\n if (hardAbortTimer) {\n clearTimeout(hardAbortTimer);\n hardAbortTimer = null;\n }\n });\n\n const usage = usageRef.current;\n if (\n usage &&\n (usage.inputTokens > 0 ||\n usage.outputTokens > 0 ||\n usage.cacheReadTokens > 0 ||\n usage.cacheWriteTokens > 0)\n ) {\n try {\n const { recordUsage } = await import(\"../usage/store.js\");\n await recordUsage({\n ownerEmail,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n cacheReadTokens: usage.cacheReadTokens,\n cacheWriteTokens: usage.cacheWriteTokens,\n model: usage.model,\n label: usageLabel,\n app: deps.appId,\n refId: options.usageRefId ?? runId,\n });\n } catch {\n // Usage attribution must not break an otherwise successful run.\n }\n }\n\n if (\n responseText.trim() &&\n automation.meta.deliveryPlatform &&\n automation.meta.deliveryDestination\n ) {\n const { getDefaultAdapter } =\n await import(\"../integrations/adapters/index.js\");\n const adapter = getDefaultAdapter(automation.meta.deliveryPlatform);\n if (!adapter?.sendMessageToTarget) {\n throw new Error(\n `Automation delivery is not supported for ${automation.meta.deliveryPlatform}`,\n );\n }\n await adapter.sendMessageToTarget(\n adapter.formatAgentResponse(responseText),\n {\n destination: automation.meta.deliveryDestination,\n threadRef: automation.meta.deliveryThreadRef ?? null,\n tenantId: automation.meta.deliveryTenantId,\n },\n );\n }\n\n return { responseText, runId };\n },\n );\n}\n"]}
1
+ {"version":3,"file":"background-automation-runner.js","sourceRoot":"","sources":["../../src/jobs/background-automation-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uCAAuC,EAAE,MAAM,yBAAyB,CAAC;AAElF,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,GAGrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,kCAAkC,GAEnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACL,+BAA+B,GAEhC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,qBAAqB,GAEtB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,uBAAuB,GAAG,EAAE,GAAG,MAAM,CAAC;AAC5C,MAAM,8BAA8B,GAAG,CAAC,GAAG,MAAM,CAAC;AAkDlD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,UAAkB,EAClB,KAAc;IAEd,IACE,UAAU,KAAK,YAAY;QAC3B,+BAA+B,CAAC,UAAU,CAAC,EAC3C,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACtD,MAAM,UAAU,GAAG,MAAM,SAAS,EAAE,CAAC,OAAO,CAAC;YAC3C,GAAG,EAAE,8CAA8C;YACnD,IAAI,EAAE,CAAC,UAAU,CAAC;SACnB,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,UAAU,oBAAoB,EAAE,CAAC;QACxE,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,yBAAyB,GAC7B,CAAC,KAAK;YACN,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;gBACjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACzC,IAAI,yBAAyB;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACnD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,0BAA0B,UAAU,gBAAgB;SAC7D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAEhC,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC;YACvC,GAAG,EAAE,gFAAgF;YACrF,IAAI,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC;SAC1B,CAAC,CAAC;QACH,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,uCAAuC,KAAK,GAAG;aACxD,CAAC;QACJ,CAAC;QACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,SAAS,UAAU,mCAAmC,KAAK,GAAG;aACvE,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,uCAAuC,KAAK,GAAG;SACxD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mCAAmC,CACvD,UAAuC;IAEvC,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,OAAO,MAAM,kCAAkC,CAC7C,UAAU,CAAC,QAAQ,CAAC,KAAK,EACzB,UAAU,CAAC,IAAI,CAChB,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,qDAAqD;aAC9D,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;IAC1D,MAAM,SAAS,GACb,cAAc,KAAK,SAAS;QAC1B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK;QACxD,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;IAChC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,6BAA6B,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACvE,OAAO,QAAQ,CAAC,EAAE;QAChB,CAAC,CAAC;YACE,EAAE,EAAE,IAAI;YACR,QAAQ,EAAE;gBACR,SAAS;gBACT,KAAK;gBACL,UAAU,EAAE,SAAS,CAAC,WAAW,EAAE;aACpC;SACF;QACH,CAAC,CAAC,QAAQ,CAAC;AACf,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,IAAoD,EACpD,GAAG,GAAG,IAAI,IAAI,EAAE;IAEhB,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAChD,IAAI,CAAC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;IACnD,OAAO,CACL,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC1B,GAAG,CAAC,OAAO,EAAE,GAAG,SAAS,GAAG,uBAAuB,CACpD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,GAEzC;IACC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC9B,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC,MAAM,KAAK,aAAa,IAAI,KAAK,CAAC,MAAM,KAAK,aAAa;gBACrE,CAAC,CAAC,KAAK,CAAC,MAAM;gBACd,CAAC,CAAC,IAAI,CAAC;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;IACnE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CAAC,KAAwB;IAC/C,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,gCAAgC,CACvC,UAAuC,EACvC,OAAoC;IAEpC,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IACjD,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,qDAAqD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,wEAAwE,CAChJ,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IAC3D,OAAO,GAAG,UAAU,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACjF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAuC,EACvC,IAA8B;IAE9B,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAC/B,0EAA0E;IAC1E,wEAAwE;IACxE,uEAAuE;IACvE,IAAI,SAAS,GAAkB,IAAI,CAAC;IACpC,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,kBAAkB,CAAC;YACnC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK;YAChC,UAAU,EAAE,UAAU,CAAC,IAAI;YAC3B,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI;YAC9B,KAAK,EAAE,+BAA+B,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAC/D,CAAC,CAAC,cAAc;gBAChB,CAAC,CAAC,UAAU;YACd,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI;SAC7B,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,sDAAsD,UAAU,CAAC,IAAI,oBAAoB,EACzF,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,IAAI,MAAqC,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,2BAA2B,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,gBAAgB,CACpB,SAAS,EACT,OAAO,EACP,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;QACF,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,yEAAyE;IACzE,yEAAyE;IACzE,MAAM,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC7C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAC5B,SAAwB,EACxB,QAAgB,EAChB,KAAa;IAEb,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,IAAI,CAAC;QACH,MAAM,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,yCAAyC,QAAQ,WAAW,SAAS,GAAG,EACxE,GAAG,CACJ,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,SAAwB,EACxB,MAA2B,EAC3B,KAAc;IAEd,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,IAAI,CAAC;QACH,MAAM,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,sCAAsC,SAAS,OAAO,MAAM,GAAG,EAC/D,GAAG,CACJ,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,2BAA2B,CACxC,OAAuC,EACvC,IAA8B,EAC9B,SAAwB;IAExB,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GACtE,OAAO,CAAC;IAEV,OAAO,qBAAqB,CAC1B;QACE,GAAG,OAAO,CAAC,cAAc;QACzB,SAAS,EAAE,UAAU;QACrB,KAAK;KACN,EACD,KAAK,IAAI,EAAE;QACT,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAChD,gCAAgC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAE1D,MAAM,sBAAsB,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC,UAAU,CAAC,CAAC;QACtE,MAAM,gBAAgB,GAAG,sBAAsB;YAC7C,CAAC,CAAC,eAAe,CAAC;gBACd,GAAG,sBAAsB;gBACzB,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;aACpC,CAAC;YACJ,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,OAAO,GAAG,gBAAgB;YAC9B,CAAC,CAAC,gBAAgB,CAAC,EAAE,GAAG,WAAW,EAAE,CAAC;YACtC,CAAC,CAAC,WAAW,CAAC;QAChB,MAAM,cAAc,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,wBAAwB,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;QAEzE,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAC1D,MAAM,MAAM,GACV,IAAI,CAAC,MAAM;YACX,CAAC,MAAM,aAAa,CAAC;gBACnB,MAAM,EAAE,UAAU,IAAI,IAAI,CAAC,MAAM;gBACjC,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB,CAAC,CAAC,CAAC;QACN,MAAM,cAAc,GAClB,UAAU,CAAC,IAAI,CAAC,KAAK;YACrB,IAAI,CAAC,KAAK;YACV,CAAC,MAAM,uBAAuB,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9D,MAAM,CAAC,YAAY,CAAC;QACtB,MAAM,KAAK,GAAG,uBAAuB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAC9D,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QACtE,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAEnD,sEAAsE;QACtE,qEAAqE;QACrE,qEAAqE;QACrE,mEAAmE;QACnE,kEAAkE;QAClE,oEAAoE;QACpE,kEAAkE;QAClE,mDAAmD;QACnD,EAAE;QACF,gEAAgE;QAChE,wEAAwE;QACxE,8DAA8D;QAC9D,sEAAsE;QACtE,qEAAqE;QACrE,MAAM,aAAa,GAAG,uBAAuB,CAAC,SAAS,EAAE;YACvD,gBAAgB,EAAE,IAAI;YACtB,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAEV,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACtB,IAAI,YAAY,GAAG,EAAE,CAAC;QACtB,IAAI,cAAc,GAAyC,IAAI,CAAC;QAEhE,oEAAoE;QACpE,8DAA8D;QAC9D,kEAAkE;QAClE,+DAA+D;QAC/D,wEAAwE;QACxE,wEAAwE;QACxE,uEAAuE;QACvE,oEAAoE;QACpE,qEAAqE;QACrE,sEAAsE;QACtE,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE;YAC3C,YAAY,EAAE,YAAY;SAC3B,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,0BAA0B,UAAU,CAAC,IAAI,WAAW,KAAK,qDAAqD,CAC/G,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,SAAS,GAAG,QAAQ,CACxB,KAAK,EACL,MAAM,CAAC,EAAE,EACT,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;gBACrB,QAAQ,CAAC,OAAO,GAAG,MAAM,iCAAiC,CACxD;oBACE,MAAM;oBACN,KAAK;oBACL,YAAY;oBACZ,KAAK;oBACL,cAAc;oBACd,QAAQ,EAAE;wBACR;4BACE,IAAI,EAAE,MAAM;4BACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;yBAC1C;qBACF;oBACD,OAAO;oBACP,IAAI;oBACJ,MAAM;oBACN,QAAQ,EAAE,MAAM,CAAC,EAAE;oBACnB,UAAU;oBACV,KAAK;oBACL,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,UAAU,EAAE,OAAO,CAAC,gBAAgB;oBACpC,KAAK;iBACN,EACD,aAAa,EACb,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAC7B,CAAC;YACJ,CAAC,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;gBACZ,IAAI,cAAc,EAAE,CAAC;oBACnB,YAAY,CAAC,cAAc,CAAC,CAAC;oBAC7B,cAAc,GAAG,IAAI,CAAC;gBACxB,CAAC;gBACD,MAAM,YAAY,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC;gBACpD,IAAI,YAAY,EAAE,CAAC;oBACjB,MAAM,CACJ,IAAI,KAAK,CACP,uDAAuD,YAAY,GAAG,CACvE,CACF,CAAC;oBACF,OAAO;gBACT,CAAC;gBACD,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBAC/B,MAAM,CACJ,IAAI,KAAK,CACP,4CAA4C,GAAG,CAAC,MAAM,EAAE,CACzD,CACF,CAAC;oBACF,OAAO;gBACT,CAAC;gBACD,YAAY,GAAG,uCAAuC,CACpD,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAC/C,CAAC;gBACF,OAAO,EAAE,CAAC;YACZ,CAAC,EACD;gBACE,aAAa;gBACb,kBAAkB,EAAE,IAAI;gBACxB,KAAK;gBACL,UAAU,EAAE,MAAM,CAAC,IAAI;aACxB,CACF,CAAC;YAEF,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC/B,cAAc,GAAG,IAAI,CAAC;gBACtB,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBACnC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;oBAC5D,MAAM,CACJ,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAC7D,CAAC;gBACJ,CAAC;YACH,CAAC,EAAE,8BAA8B,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YACd,IAAI,cAAc,EAAE,CAAC;gBACnB,YAAY,CAAC,cAAc,CAAC,CAAC;gBAC7B,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC/B,IACE,KAAK;YACL,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC;gBACpB,KAAK,CAAC,YAAY,GAAG,CAAC;gBACtB,KAAK,CAAC,eAAe,GAAG,CAAC;gBACzB,KAAK,CAAC,gBAAgB,GAAG,CAAC,CAAC,EAC7B,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;gBAC1D,MAAM,WAAW,CAAC;oBAChB,UAAU;oBACV,WAAW,EAAE,KAAK,CAAC,WAAW;oBAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;oBAChC,eAAe,EAAE,KAAK,CAAC,eAAe;oBACtC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;oBACxC,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,KAAK,EAAE,UAAU;oBACjB,GAAG,EAAE,IAAI,CAAC,KAAK;oBACf,KAAK,EAAE,OAAO,CAAC,UAAU,IAAI,KAAK;iBACnC,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,gEAAgE;YAClE,CAAC;QACH,CAAC;QAED,IACE,YAAY,CAAC,IAAI,EAAE;YACnB,UAAU,CAAC,IAAI,CAAC,gBAAgB;YAChC,UAAU,CAAC,IAAI,CAAC,mBAAmB,EACnC,CAAC;YACD,MAAM,EAAE,iBAAiB,EAAE,GACzB,MAAM,MAAM,CAAC,mCAAmC,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpE,IAAI,CAAC,OAAO,EAAE,mBAAmB,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CACb,4CAA4C,UAAU,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAC/E,CAAC;YACJ,CAAC;YACD,MAAM,OAAO,CAAC,mBAAmB,CAC/B,OAAO,CAAC,mBAAmB,CAAC,YAAY,CAAC,EACzC;gBACE,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,mBAAmB;gBAChD,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,iBAAiB,IAAI,IAAI;gBACpD,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,gBAAgB;aAC3C,CACF,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACjC,CAAC,CACF,CAAC;AACJ,CAAC","sourcesContent":["import { collectFinalResponseTextFromAgentEvents } from \"../a2a/response-text.js\";\nimport type { ActionAutomationContext, ActionCaller } from \"../action.js\";\nimport {\n getStoredModelForEngine,\n normalizeModelForEngine,\n resolveEngine,\n} from \"../agent/engine/index.js\";\nimport type { AgentEngine } from \"../agent/engine/types.js\";\nimport {\n actionsToEngineTools,\n filterInitialEngineTools,\n getOwnerActiveApiKey,\n runAgentLoop,\n type ActionEntry,\n} from \"../agent/production-agent.js\";\nimport { runAgentLoopDirectWithSoftTimeout } from \"../agent/run-loop-with-resume.js\";\nimport { resolveRunSoftTimeoutMs, startRun } from \"../agent/run-manager.js\";\nimport { claimBackgroundRun, insertRun } from \"../agent/run-store.js\";\nimport { attachToolSearch } from \"../agent/tool-search.js\";\nimport {\n resolveAutomationExecutionIdentity,\n type AutomationExecutionIdentity,\n} from \"../automations/service.js\";\nimport { createThread } from \"../chat-threads/store.js\";\nimport { queryOrgMembers } from \"../org/context.js\";\nimport {\n organizationIdFromResourceOwner,\n type Resource,\n} from \"../resources/store.js\";\nimport {\n runWithRequestContext,\n type RequestContext,\n} from \"../server/request-context.js\";\nimport type { JobFrontmatter } from \"./frontmatter.js\";\nimport {\n attachAutomationRunThread,\n finishAutomationRun,\n startAutomationRun,\n} from \"./run-history.js\";\n\nconst BACKGROUND_RUN_STUCK_MS = 10 * 60_000;\nconst BACKGROUND_RUN_HARD_TIMEOUT_MS = 5 * 60_000;\n\nexport interface BackgroundAutomationContext {\n name: string;\n meta: JobFrontmatter;\n body: string;\n resource: Resource;\n}\n\nexport interface BackgroundAutomationDeps {\n getActions: (\n automation?: BackgroundAutomationContext,\n ) => Record<string, ActionEntry>;\n getSystemPrompt: (owner: string) => Promise<string>;\n getInitialToolNames?: (\n automation?: BackgroundAutomationContext,\n ) => string[] | undefined;\n engine?: AgentEngine;\n apiKey?: string;\n model?: string;\n appId?: string;\n}\n\nexport interface BackgroundAutomationRunOptions {\n automation: BackgroundAutomationContext;\n ownerEmail: string;\n orgId?: string;\n prompt: string;\n threadTitle: string;\n runIdPrefix: string;\n usageLabel: string;\n usageRefId?: string;\n requestContext?: Omit<RequestContext, \"userEmail\" | \"orgId\">;\n actionCaller?: ActionCaller;\n actionAutomation?: ActionAutomationContext;\n}\n\nexport interface BackgroundAutomationRunResult {\n responseText: string;\n runId: string;\n}\n\nexport type AutomationIdentityValidation =\n | { ok: true }\n | { ok: false; reason: string };\n\nexport type BackgroundAutomationIdentityResult =\n | { ok: true; identity: AutomationExecutionIdentity }\n | { ok: false; reason: string };\n\n/**\n * A persisted background run must not outlive its execution identity.\n * Organization runs fail closed when membership state cannot be read. A\n * brand-new personal install without auth tables remains a distinct\n * not-applicable case so local/CLI jobs keep working before auth is configured.\n */\nexport async function validateAutomationRunIdentity(\n ownerEmail: string,\n orgId?: string,\n): Promise<AutomationIdentityValidation> {\n if (\n ownerEmail === \"__shared__\" ||\n organizationIdFromResourceOwner(ownerEmail)\n ) {\n return { ok: true };\n }\n\n try {\n const { getDbExec } = await import(\"../db/client.js\");\n const userResult = await getDbExec().execute({\n sql: `SELECT 1 FROM \"user\" WHERE email = ? LIMIT 1`,\n args: [ownerEmail],\n });\n if (!userResult.rows || userResult.rows.length === 0) {\n return { ok: false, reason: `user \"${ownerEmail}\" no longer exists` };\n }\n } catch (error) {\n const message =\n error instanceof Error ? error.message.toLowerCase() : String(error);\n const authTablesAreUnconfigured =\n !orgId &&\n (message.includes(\"does not exist\") ||\n message.includes(\"no such table\") ||\n message.includes(\"undefined table\"));\n if (authTablesAreUnconfigured) return { ok: true };\n return {\n ok: false,\n reason: `could not verify user \"${ownerEmail}\" for this run`,\n };\n }\n\n if (!orgId) return { ok: true };\n\n try {\n const memberRows = await queryOrgMembers({\n sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = LOWER(?) LIMIT 1`,\n args: [orgId, ownerEmail],\n });\n if (memberRows === null) {\n return {\n ok: false,\n reason: `could not verify membership in org \"${orgId}\"`,\n };\n }\n if (memberRows.length === 0) {\n return {\n ok: false,\n reason: `user \"${ownerEmail}\" is no longer a member of org \"${orgId}\"`,\n };\n }\n return { ok: true };\n } catch {\n return {\n ok: false,\n reason: `could not verify membership in org \"${orgId}\"`,\n };\n }\n}\n\nexport async function resolveBackgroundAutomationIdentity(\n automation: BackgroundAutomationContext,\n): Promise<BackgroundAutomationIdentityResult> {\n if (automation.meta.triggerType) {\n try {\n return await resolveAutomationExecutionIdentity(\n automation.resource.owner,\n automation.meta,\n );\n } catch {\n return {\n ok: false,\n reason: \"Could not verify the automation execution identity.\",\n };\n }\n }\n\n const effectiveRunAs = automation.meta.runAs ?? \"creator\";\n const userEmail =\n effectiveRunAs === \"creator\"\n ? automation.meta.createdBy || automation.resource.owner\n : automation.resource.owner;\n const orgId = automation.meta.orgId ?? undefined;\n const validity = await validateAutomationRunIdentity(userEmail, orgId);\n return validity.ok\n ? {\n ok: true,\n identity: {\n userEmail,\n orgId,\n eventOwner: userEmail.toLowerCase(),\n },\n }\n : validity;\n}\n\nexport function isBackgroundAutomationRunActive(\n meta: Pick<JobFrontmatter, \"lastRun\" | \"lastStatus\">,\n now = new Date(),\n): boolean {\n if (meta.lastStatus !== \"running\") return false;\n if (!meta.lastRun) return false;\n const startedAt = new Date(meta.lastRun).getTime();\n return (\n Number.isFinite(startedAt) &&\n now.getTime() - startedAt < BACKGROUND_RUN_STUCK_MS\n );\n}\n\n/**\n * A soft-timeout/no-progress checkpoint is a continuation boundary, not a\n * successful finish. Only the last terminal event decides whether an\n * in-invocation resume recovered from the boundary.\n */\nexport function backgroundRunCutOffReason(run: {\n events?: readonly { event: { type: string; reason?: string } }[];\n}): string | null {\n const events = run.events ?? [];\n for (let i = events.length - 1; i >= 0; i--) {\n const event = events[i].event;\n if (event.type === \"auto_continue\") {\n return event.reason === \"run_timeout\" || event.reason === \"no_progress\"\n ? event.reason\n : null;\n }\n if (event.type === \"done\" || event.type === \"error\") return null;\n }\n return null;\n}\n\nfunction uniqueToolNames(names: readonly string[]): string[] {\n return [...new Set(names)];\n}\n\nfunction assertRequestedMcpToolsAvailable(\n automation: BackgroundAutomationContext,\n actions: Record<string, ActionEntry>,\n): void {\n const requested = automation.meta.mcpTools ?? [];\n const missing = requested.filter((toolName) => !actions[toolName]);\n if (missing.length > 0) {\n throw new Error(\n `Configured MCP tools are unavailable in this run: ${missing.join(\", \")}. Reconnect the MCP server or update the automation's capability list.`,\n );\n }\n}\n\nfunction createRunId(prefix: string): string {\n const safePrefix = prefix.replace(/[^a-zA-Z0-9._-]/g, \"-\");\n return `${safePrefix}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n}\n\nexport async function runBackgroundAutomation(\n options: BackgroundAutomationRunOptions,\n deps: BackgroundAutomationDeps,\n): Promise<BackgroundAutomationRunResult> {\n const { automation } = options;\n // Bookkeeping, so it must not gate the work it describes: a history table\n // that cannot be written should cost us the record, not the automation.\n // Everything downstream tolerates a null id by skipping its own write.\n let historyId: string | null = null;\n try {\n historyId = await startAutomationRun({\n owner: automation.resource.owner,\n automation: automation.name,\n path: automation.resource.path,\n scope: organizationIdFromResourceOwner(automation.resource.owner)\n ? \"organization\"\n : \"personal\",\n orgId: options.orgId ?? null,\n });\n } catch (err) {\n console.error(\n `[automations] Could not open a history record for \"${automation.name}\"; running anyway:`,\n err,\n );\n }\n\n let result: BackgroundAutomationRunResult;\n try {\n result = await executeBackgroundAutomation(options, deps, historyId);\n } catch (err) {\n await recordRunOutcome(\n historyId,\n \"error\",\n err instanceof Error ? err.message : String(err),\n );\n throw err;\n }\n // Outside the try: history is bookkeeping about the run, so a failure to\n // write it must not turn a completed automation into a reported failure.\n await recordRunOutcome(historyId, \"success\");\n return result;\n}\n\n/**\n * Link the run to its agent thread. Bookkeeping again: the automation is\n * already executing by this point, so a failed write costs the cross-reference\n * in the history view, not the run.\n */\nasync function recordRunThread(\n historyId: string | null,\n threadId: string,\n runId: string,\n): Promise<void> {\n if (!historyId) return;\n try {\n await attachAutomationRunThread(historyId, threadId, runId);\n } catch (err) {\n console.error(\n `[automations] Could not attach thread ${threadId} to run ${historyId}:`,\n err,\n );\n }\n}\n\nasync function recordRunOutcome(\n historyId: string | null,\n status: \"success\" | \"error\",\n error?: string,\n): Promise<void> {\n if (!historyId) return;\n try {\n await finishAutomationRun(historyId, status, error);\n } catch (err) {\n console.error(\n `[automations] Could not record run ${historyId} as ${status}:`,\n err,\n );\n }\n}\n\nasync function executeBackgroundAutomation(\n options: BackgroundAutomationRunOptions,\n deps: BackgroundAutomationDeps,\n historyId: string | null,\n): Promise<BackgroundAutomationRunResult> {\n const { automation, ownerEmail, orgId, prompt, threadTitle, usageLabel } =\n options;\n\n return runWithRequestContext(\n {\n ...options.requestContext,\n userEmail: ownerEmail,\n orgId,\n },\n async () => {\n const baseActions = deps.getActions(automation);\n assertRequestedMcpToolsAvailable(automation, baseActions);\n\n const configuredInitialTools = deps.getInitialToolNames?.(automation);\n const initialToolNames = configuredInitialTools\n ? uniqueToolNames([\n ...configuredInitialTools,\n ...(automation.meta.mcpTools ?? []),\n ])\n : undefined;\n const actions = initialToolNames\n ? attachToolSearch({ ...baseActions })\n : baseActions;\n const availableTools = actionsToEngineTools(actions);\n const tools = filterInitialEngineTools(availableTools, initialToolNames);\n\n const userApiKey = await getOwnerActiveApiKey(ownerEmail);\n const engine =\n deps.engine ??\n (await resolveEngine({\n apiKey: userApiKey ?? deps.apiKey,\n appId: deps.appId,\n }));\n const modelCandidate =\n automation.meta.model ??\n deps.model ??\n (await getStoredModelForEngine(engine, { appId: deps.appId })) ??\n engine.defaultModel;\n const model = normalizeModelForEngine(engine, modelCandidate);\n const systemPrompt = await deps.getSystemPrompt(ownerEmail);\n const thread = await createThread(ownerEmail, { title: threadTitle });\n const runId = createRunId(options.runIdPrefix);\n await recordRunThread(historyId, thread.id, runId);\n\n // Scheduled work is background work: it has no synchronous serverless\n // caller waiting on it, so it must not inherit the interactive clamp\n // (40s soft timeout, a 30s no-progress backstop at 0.75x that, and 6\n // continuations). A dashboard render or digest legitimately spends\n // minutes across many tool calls, and dies the first time any gap\n // between two of them exceeds 30s — recorded as `no_progress` after\n // several minutes of real work, because the backstop is suspended\n // while a tool is in flight but not between tools.\n //\n // Hardcoded rather than `isInBackgroundFunctionRuntime()` (what\n // webhook-handler.ts uses): a webhook can arrive on either runtime, but\n // a scheduler tick never serves a synchronous request, so the\n // interactive clamp never applies to it. The wider soft ceiling stays\n // bounded by this runner's own BACKGROUND_RUN_HARD_TIMEOUT_MS abort.\n const softTimeoutMs = resolveRunSoftTimeoutMs(undefined, {\n useHostedDefault: true,\n backgroundFunction: true,\n });\n\n const usageRef: {\n current: Awaited<ReturnType<typeof runAgentLoop>> | null;\n } = { current: null };\n let responseText = \"\";\n let hardAbortTimer: ReturnType<typeof setTimeout> | null = null;\n\n // This runner executes in-process, synchronously — there is no HTTP\n // self-dispatch to a separate worker. Self-claim the row into\n // 'background-processing' right away, exactly like a genuine HTTP\n // background worker does immediately after its own insert (see\n // production-agent.ts's `claimBackgroundWorkerRunEarly`). Without this,\n // the row sits at dispatch_mode='background' for its whole life with no\n // worker ever claiming it, which is indistinguishable from a lost HTTP\n // handoff to the unclaimed-background-run sweep — it gets reaped as\n // \"background_worker_never_started\" out from under a still-executing\n // job the moment any single tool call runs past the 25s grace window.\n await insertRun(runId, thread.id, undefined, {\n dispatchMode: \"background\",\n });\n const claimedOwnRun = await claimBackgroundRun(runId);\n if (!claimedOwnRun) {\n throw new Error(\n `Background automation \"${automation.name}\" (run \"${runId}\") could not claim its own freshly-inserted run row`,\n );\n }\n\n await new Promise<void>((resolve, reject) => {\n const activeRun = startRun(\n runId,\n thread.id,\n async (send, signal) => {\n usageRef.current = await runAgentLoopDirectWithSoftTimeout(\n {\n engine,\n model,\n systemPrompt,\n tools,\n availableTools,\n messages: [\n {\n role: \"user\",\n content: [{ type: \"text\", text: prompt }],\n },\n ],\n actions,\n send,\n signal,\n threadId: thread.id,\n ownerEmail,\n orgId,\n actionCaller: options.actionCaller,\n automation: options.actionAutomation,\n runId,\n },\n softTimeoutMs,\n { backgroundFunction: true },\n );\n },\n async (run) => {\n if (hardAbortTimer) {\n clearTimeout(hardAbortTimer);\n hardAbortTimer = null;\n }\n const cutOffReason = backgroundRunCutOffReason(run);\n if (cutOffReason) {\n reject(\n new Error(\n `Background automation was cut off before finishing (${cutOffReason})`,\n ),\n );\n return;\n }\n if (run.status !== \"completed\") {\n reject(\n new Error(\n `Background automation ended with status: ${run.status}`,\n ),\n );\n return;\n }\n responseText = collectFinalResponseTextFromAgentEvents(\n (run.events ?? []).map((entry) => entry.event),\n );\n resolve();\n },\n {\n softTimeoutMs,\n backgroundFunction: true,\n model,\n engineName: engine.name,\n },\n );\n\n hardAbortTimer = setTimeout(() => {\n hardAbortTimer = null;\n if (activeRun.status === \"running\") {\n activeRun.abort.abort(\"background_automation_hard_timeout\");\n reject(\n new Error(\"Background automation timed out after 5 minutes\"),\n );\n }\n }, BACKGROUND_RUN_HARD_TIMEOUT_MS);\n }).finally(() => {\n if (hardAbortTimer) {\n clearTimeout(hardAbortTimer);\n hardAbortTimer = null;\n }\n });\n\n const usage = usageRef.current;\n if (\n usage &&\n (usage.inputTokens > 0 ||\n usage.outputTokens > 0 ||\n usage.cacheReadTokens > 0 ||\n usage.cacheWriteTokens > 0)\n ) {\n try {\n const { recordUsage } = await import(\"../usage/store.js\");\n await recordUsage({\n ownerEmail,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n cacheReadTokens: usage.cacheReadTokens,\n cacheWriteTokens: usage.cacheWriteTokens,\n model: usage.model,\n label: usageLabel,\n app: deps.appId,\n refId: options.usageRefId ?? runId,\n });\n } catch {\n // Usage attribution must not break an otherwise successful run.\n }\n }\n\n if (\n responseText.trim() &&\n automation.meta.deliveryPlatform &&\n automation.meta.deliveryDestination\n ) {\n const { getDefaultAdapter } =\n await import(\"../integrations/adapters/index.js\");\n const adapter = getDefaultAdapter(automation.meta.deliveryPlatform);\n if (!adapter?.sendMessageToTarget) {\n throw new Error(\n `Automation delivery is not supported for ${automation.meta.deliveryPlatform}`,\n );\n }\n await adapter.sendMessageToTarget(\n adapter.formatAgentResponse(responseText),\n {\n destination: automation.meta.deliveryDestination,\n threadRef: automation.meta.deliveryThreadRef ?? null,\n tenantId: automation.meta.deliveryTenantId,\n },\n );\n }\n\n return { responseText, runId };\n },\n );\n}\n"]}
@@ -1,7 +1,21 @@
1
+ /**
2
+ * IANA zone the host process evaluates wall-clock times in. Jobs stored before
3
+ * schedules carried a `timezone` are interpreted here, so their meaning does
4
+ * not silently shift when timezone support is added.
5
+ */
6
+ export declare function serverTimezone(): string;
7
+ export declare function isValidTimezone(timezone: string): boolean;
8
+ /**
9
+ * Resolve the zone a schedule's wall-clock fields are read in. An absent
10
+ * `timezone` means the schedule predates timezone support, so it keeps its
11
+ * original host-relative meaning rather than being reinterpreted as UTC.
12
+ */
13
+ export declare function effectiveTimezone(timezone?: string | null): string;
1
14
  /**
2
15
  * Compute the next occurrence of a cron expression after the given date.
16
+ * `timezone` is the IANA zone the expression's wall-clock fields refer to.
3
17
  */
4
- export declare function nextOccurrence(cronExpr: string, after?: Date): Date;
18
+ export declare function nextOccurrence(cronExpr: string, after?: Date, timezone?: string | null): Date;
5
19
  /**
6
20
  * Validate a cron expression. Returns true if valid.
7
21
  */
@@ -10,5 +24,5 @@ export declare function isValidCron(cronExpr: string): boolean;
10
24
  * Convert a cron expression to a human-readable description.
11
25
  * Handles common patterns; falls back to the raw expression for unusual ones.
12
26
  */
13
- export declare function describeCron(cronExpr: string): string;
27
+ export declare function describeCron(cronExpr: string, timezone?: string | null): string;
14
28
  //# sourceMappingURL=cron.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAMnE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAuFrD"}
1
+ {"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQzD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAElE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,IAAI,EACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GACvB,IAAI,CAON;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GACvB,MAAM,CA4FR"}
package/dist/jobs/cron.js CHANGED
@@ -6,12 +6,46 @@ const ALIAS_MAP = {
6
6
  function normalize(cronExpr) {
7
7
  return ALIAS_MAP[cronExpr.trim().toLowerCase()] ?? cronExpr;
8
8
  }
9
+ /**
10
+ * IANA zone the host process evaluates wall-clock times in. Jobs stored before
11
+ * schedules carried a `timezone` are interpreted here, so their meaning does
12
+ * not silently shift when timezone support is added.
13
+ */
14
+ export function serverTimezone() {
15
+ try {
16
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
17
+ }
18
+ catch {
19
+ return "UTC";
20
+ }
21
+ }
22
+ export function isValidTimezone(timezone) {
23
+ if (!timezone.trim())
24
+ return false;
25
+ try {
26
+ new Intl.DateTimeFormat("en-US", { timeZone: timezone });
27
+ return true;
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
33
+ /**
34
+ * Resolve the zone a schedule's wall-clock fields are read in. An absent
35
+ * `timezone` means the schedule predates timezone support, so it keeps its
36
+ * original host-relative meaning rather than being reinterpreted as UTC.
37
+ */
38
+ export function effectiveTimezone(timezone) {
39
+ return timezone && isValidTimezone(timezone) ? timezone : serverTimezone();
40
+ }
9
41
  /**
10
42
  * Compute the next occurrence of a cron expression after the given date.
43
+ * `timezone` is the IANA zone the expression's wall-clock fields refer to.
11
44
  */
12
- export function nextOccurrence(cronExpr, after) {
45
+ export function nextOccurrence(cronExpr, after, timezone) {
13
46
  const expr = CronExpressionParser.parse(normalize(cronExpr), {
14
47
  currentDate: after ?? new Date(),
48
+ tz: effectiveTimezone(timezone),
15
49
  });
16
50
  const next = expr.next();
17
51
  return next.toDate();
@@ -32,12 +66,15 @@ export function isValidCron(cronExpr) {
32
66
  * Convert a cron expression to a human-readable description.
33
67
  * Handles common patterns; falls back to the raw expression for unusual ones.
34
68
  */
35
- export function describeCron(cronExpr) {
69
+ export function describeCron(cronExpr, timezone) {
36
70
  const normalized = normalize(cronExpr);
37
71
  const parts = normalized.trim().split(/\s+/);
38
72
  if (parts.length !== 5)
39
73
  return cronExpr;
40
74
  const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
75
+ // A bare wall-clock time is ambiguous the moment the host and the reader sit
76
+ // in different zones, so every description carrying a time names its zone.
77
+ const zone = (text) => timezone ? text + " (" + timezone + ")" : text;
41
78
  // Every minute
42
79
  if (normalized === "* * * * *")
43
80
  return "Every minute";
@@ -85,23 +122,23 @@ export function describeCron(cronExpr) {
85
122
  };
86
123
  // Every day at specific time
87
124
  if (dayOfMonth === "*" && month === "*" && dayOfWeek === "*" && time) {
88
- return `Every day at ${time}`;
125
+ return zone(`Every day at ${time}`);
89
126
  }
90
127
  // Weekdays
91
128
  if (dayOfMonth === "*" &&
92
129
  month === "*" &&
93
130
  (dayOfWeek === "1-5" || dayOfWeek === "MON-FRI") &&
94
131
  time) {
95
- return `Every weekday at ${time}`;
132
+ return zone(`Every weekday at ${time}`);
96
133
  }
97
134
  // Specific day of week
98
135
  if (dayOfMonth === "*" && month === "*" && dayOfWeek !== "*" && time) {
99
136
  const days = dayOfWeek.split(",").map((d) => dayNames[d] || d);
100
- return `Every ${days.join(", ")} at ${time}`;
137
+ return zone(`Every ${days.join(", ")} at ${time}`);
101
138
  }
102
139
  // Specific day of month
103
140
  if (dayOfMonth !== "*" && month === "*" && dayOfWeek === "*" && time) {
104
- return `On day ${dayOfMonth} of every month at ${time}`;
141
+ return zone(`On day ${dayOfMonth} of every month at ${time}`);
105
142
  }
106
143
  return cronExpr;
107
144
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"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","sourcesContent":["import { CronExpressionParser } from \"cron-parser\";\n\n// cron-parser v5 mishandles @midnight — normalize it to an equivalent 5-field expression.\nconst ALIAS_MAP: Record<string, string> = {\n \"@midnight\": \"0 0 * * *\",\n};\n\nfunction normalize(cronExpr: string): string {\n return ALIAS_MAP[cronExpr.trim().toLowerCase()] ?? cronExpr;\n}\n\n/**\n * Compute the next occurrence of a cron expression after the given date.\n */\nexport function nextOccurrence(cronExpr: string, after?: Date): Date {\n const expr = CronExpressionParser.parse(normalize(cronExpr), {\n currentDate: after ?? new Date(),\n });\n const next = expr.next();\n return next.toDate();\n}\n\n/**\n * Validate a cron expression. Returns true if valid.\n */\nexport function isValidCron(cronExpr: string): boolean {\n try {\n CronExpressionParser.parse(normalize(cronExpr));\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Convert a cron expression to a human-readable description.\n * Handles common patterns; falls back to the raw expression for unusual ones.\n */\nexport function describeCron(cronExpr: string): string {\n const normalized = normalize(cronExpr);\n const parts = normalized.trim().split(/\\s+/);\n if (parts.length !== 5) return cronExpr;\n\n const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;\n\n // Every minute\n if (normalized === \"* * * * *\") return \"Every minute\";\n\n // Every N minutes\n const minMatch = minute.match(/^\\*\\/(\\d+)$/);\n if (\n minMatch &&\n hour === \"*\" &&\n dayOfMonth === \"*\" &&\n month === \"*\" &&\n dayOfWeek === \"*\"\n ) {\n return `Every ${minMatch[1]} minutes`;\n }\n\n // Every hour\n if (\n minute !== \"*\" &&\n hour === \"*\" &&\n dayOfMonth === \"*\" &&\n month === \"*\" &&\n dayOfWeek === \"*\"\n ) {\n return `Every hour at :${minute.padStart(2, \"0\")}`;\n }\n\n // Build time string\n const formatTime = (h: string, m: string): string => {\n if (h === \"*\") return \"\";\n const hours = h.split(\",\").map((hh) => {\n const hr = parseInt(hh, 10);\n const ampm = hr >= 12 ? \"PM\" : \"AM\";\n const hr12 = hr === 0 ? 12 : hr > 12 ? hr - 12 : hr;\n const min = m === \"0\" || m === \"00\" ? \"\" : `:${m.padStart(2, \"0\")}`;\n return `${hr12}${min} ${ampm}`;\n });\n return hours.join(\" and \");\n };\n\n const time = formatTime(hour, minute);\n\n // Day of week mapping\n const dayNames: Record<string, string> = {\n \"0\": \"Sunday\",\n \"1\": \"Monday\",\n \"2\": \"Tuesday\",\n \"3\": \"Wednesday\",\n \"4\": \"Thursday\",\n \"5\": \"Friday\",\n \"6\": \"Saturday\",\n \"7\": \"Sunday\",\n };\n\n // Every day at specific time\n if (dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\" && time) {\n return `Every day at ${time}`;\n }\n\n // Weekdays\n if (\n dayOfMonth === \"*\" &&\n month === \"*\" &&\n (dayOfWeek === \"1-5\" || dayOfWeek === \"MON-FRI\") &&\n time\n ) {\n return `Every weekday at ${time}`;\n }\n\n // Specific day of week\n if (dayOfMonth === \"*\" && month === \"*\" && dayOfWeek !== \"*\" && time) {\n const days = dayOfWeek.split(\",\").map((d) => dayNames[d] || d);\n return `Every ${days.join(\", \")} at ${time}`;\n }\n\n // Specific day of month\n if (dayOfMonth !== \"*\" && month === \"*\" && dayOfWeek === \"*\" && time) {\n return `On day ${dayOfMonth} of every month at ${time}`;\n }\n\n return cronExpr;\n}\n"]}
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"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","sourcesContent":["import { CronExpressionParser } from \"cron-parser\";\n\n// cron-parser v5 mishandles @midnight — normalize it to an equivalent 5-field expression.\nconst ALIAS_MAP: Record<string, string> = {\n \"@midnight\": \"0 0 * * *\",\n};\n\nfunction normalize(cronExpr: string): string {\n return ALIAS_MAP[cronExpr.trim().toLowerCase()] ?? cronExpr;\n}\n\n/**\n * IANA zone the host process evaluates wall-clock times in. Jobs stored before\n * schedules carried a `timezone` are interpreted here, so their meaning does\n * not silently shift when timezone support is added.\n */\nexport function serverTimezone(): string {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\";\n } catch {\n return \"UTC\";\n }\n}\n\nexport function isValidTimezone(timezone: string): boolean {\n if (!timezone.trim()) return false;\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: timezone });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve the zone a schedule's wall-clock fields are read in. An absent\n * `timezone` means the schedule predates timezone support, so it keeps its\n * original host-relative meaning rather than being reinterpreted as UTC.\n */\nexport function effectiveTimezone(timezone?: string | null): string {\n return timezone && isValidTimezone(timezone) ? timezone : serverTimezone();\n}\n\n/**\n * Compute the next occurrence of a cron expression after the given date.\n * `timezone` is the IANA zone the expression's wall-clock fields refer to.\n */\nexport function nextOccurrence(\n cronExpr: string,\n after?: Date,\n timezone?: string | null,\n): Date {\n const expr = CronExpressionParser.parse(normalize(cronExpr), {\n currentDate: after ?? new Date(),\n tz: effectiveTimezone(timezone),\n });\n const next = expr.next();\n return next.toDate();\n}\n\n/**\n * Validate a cron expression. Returns true if valid.\n */\nexport function isValidCron(cronExpr: string): boolean {\n try {\n CronExpressionParser.parse(normalize(cronExpr));\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Convert a cron expression to a human-readable description.\n * Handles common patterns; falls back to the raw expression for unusual ones.\n */\nexport function describeCron(\n cronExpr: string,\n timezone?: string | null,\n): string {\n const normalized = normalize(cronExpr);\n const parts = normalized.trim().split(/\\s+/);\n if (parts.length !== 5) return cronExpr;\n\n const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;\n\n // A bare wall-clock time is ambiguous the moment the host and the reader sit\n // in different zones, so every description carrying a time names its zone.\n const zone = (text: string) =>\n timezone ? text + \" (\" + timezone + \")\" : text;\n\n // Every minute\n if (normalized === \"* * * * *\") return \"Every minute\";\n\n // Every N minutes\n const minMatch = minute.match(/^\\*\\/(\\d+)$/);\n if (\n minMatch &&\n hour === \"*\" &&\n dayOfMonth === \"*\" &&\n month === \"*\" &&\n dayOfWeek === \"*\"\n ) {\n return `Every ${minMatch[1]} minutes`;\n }\n\n // Every hour\n if (\n minute !== \"*\" &&\n hour === \"*\" &&\n dayOfMonth === \"*\" &&\n month === \"*\" &&\n dayOfWeek === \"*\"\n ) {\n return `Every hour at :${minute.padStart(2, \"0\")}`;\n }\n\n // Build time string\n const formatTime = (h: string, m: string): string => {\n if (h === \"*\") return \"\";\n const hours = h.split(\",\").map((hh) => {\n const hr = parseInt(hh, 10);\n const ampm = hr >= 12 ? \"PM\" : \"AM\";\n const hr12 = hr === 0 ? 12 : hr > 12 ? hr - 12 : hr;\n const min = m === \"0\" || m === \"00\" ? \"\" : `:${m.padStart(2, \"0\")}`;\n return `${hr12}${min} ${ampm}`;\n });\n return hours.join(\" and \");\n };\n\n const time = formatTime(hour, minute);\n\n // Day of week mapping\n const dayNames: Record<string, string> = {\n \"0\": \"Sunday\",\n \"1\": \"Monday\",\n \"2\": \"Tuesday\",\n \"3\": \"Wednesday\",\n \"4\": \"Thursday\",\n \"5\": \"Friday\",\n \"6\": \"Saturday\",\n \"7\": \"Sunday\",\n };\n\n // Every day at specific time\n if (dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\" && time) {\n return zone(`Every day at ${time}`);\n }\n\n // Weekdays\n if (\n dayOfMonth === \"*\" &&\n month === \"*\" &&\n (dayOfWeek === \"1-5\" || dayOfWeek === \"MON-FRI\") &&\n time\n ) {\n return zone(`Every weekday at ${time}`);\n }\n\n // Specific day of week\n if (dayOfMonth === \"*\" && month === \"*\" && dayOfWeek !== \"*\" && time) {\n const days = dayOfWeek.split(\",\").map((d) => dayNames[d] || d);\n return zone(`Every ${days.join(\", \")} at ${time}`);\n }\n\n // Specific day of month\n if (dayOfMonth !== \"*\" && month === \"*\" && dayOfWeek === \"*\" && time) {\n return zone(`On day ${dayOfMonth} of every month at ${time}`);\n }\n\n return cronExpr;\n}\n"]}
@@ -10,10 +10,22 @@ export type JobExecutionMode = "agentic" | "deterministic";
10
10
  export interface JobFrontmatter {
11
11
  schedule: string;
12
12
  enabled: boolean;
13
+ /**
14
+ * IANA zone the cron fields are read in. Absent means the schedule predates
15
+ * timezone support and keeps its original host-relative meaning.
16
+ */
17
+ timezone?: string;
13
18
  createdBy?: string;
14
19
  orgId?: string;
15
20
  runAs?: "creator" | "shared";
21
+ /** Last time the automation actually started executing. */
16
22
  lastRun?: string;
23
+ /**
24
+ * Last time a tick evaluated this automation and declined to run it. Kept
25
+ * distinct from `lastRun` so a blocked automation cannot report a run it
26
+ * never performed.
27
+ */
28
+ lastCheck?: string;
17
29
  lastStatus?: JobLastStatus;
18
30
  lastError?: string;
19
31
  nextRun?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/jobs/frontmatter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AACxE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,OAAO,CAAC;AAClD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,eAAe,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oEAAoE;IACpE,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,KAAK,GAAG,YAAY,CAAC;IAC3B,sBAAsB,EAAE,OAAO,CAAC;IAChC,WAAW,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,yBAAyB,CAAC;CAC3C;AAOD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAgCzE;AAwGD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,cAAc,GACnB,yBAAyB,CAO3B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CA2BnE;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,GACd,yBAAyB,CAE3B;AAgBD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,MAAM,GACX,MAAM,CA0CR"}
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/jobs/frontmatter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AACxE,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,OAAO,CAAC;AAClD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,eAAe,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oEAAoE;IACpE,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,KAAK,GAAG,YAAY,CAAC;IAC3B,sBAAsB,EAAE,OAAO,CAAC;IAChC,WAAW,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,yBAAyB,CAAC;CAC3C;AAOD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAgCzE;AA8GD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,cAAc,GACnB,yBAAyB,CAO3B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CA2BnE;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,GACd,yBAAyB,CAE3B;AAgBD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,MAAM,GACX,MAAM,CA4CR"}
@@ -62,6 +62,9 @@ function parseKnownField(meta, key, rawValue) {
62
62
  case "enabled":
63
63
  meta.enabled = value !== "false";
64
64
  break;
65
+ case "timezone":
66
+ meta.timezone = value || undefined;
67
+ break;
65
68
  case "createdBy":
66
69
  meta.createdBy = value;
67
70
  break;
@@ -75,6 +78,9 @@ function parseKnownField(meta, key, rawValue) {
75
78
  case "lastRun":
76
79
  meta.lastRun = value;
77
80
  break;
81
+ case "lastCheck":
82
+ meta.lastCheck = value;
83
+ break;
78
84
  case "lastStatus":
79
85
  meta.lastStatus = value;
80
86
  break;
@@ -196,7 +202,9 @@ export function buildJobResourceContent(meta, body) {
196
202
  pushString(lines, "orgId", meta.orgId);
197
203
  if (meta.runAs)
198
204
  lines.push(`runAs: ${meta.runAs}`);
205
+ pushString(lines, "timezone", meta.timezone);
199
206
  pushString(lines, "lastRun", meta.lastRun);
207
+ pushString(lines, "lastCheck", meta.lastCheck);
200
208
  if (meta.lastStatus)
201
209
  lines.push(`lastStatus: ${meta.lastStatus}`);
202
210
  pushString(lines, "lastError", meta.lastError);