@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.
- package/corpus/README.md +3 -3
- package/corpus/core/CHANGELOG.md +113 -0
- package/corpus/core/package.json +3 -2
- package/corpus/core/src/automations/service.ts +41 -4
- package/corpus/core/src/cli/mcp-config-writers.ts +27 -21
- package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +187 -85
- package/corpus/core/src/client/agent-page/AutomationDetailsDialog.tsx +208 -0
- package/corpus/core/src/client/agent-page/AutomationScheduleDialog.tsx +180 -0
- package/corpus/core/src/client/agent-page/TimezoneSelect.tsx +241 -0
- package/corpus/core/src/client/agent-page/use-jobs.ts +50 -10
- package/corpus/core/src/client/org/OrgSwitcher.tsx +26 -0
- package/corpus/core/src/client/settings/AccountSettingsCard.tsx +35 -31
- package/corpus/core/src/client/settings/SchedulingTimezoneField.tsx +71 -0
- package/corpus/core/src/client/settings/SettingsRow.tsx +113 -0
- package/corpus/core/src/client/settings/agent-settings-search.ts +2 -1
- package/corpus/core/src/client/settings/index.ts +6 -0
- package/corpus/core/src/integrations/identity.ts +2 -12
- package/corpus/core/src/jobs/actions/list-automation-runs.ts +33 -0
- package/corpus/core/src/jobs/actions/list-recurring-jobs.ts +27 -6
- package/corpus/core/src/jobs/actions/manage-recurring-job.ts +41 -9
- package/corpus/core/src/jobs/background-automation-runner.ts +88 -0
- package/corpus/core/src/jobs/cron.ts +52 -6
- package/corpus/core/src/jobs/frontmatter.ts +20 -0
- package/corpus/core/src/jobs/run-history.ts +242 -0
- package/corpus/core/src/jobs/scheduler.ts +73 -18
- package/corpus/core/src/jobs/tools.ts +54 -6
- package/corpus/core/src/localization/actions/get-localization-preference.ts +2 -2
- package/corpus/core/src/localization/actions/set-localization-preference.ts +49 -11
- package/corpus/core/src/localization/default-messages.ts +27 -0
- package/corpus/core/src/localization/shared.ts +39 -6
- package/corpus/core/src/localization/user-timezone.ts +36 -0
- package/corpus/core/src/org/app-roles-handlers.ts +1 -9
- package/corpus/core/src/org/index.ts +2 -0
- package/corpus/core/src/org/membership.ts +18 -0
- package/corpus/core/src/review/actions/create-review-comment.ts +4 -1
- package/corpus/core/src/review/actions/reply-review-comment.ts +4 -1
- package/corpus/core/src/review/index.ts +5 -0
- package/corpus/core/src/review/notifications.ts +163 -0
- package/corpus/core/src/review/types.ts +7 -0
- package/corpus/core/src/server/action-discovery.ts +4 -0
- package/corpus/core/src/server/activity-notifications.ts +174 -0
- package/corpus/core/src/server/app-name.ts +31 -0
- package/corpus/core/src/server/better-auth-instance.ts +4 -4
- package/corpus/core/src/server/email-templates.ts +70 -14
- package/corpus/core/src/server/email.ts +66 -3
- package/corpus/core/src/server/index.ts +10 -0
- package/corpus/core/src/sharing/access.ts +44 -2
- package/corpus/core/src/sharing/index.ts +5 -0
- package/corpus/core/src/sharing/recipients.ts +67 -0
- package/corpus/core/src/triggers/actions/list-automations.ts +27 -8
- package/corpus/core/src/triggers/actions/manage-automation.ts +17 -6
- package/corpus/core/src/triggers/actions.ts +16 -4
- package/corpus/core/src/triggers/dispatcher.ts +44 -30
- package/corpus/core/src/triggers/routes.ts +19 -6
- package/corpus/core/src/vitest-config.ts +68 -0
- package/corpus/core/vitest.config.ts +5 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +37 -53
- package/corpus/templates/analytics/changelog/2026-08-01-new-error-alerts-now-reach-you-by-email-and-a-scheduled-dash.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +43 -0
- package/corpus/templates/analytics/server/lib/error-capture.ts +5 -1
- package/corpus/templates/analytics/vitest.config.ts +16 -12
- package/corpus/templates/assets/actions/refresh-generation-run.ts +3 -0
- package/corpus/templates/assets/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/assets/app/hooks/use-assets-prefs.ts +55 -0
- package/corpus/templates/assets/app/i18n-data.ts +30 -0
- package/corpus/templates/assets/app/routes/settings.tsx +58 -55
- package/corpus/templates/assets/changelog/2026-08-01-get-an-email-when-a-generation-you-started-finishes-or-fails.md +6 -0
- package/corpus/templates/assets/server/lib/generation-run-notifications.ts +89 -0
- package/corpus/templates/assets/server/lib/video-runs.ts +8 -1
- package/corpus/templates/assets/server/routes/_agent-native/assets/user-prefs.get.ts +17 -0
- package/corpus/templates/assets/server/routes/_agent-native/assets/user-prefs.put.ts +36 -0
- package/corpus/templates/assets/shared/assets-user-prefs.ts +10 -0
- package/corpus/templates/assets/vitest.config.ts +16 -12
- package/corpus/templates/brain/app/routes/settings.tsx +15 -15
- package/corpus/templates/brain/vitest.config.ts +16 -12
- package/corpus/templates/calendar/app/pages/Settings.tsx +32 -40
- package/corpus/templates/calendar/changelog/2026-08-01-language-and-appearance-now-sit-together-in-one-preferences-.md +6 -0
- package/corpus/templates/calendar/vitest.config.ts +16 -12
- package/corpus/templates/chat/app/routes/settings.tsx +14 -22
- package/corpus/templates/chat/vitest.config.ts +9 -0
- package/corpus/templates/clips/.agents/skills/video-editing/SKILL.md +31 -0
- package/corpus/templates/clips/AGENTS.md +1 -0
- package/corpus/templates/clips/actions/add-comment.ts +12 -1
- package/corpus/templates/clips/actions/create-meeting.ts +2 -2
- package/corpus/templates/clips/actions/create-recording.ts +2 -2
- package/corpus/templates/clips/actions/finalize-recording.ts +42 -6
- package/corpus/templates/clips/actions/generate-filmstrip.ts +154 -0
- package/corpus/templates/clips/actions/get-recording-player-data.ts +6 -0
- package/corpus/templates/clips/actions/import-loom-recording.ts +2 -2
- package/corpus/templates/clips/actions/lib/ensure-recording-filmstrip.ts +258 -0
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +11 -3
- package/corpus/templates/clips/actions/react-to-comment.ts +13 -0
- package/corpus/templates/clips/actions/react-to-recording.ts +10 -1
- package/corpus/templates/clips/actions/reply-to-comment.ts +12 -1
- package/corpus/templates/clips/actions/stitch-recordings.ts +2 -2
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +152 -23
- package/corpus/templates/clips/app/components/editor/waveform.tsx +237 -75
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +23 -1
- package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +441 -0
- package/corpus/templates/clips/app/components/settings/slack-section.tsx +329 -0
- package/corpus/templates/clips/app/components/settings/types.ts +14 -0
- package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +443 -0
- package/corpus/templates/clips/app/hooks/use-secret-status.ts +69 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +9 -1
- package/corpus/templates/clips/app/lib/video-filmstrip.ts +262 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +165 -1351
- package/corpus/templates/clips/changelog/2026-07-27-saved-clips-now-resume-from-the-last-uploaded-byte-after-an-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-31-editor-timeline-now-shows-video-frames-behind-the-waveform-g.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-31-email-notifications-now-go-out-when-someone-comments-on-or-r.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-31-you-can-now-set-a-default-visibility-for-new-recordings-in-s.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-01-email-notifications-for-comments-and-reactions-now-actually-.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-03-the-desktop-app-now-opens-directly-beneath-its-tray-icon-on-.md +6 -0
- package/corpus/templates/clips/chrome-extension/package.json +1 -0
- package/corpus/templates/clips/chrome-extension/vitest.config.ts +9 -0
- package/corpus/templates/clips/desktop/package.json +1 -0
- package/corpus/templates/clips/desktop/src/app.tsx +17 -1
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +331 -36
- package/corpus/templates/clips/desktop/src/lib/upload-recovery.ts +129 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +815 -15
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +61 -11
- package/corpus/templates/clips/desktop/vitest.config.ts +9 -0
- package/corpus/templates/clips/server/db/schema.ts +17 -0
- package/corpus/templates/clips/server/jobs/media-verification.ts +4 -0
- package/corpus/templates/clips/server/lib/activity-notifications.ts +185 -0
- package/corpus/templates/clips/server/lib/recording-media-cleanup.ts +2 -0
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +46 -9
- package/corpus/templates/clips/server/lib/recordings.ts +24 -0
- package/corpus/templates/clips/server/lib/resumable-session.ts +10 -4
- package/corpus/templates/clips/server/lib/transactional-email-templates.ts +109 -0
- package/corpus/templates/clips/server/lib/upload-interruption.ts +8 -0
- package/corpus/templates/clips/server/lib/upload-lease.ts +50 -4
- package/corpus/templates/clips/server/lib/video-filmstrip-sprite.ts +207 -0
- package/corpus/templates/clips/server/lib/video-remux.ts +13 -4
- package/corpus/templates/clips/server/plugins/db.ts +16 -0
- package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +4 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +123 -36
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +159 -29
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +197 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +193 -39
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/resume.get.ts +191 -12
- package/corpus/templates/clips/shared/clips-ai-prefs.ts +6 -0
- package/corpus/templates/clips/shared/feature-flags.ts +12 -0
- package/corpus/templates/clips/shared/recording-core.ts +4 -0
- package/corpus/templates/clips/vitest.config.ts +23 -19
- package/corpus/templates/content/actions/_database-utils.ts +113 -4
- package/corpus/templates/content/actions/add-comment.ts +15 -1
- package/corpus/templates/content/actions/get-document.ts +84 -3
- package/corpus/templates/content/actions/list-documents.ts +1 -0
- package/corpus/templates/content/app/components/editor/BuilderBodySyncingNotice.tsx +9 -2
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +34 -15
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +55 -13
- package/corpus/templates/content/app/components/editor/body-hydration.ts +12 -6
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +2 -3
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +5 -12
- package/corpus/templates/content/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +16 -27
- package/corpus/templates/content/app/hooks/use-content-prefs.ts +55 -0
- package/corpus/templates/content/app/hooks/use-create-page.ts +3 -6
- package/corpus/templates/content/app/hooks/use-document-properties.ts +9 -16
- package/corpus/templates/content/app/hooks/use-document-versions.ts +3 -3
- package/corpus/templates/content/app/hooks/use-documents.ts +85 -29
- package/corpus/templates/content/app/hooks/use-notion.ts +15 -13
- package/corpus/templates/content/app/i18n-data.ts +72 -1
- package/corpus/templates/content/app/lib/document-query.ts +36 -0
- package/corpus/templates/content/app/routes/_app.settings.tsx +47 -18
- package/corpus/templates/content/changelog/2026-07-30-breadcrumb-menus-now-hide-internal-system-pages.md +6 -0
- package/corpus/templates/content/changelog/2026-08-01-get-an-email-when-someone-comments-on-replies-in-or-mentions.md +6 -0
- package/corpus/templates/content/changelog/2026-08-02-pages-opened-from-a-database-now-keep-that-database-s-fields.md +6 -0
- package/corpus/templates/content/server/lib/comment-notifications.ts +146 -0
- package/corpus/templates/content/server/lib/document-context.ts +11 -6
- package/corpus/templates/content/server/routes/_agent-native/content/user-prefs.get.ts +17 -0
- package/corpus/templates/content/server/routes/_agent-native/content/user-prefs.put.ts +36 -0
- package/corpus/templates/content/shared/api.ts +8 -0
- package/corpus/templates/content/shared/content-user-prefs.ts +11 -0
- package/corpus/templates/content/vitest.config.ts +20 -16
- package/corpus/templates/crm/app/routes/settings.tsx +14 -22
- package/corpus/templates/crm/vitest.config.ts +8 -4
- package/corpus/templates/design/app/routes/settings.tsx +14 -22
- package/corpus/templates/design/changelog/2026-08-01-review-comments-replies-and-mentions-now-send-an-email-to-th.md +6 -0
- package/corpus/templates/design/vitest.config.ts +18 -12
- package/corpus/templates/dispatch/app/routes/settings.tsx +26 -40
- package/corpus/templates/dispatch/vitest.config.ts +11 -7
- package/corpus/templates/factory/app/routes/settings.tsx +14 -22
- package/corpus/templates/factory/vitest.config.ts +9 -0
- package/corpus/templates/forms/app/routes/_app.settings.tsx +14 -22
- package/corpus/templates/forms/vitest.config.ts +27 -23
- package/corpus/templates/macros/app/routes/settings.tsx +14 -22
- package/corpus/templates/macros/vitest.config.ts +16 -12
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +14 -16
- package/corpus/templates/mail/vitest.config.ts +16 -12
- package/corpus/templates/plan/app/routes/settings.tsx +30 -44
- package/corpus/templates/plan/vitest.config.ts +24 -20
- package/corpus/templates/slides/actions/add-slide-comment.ts +12 -1
- package/corpus/templates/slides/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/slides/app/hooks/use-slides-prefs.ts +55 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/routes/settings.tsx +45 -22
- package/corpus/templates/slides/changelog/2026-08-01-get-an-email-when-someone-comments-on-or-replies-in-your-dec.md +6 -0
- package/corpus/templates/slides/server/lib/comment-notifications.ts +182 -0
- package/corpus/templates/slides/server/routes/_agent-native/slides/user-prefs.get.ts +16 -0
- package/corpus/templates/slides/server/routes/_agent-native/slides/user-prefs.put.ts +36 -0
- package/corpus/templates/slides/shared/slides-user-prefs.ts +11 -0
- package/corpus/templates/slides/vitest.config.ts +17 -13
- package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +2 -0
- package/corpus/templates/tasks/app/routes/settings.tsx +14 -22
- package/corpus/templates/tasks/vitest.config.ts +17 -13
- package/corpus/toolkit/CHANGELOG.md +9 -0
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/vitest.config.ts +3 -0
- package/dist/automations/service.d.ts +2 -0
- package/dist/automations/service.d.ts.map +1 -1
- package/dist/automations/service.js +29 -4
- package/dist/automations/service.js.map +1 -1
- package/dist/cli/mcp-config-writers.d.ts.map +1 -1
- package/dist/cli/mcp-config-writers.js +24 -23
- package/dist/cli/mcp-config-writers.js.map +1 -1
- package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
- package/dist/client/agent-page/AgentJobsTab.js +86 -29
- package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
- package/dist/client/agent-page/AutomationDetailsDialog.d.ts +21 -0
- package/dist/client/agent-page/AutomationDetailsDialog.d.ts.map +1 -0
- package/dist/client/agent-page/AutomationDetailsDialog.js +33 -0
- package/dist/client/agent-page/AutomationDetailsDialog.js.map +1 -0
- package/dist/client/agent-page/AutomationScheduleDialog.d.ts +15 -0
- package/dist/client/agent-page/AutomationScheduleDialog.d.ts.map +1 -0
- package/dist/client/agent-page/AutomationScheduleDialog.js +46 -0
- package/dist/client/agent-page/AutomationScheduleDialog.js.map +1 -0
- package/dist/client/agent-page/TimezoneSelect.d.ts +17 -0
- package/dist/client/agent-page/TimezoneSelect.d.ts.map +1 -0
- package/dist/client/agent-page/TimezoneSelect.js +107 -0
- package/dist/client/agent-page/TimezoneSelect.js.map +1 -0
- package/dist/client/agent-page/use-jobs.d.ts +20 -7
- package/dist/client/agent-page/use-jobs.d.ts.map +1 -1
- package/dist/client/agent-page/use-jobs.js +24 -4
- package/dist/client/agent-page/use-jobs.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +8 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +8 -2
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/settings/AccountSettingsCard.d.ts.map +1 -1
- package/dist/client/settings/AccountSettingsCard.js +10 -9
- package/dist/client/settings/AccountSettingsCard.js.map +1 -1
- package/dist/client/settings/SchedulingTimezoneField.d.ts +10 -0
- package/dist/client/settings/SchedulingTimezoneField.d.ts.map +1 -0
- package/dist/client/settings/SchedulingTimezoneField.js +30 -0
- package/dist/client/settings/SchedulingTimezoneField.js.map +1 -0
- package/dist/client/settings/SettingsRow.d.ts +36 -0
- package/dist/client/settings/SettingsRow.d.ts.map +1 -0
- package/dist/client/settings/SettingsRow.js +15 -0
- package/dist/client/settings/SettingsRow.js.map +1 -0
- package/dist/client/settings/agent-settings-search.d.ts.map +1 -1
- package/dist/client/settings/agent-settings-search.js +1 -1
- package/dist/client/settings/agent-settings-search.js.map +1 -1
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -0
- package/dist/client/settings/index.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/identity.d.ts.map +1 -1
- package/dist/integrations/identity.js +2 -11
- package/dist/integrations/identity.js.map +1 -1
- package/dist/jobs/actions/list-automation-runs.d.ts +8 -0
- package/dist/jobs/actions/list-automation-runs.d.ts.map +1 -0
- package/dist/jobs/actions/list-automation-runs.js +29 -0
- package/dist/jobs/actions/list-automation-runs.js.map +1 -0
- package/dist/jobs/actions/list-recurring-jobs.d.ts +2 -0
- package/dist/jobs/actions/list-recurring-jobs.d.ts.map +1 -1
- package/dist/jobs/actions/list-recurring-jobs.js +20 -7
- package/dist/jobs/actions/list-recurring-jobs.js.map +1 -1
- package/dist/jobs/actions/manage-recurring-job.d.ts +2 -0
- package/dist/jobs/actions/manage-recurring-job.js +30 -9
- package/dist/jobs/actions/manage-recurring-job.js.map +1 -1
- package/dist/jobs/background-automation-runner.d.ts.map +1 -1
- package/dist/jobs/background-automation-runner.js +60 -0
- package/dist/jobs/background-automation-runner.js.map +1 -1
- package/dist/jobs/cron.d.ts +16 -2
- package/dist/jobs/cron.d.ts.map +1 -1
- package/dist/jobs/cron.js +43 -6
- package/dist/jobs/cron.js.map +1 -1
- package/dist/jobs/frontmatter.d.ts +12 -0
- package/dist/jobs/frontmatter.d.ts.map +1 -1
- package/dist/jobs/frontmatter.js +8 -0
- package/dist/jobs/frontmatter.js.map +1 -1
- package/dist/jobs/run-history.d.ts +56 -0
- package/dist/jobs/run-history.d.ts.map +1 -0
- package/dist/jobs/run-history.js +169 -0
- package/dist/jobs/run-history.js.map +1 -0
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +51 -18
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/jobs/tools.d.ts.map +1 -1
- package/dist/jobs/tools.js +37 -6
- package/dist/jobs/tools.js.map +1 -1
- package/dist/localization/actions/get-localization-preference.d.ts +1 -2
- package/dist/localization/actions/get-localization-preference.d.ts.map +1 -1
- package/dist/localization/actions/get-localization-preference.js.map +1 -1
- package/dist/localization/actions/set-localization-preference.d.ts +3 -3
- package/dist/localization/actions/set-localization-preference.d.ts.map +1 -1
- package/dist/localization/actions/set-localization-preference.js +33 -8
- package/dist/localization/actions/set-localization-preference.js.map +1 -1
- package/dist/localization/default-messages.d.ts +25 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +25 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/localization/shared.d.ts +16 -1
- package/dist/localization/shared.d.ts.map +1 -1
- package/dist/localization/shared.js +22 -4
- package/dist/localization/shared.js.map +1 -1
- package/dist/localization/user-timezone.d.ts +11 -0
- package/dist/localization/user-timezone.d.ts.map +1 -0
- package/dist/localization/user-timezone.js +31 -0
- package/dist/localization/user-timezone.js.map +1 -0
- package/dist/notifications/routes.d.ts +4 -4
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/app-roles-handlers.d.ts.map +1 -1
- package/dist/org/app-roles-handlers.js +1 -8
- package/dist/org/app-roles-handlers.js.map +1 -1
- package/dist/org/index.d.ts +1 -0
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +1 -0
- package/dist/org/index.js.map +1 -1
- package/dist/org/membership.d.ts +6 -0
- package/dist/org/membership.d.ts.map +1 -0
- package/dist/org/membership.js +16 -0
- package/dist/org/membership.js.map +1 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/review/actions/create-review-comment.d.ts +32 -1
- package/dist/review/actions/create-review-comment.d.ts.map +1 -1
- package/dist/review/actions/create-review-comment.js +3 -1
- package/dist/review/actions/create-review-comment.js.map +1 -1
- package/dist/review/actions/reply-review-comment.d.ts +32 -1
- package/dist/review/actions/reply-review-comment.d.ts.map +1 -1
- package/dist/review/actions/reply-review-comment.js +3 -1
- package/dist/review/actions/reply-review-comment.js.map +1 -1
- package/dist/review/index.d.ts +1 -0
- package/dist/review/index.d.ts.map +1 -1
- package/dist/review/index.js +1 -0
- package/dist/review/index.js.map +1 -1
- package/dist/review/notifications.d.ts +24 -0
- package/dist/review/notifications.d.ts.map +1 -0
- package/dist/review/notifications.js +123 -0
- package/dist/review/notifications.js.map +1 -0
- package/dist/review/types.d.ts +5 -0
- package/dist/review/types.d.ts.map +1 -1
- package/dist/review/types.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +4 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/activity-notifications.d.ts +61 -0
- package/dist/server/activity-notifications.d.ts.map +1 -0
- package/dist/server/activity-notifications.js +103 -0
- package/dist/server/activity-notifications.js.map +1 -0
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/app-name.d.ts +18 -0
- package/dist/server/app-name.d.ts.map +1 -1
- package/dist/server/app-name.js +31 -0
- package/dist/server/app-name.js.map +1 -1
- package/dist/server/better-auth-instance.js +4 -4
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/email-templates.d.ts +12 -0
- package/dist/server/email-templates.d.ts.map +1 -1
- package/dist/server/email-templates.js +57 -14
- package/dist/server/email-templates.js.map +1 -1
- package/dist/server/email.d.ts +12 -0
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +52 -5
- package/dist/server/email.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +32 -2
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/index.d.ts +1 -0
- package/dist/sharing/index.d.ts.map +1 -1
- package/dist/sharing/index.js +1 -0
- package/dist/sharing/index.js.map +1 -1
- package/dist/sharing/recipients.d.ts +31 -0
- package/dist/sharing/recipients.d.ts.map +1 -0
- package/dist/sharing/recipients.js +40 -0
- package/dist/sharing/recipients.js.map +1 -0
- package/dist/templates/chat/app/routes/settings.tsx +14 -22
- package/dist/templates/chat/vitest.config.ts +9 -0
- package/dist/triggers/actions/list-automations.d.ts +2 -0
- package/dist/triggers/actions/list-automations.d.ts.map +1 -1
- package/dist/triggers/actions/list-automations.js +19 -8
- package/dist/triggers/actions/list-automations.js.map +1 -1
- package/dist/triggers/actions/manage-automation.d.ts +6 -0
- package/dist/triggers/actions/manage-automation.js +12 -6
- package/dist/triggers/actions/manage-automation.js.map +1 -1
- package/dist/triggers/actions.d.ts.map +1 -1
- package/dist/triggers/actions.js +15 -4
- package/dist/triggers/actions.js.map +1 -1
- package/dist/triggers/dispatcher.d.ts.map +1 -1
- package/dist/triggers/dispatcher.js +19 -17
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/triggers/routes.d.ts.map +1 -1
- package/dist/triggers/routes.js +6 -6
- package/dist/triggers/routes.js.map +1 -1
- package/dist/vitest-config.d.ts +10 -0
- package/dist/vitest-config.d.ts.map +1 -0
- package/dist/vitest-config.js +55 -0
- package/dist/vitest-config.js.map +1 -0
- package/package.json +5 -4
- package/src/automations/service.ts +41 -4
- package/src/cli/mcp-config-writers.ts +27 -21
- package/src/client/agent-page/AgentJobsTab.tsx +187 -85
- package/src/client/agent-page/AutomationDetailsDialog.tsx +208 -0
- package/src/client/agent-page/AutomationScheduleDialog.tsx +180 -0
- package/src/client/agent-page/TimezoneSelect.tsx +241 -0
- package/src/client/agent-page/use-jobs.ts +50 -10
- package/src/client/org/OrgSwitcher.tsx +26 -0
- package/src/client/settings/AccountSettingsCard.tsx +35 -31
- package/src/client/settings/SchedulingTimezoneField.tsx +71 -0
- package/src/client/settings/SettingsRow.tsx +113 -0
- package/src/client/settings/agent-settings-search.ts +2 -1
- package/src/client/settings/index.ts +6 -0
- package/src/integrations/identity.ts +2 -12
- package/src/jobs/actions/list-automation-runs.ts +33 -0
- package/src/jobs/actions/list-recurring-jobs.ts +27 -6
- package/src/jobs/actions/manage-recurring-job.ts +41 -9
- package/src/jobs/background-automation-runner.ts +88 -0
- package/src/jobs/cron.ts +52 -6
- package/src/jobs/frontmatter.ts +20 -0
- package/src/jobs/run-history.ts +242 -0
- package/src/jobs/scheduler.ts +73 -18
- package/src/jobs/tools.ts +54 -6
- package/src/localization/actions/get-localization-preference.ts +2 -2
- package/src/localization/actions/set-localization-preference.ts +49 -11
- package/src/localization/default-messages.ts +27 -0
- package/src/localization/shared.ts +39 -6
- package/src/localization/user-timezone.ts +36 -0
- package/src/org/app-roles-handlers.ts +1 -9
- package/src/org/index.ts +2 -0
- package/src/org/membership.ts +18 -0
- package/src/review/actions/create-review-comment.ts +4 -1
- package/src/review/actions/reply-review-comment.ts +4 -1
- package/src/review/index.ts +5 -0
- package/src/review/notifications.ts +163 -0
- package/src/review/types.ts +7 -0
- package/src/server/action-discovery.ts +4 -0
- package/src/server/activity-notifications.ts +174 -0
- package/src/server/app-name.ts +31 -0
- package/src/server/better-auth-instance.ts +4 -4
- package/src/server/email-templates.ts +70 -14
- package/src/server/email.ts +66 -3
- package/src/server/index.ts +10 -0
- package/src/sharing/access.ts +44 -2
- package/src/sharing/index.ts +5 -0
- package/src/sharing/recipients.ts +67 -0
- package/src/templates/chat/app/routes/settings.tsx +14 -22
- package/src/templates/chat/vitest.config.ts +9 -0
- package/src/triggers/actions/list-automations.ts +27 -8
- package/src/triggers/actions/manage-automation.ts +17 -6
- package/src/triggers/actions.ts +16 -4
- package/src/triggers/dispatcher.ts +44 -30
- package/src/triggers/routes.ts +19 -6
- package/src/vitest-config.ts +68 -0
package/dist/triggers/actions.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { defineAutomation, deleteAutomation, listAutomationDefinitions, updateAutomation, } from "../automations/service.js";
|
|
12
12
|
import { listEvents } from "../event-bus/index.js";
|
|
13
|
-
import { describeCron } from "../jobs/cron.js";
|
|
13
|
+
import { describeCron, effectiveTimezone } from "../jobs/cron.js";
|
|
14
14
|
import { getIntegrationRequestContext, getRequestOrgId, } from "../server/request-context.js";
|
|
15
15
|
import { refreshEventSubscriptions } from "./dispatcher.js";
|
|
16
16
|
/* ------------------------------------------------------------------ */
|
|
@@ -52,7 +52,10 @@ async function handleList(args, getCurrentUser) {
|
|
|
52
52
|
triggerType: meta.triggerType,
|
|
53
53
|
event: meta.event ?? null,
|
|
54
54
|
schedule: meta.schedule || null,
|
|
55
|
-
|
|
55
|
+
timezone: meta.timezone ? effectiveTimezone(meta.timezone) : null,
|
|
56
|
+
scheduleDescription: meta.schedule
|
|
57
|
+
? describeCron(meta.schedule, effectiveTimezone(meta.timezone))
|
|
58
|
+
: null,
|
|
56
59
|
condition: meta.condition ?? null,
|
|
57
60
|
mode: meta.mode,
|
|
58
61
|
domain: meta.domain ?? null,
|
|
@@ -101,6 +104,7 @@ async function handleDefine(args, getCurrentUser) {
|
|
|
101
104
|
triggerType: automationTriggerType(args.trigger_type),
|
|
102
105
|
body: typeof args.body === "string" ? args.body : "",
|
|
103
106
|
schedule: typeof args.schedule === "string" ? args.schedule : undefined,
|
|
107
|
+
timezone: typeof args.timezone === "string" ? args.timezone : undefined,
|
|
104
108
|
event: typeof args.event === "string" ? args.event : undefined,
|
|
105
109
|
condition: typeof args.condition === "string" ? args.condition : undefined,
|
|
106
110
|
domain: typeof args.domain === "string" ? args.domain : undefined,
|
|
@@ -132,6 +136,7 @@ async function handleDefine(args, getCurrentUser) {
|
|
|
132
136
|
triggerType: definition.meta.triggerType,
|
|
133
137
|
event: definition.meta.event ?? null,
|
|
134
138
|
schedule: definition.meta.schedule || null,
|
|
139
|
+
timezone: definition.meta.timezone ?? null,
|
|
135
140
|
nextRun: definition.meta.nextRun ?? null,
|
|
136
141
|
createdBy: definition.meta.createdBy,
|
|
137
142
|
runAs: definition.meta.runAs,
|
|
@@ -168,6 +173,7 @@ async function handleUpdate(args, getCurrentUser) {
|
|
|
168
173
|
: null,
|
|
169
174
|
body: typeof args.body === "string" ? args.body : undefined,
|
|
170
175
|
schedule: typeof args.schedule === "string" ? args.schedule : undefined,
|
|
176
|
+
timezone: typeof args.timezone === "string" ? args.timezone : undefined,
|
|
171
177
|
model: args.model === undefined
|
|
172
178
|
? undefined
|
|
173
179
|
: typeof args.model === "string"
|
|
@@ -183,6 +189,7 @@ async function handleUpdate(args, getCurrentUser) {
|
|
|
183
189
|
triggerType: definition.meta.triggerType,
|
|
184
190
|
enabled: definition.meta.enabled,
|
|
185
191
|
schedule: definition.meta.schedule || null,
|
|
192
|
+
timezone: definition.meta.timezone ?? null,
|
|
186
193
|
nextRun: definition.meta.nextRun ?? null,
|
|
187
194
|
createdBy: definition.meta.createdBy,
|
|
188
195
|
runAs: definition.meta.runAs,
|
|
@@ -247,8 +254,8 @@ export function createAutomationToolEntries(getCurrentUser) {
|
|
|
247
254
|
|
|
248
255
|
- **list-events**: List all registered event types that automations can subscribe to. Returns event names, descriptions, and payload schemas. Call this BEFORE defining an automation to discover available events.
|
|
249
256
|
- **list**: List all automations (triggers). Shows trigger, status, model, MCP allowlist, and delivery metadata. Optional params: scope, domain, enabled_only.
|
|
250
|
-
- **define**: Create a new automation. IMPORTANT: Always confirm with the user before calling — show them a summary of what will be created. Required params: name, trigger_type, body. Optional: scope, event, schedule, condition, mode, domain, delegated_policy_id, model, mcpTools.
|
|
251
|
-
- **update**: Update an existing automation's settings without changing its creator (enabled, schedule, condition, body, policy, model, MCP allowlist). Required param: name. Use the same scope it was created in.
|
|
257
|
+
- **define**: Create a new automation. IMPORTANT: Always confirm with the user before calling — show them a summary of what will be created. Required params: name, trigger_type, body. Optional: scope, event, schedule, timezone, condition, mode, domain, delegated_policy_id, model, mcpTools.
|
|
258
|
+
- **update**: Update an existing automation's settings without changing its creator (enabled, schedule, timezone, condition, body, policy, model, MCP allowlist). Required param: name. Use the same scope it was created in.
|
|
252
259
|
- **delete**: Delete an automation. Always confirm with the user first. Required param: name.
|
|
253
260
|
- **fire-test**: Fire a test event to validate automations. Emits a test.event.fired event. Optional param: data (JSON string).`,
|
|
254
261
|
parameters: {
|
|
@@ -277,6 +284,10 @@ export function createAutomationToolEntries(getCurrentUser) {
|
|
|
277
284
|
type: "string",
|
|
278
285
|
description: "For event triggers: the event name to subscribe to. Call with action=list-events first to see available events.",
|
|
279
286
|
},
|
|
287
|
+
timezone: {
|
|
288
|
+
type: "string",
|
|
289
|
+
description: "IANA timezone the cron clock time is read in, e.g. 'America/New_York'. Optional; defaults to the user's saved scheduling timezone, then the caller's browser zone. Always pass this when the user names a time of day.",
|
|
290
|
+
},
|
|
280
291
|
schedule: {
|
|
281
292
|
type: "string",
|
|
282
293
|
description: 'For schedule triggers: cron expression. Example: "0 9 * * 1-5" (9am weekdays).',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/triggers/actions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework-level agent actions for the automations system.\n *\n * These are registered as native tools (not template actions) so they're\n * available in every template. The agent uses them to create, list, and\n * manage automations from chat.\n *\n * All six operations are consolidated into a single `manage-automations` tool\n * with an `action` discriminator to keep the tool registry compact.\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport {\n defineAutomation,\n deleteAutomation,\n listAutomationDefinitions,\n updateAutomation,\n type AutomationScope,\n} from \"../automations/service.js\";\nimport { listEvents } from \"../event-bus/index.js\";\nimport { describeCron } from \"../jobs/cron.js\";\nimport {\n getIntegrationRequestContext,\n getRequestOrgId,\n} from \"../server/request-context.js\";\nimport { refreshEventSubscriptions } from \"./dispatcher.js\";\n\n/* ------------------------------------------------------------------ */\n/* Individual action handlers */\n/* ------------------------------------------------------------------ */\n\nasync function handleListEvents(): Promise<string> {\n const events = listEvents();\n if (events.length === 0) {\n return \"No events registered yet. Events are registered by integrations (mail, calendar, clips, etc.).\";\n }\n const lines = events.map((e) => {\n let schemaStr = \"\";\n try {\n const s = e.payloadSchema as any;\n if (s?._zod?.def?.shape) {\n const fields = Object.keys(s._zod.def.shape);\n schemaStr = ` Fields: ${fields.join(\", \")}`;\n }\n } catch {\n // ignore\n }\n const example = e.example\n ? `\\n Example: ${JSON.stringify(e.example)}`\n : \"\";\n return `- **${e.name}**: ${e.description}${schemaStr}${example}`;\n });\n return lines.join(\"\\n\");\n}\n\nasync function handleList(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n const scope = automationScope(args.scope);\n const definitions = await listAutomationDefinitions(\n { userEmail: getCurrentUser(), orgId: getRequestOrgId() },\n scope,\n );\n const automations = definitions\n .filter(({ meta }) => !args.domain || meta.domain === args.domain)\n .filter(({ meta }) => args.enabled_only !== \"true\" || meta.enabled)\n .map(({ name, meta, body, canUpdate }) => ({\n name,\n scope,\n triggerType: meta.triggerType,\n event: meta.event ?? null,\n schedule: meta.schedule || null,\n scheduleDescription: meta.schedule ? describeCron(meta.schedule) : null,\n condition: meta.condition ?? null,\n mode: meta.mode,\n domain: meta.domain ?? null,\n enabled: meta.enabled,\n lastRun: meta.lastRun ?? null,\n lastStatus: meta.lastStatus ?? null,\n lastError: meta.lastError ?? null,\n nextRun: meta.nextRun ?? null,\n createdBy: meta.createdBy ?? null,\n runAs: meta.runAs ?? null,\n model: meta.model ?? null,\n mcpTools: meta.mcpTools ?? [],\n originScopeId: meta.originScopeId ?? null,\n deliveryPlatform: meta.deliveryPlatform ?? null,\n deliveryDestination: meta.deliveryDestination ?? null,\n deliveryThreadRef: meta.deliveryThreadRef ?? null,\n deliveryTenantId: meta.deliveryTenantId ?? null,\n body,\n canUpdate,\n }));\n return JSON.stringify(automations, null, 2);\n}\n\nfunction automationScope(value: unknown): AutomationScope {\n if (value === undefined || value === null || value === \"\") return \"personal\";\n if (value === \"personal\" || value === \"organization\") return value;\n throw new Error('scope must be \"personal\" or \"organization\".');\n}\n\nfunction automationTriggerType(value: unknown): \"schedule\" | \"event\" {\n if (value === \"schedule\" || value === \"event\") return value;\n throw new Error('trigger_type must be \"schedule\" or \"event\".');\n}\n\nasync function handleDefine(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n if (args.mode === \"deterministic\") {\n return (\n \"Error: Deterministic mode was removed — it was never implemented and \" +\n \"automations that set it never fired. Create the automation without \" +\n \"mode (agentic), and describe the exact fixed steps in the automation body.\"\n );\n }\n const integration = getIntegrationRequestContext();\n try {\n const definition = await defineAutomation(\n { userEmail: getCurrentUser(), orgId: getRequestOrgId() },\n {\n name: typeof args.name === \"string\" ? args.name : \"\",\n scope: automationScope(args.scope),\n triggerType: automationTriggerType(args.trigger_type),\n body: typeof args.body === \"string\" ? args.body : \"\",\n schedule: typeof args.schedule === \"string\" ? args.schedule : undefined,\n event: typeof args.event === \"string\" ? args.event : undefined,\n condition:\n typeof args.condition === \"string\" ? args.condition : undefined,\n domain: typeof args.domain === \"string\" ? args.domain : undefined,\n delegatedPolicyId:\n typeof args.delegated_policy_id === \"string\"\n ? args.delegated_policy_id\n : undefined,\n model: typeof args.model === \"string\" ? args.model : undefined,\n mcpTools: args.mcpTools,\n delivery: integration\n ? {\n originScopeId: integration.scopeId,\n platform: integration.incoming.platform,\n destination:\n typeof integration.incoming.platformContext.channelId ===\n \"string\"\n ? integration.incoming.platformContext.channelId\n : undefined,\n threadRef:\n typeof integration.incoming.threadRef === \"string\"\n ? integration.incoming.threadRef\n : undefined,\n tenantId: integration.incoming.tenantId,\n }\n : undefined,\n },\n );\n\n await refreshEventSubscriptions();\n return JSON.stringify({\n created: true,\n name: definition.name,\n scope: definition.scope,\n triggerType: definition.meta.triggerType,\n event: definition.meta.event ?? null,\n schedule: definition.meta.schedule || null,\n nextRun: definition.meta.nextRun ?? null,\n createdBy: definition.meta.createdBy,\n runAs: definition.meta.runAs,\n model: definition.meta.model ?? null,\n mcpTools: definition.meta.mcpTools ?? [],\n originScopeId: definition.meta.originScopeId ?? null,\n deliveryPlatform: definition.meta.deliveryPlatform ?? null,\n deliveryDestination: definition.meta.deliveryDestination ?? null,\n deliveryThreadRef: definition.meta.deliveryThreadRef ?? null,\n deliveryTenantId: definition.meta.deliveryTenantId ?? null,\n });\n } catch (error) {\n return `Error: ${(error as Error).message}`;\n }\n}\n\nasync function handleUpdate(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n try {\n const definition = await updateAutomation(\n { userEmail: getCurrentUser(), orgId: getRequestOrgId() },\n {\n name: typeof args.name === \"string\" ? args.name : \"\",\n scope: automationScope(args.scope),\n enabled:\n args.enabled === undefined\n ? undefined\n : args.enabled === true || args.enabled === \"true\",\n condition:\n args.condition === undefined\n ? undefined\n : typeof args.condition === \"string\"\n ? args.condition\n : null,\n delegatedPolicyId:\n args.delegated_policy_id === undefined\n ? undefined\n : typeof args.delegated_policy_id === \"string\"\n ? args.delegated_policy_id\n : null,\n body: typeof args.body === \"string\" ? args.body : undefined,\n schedule: typeof args.schedule === \"string\" ? args.schedule : undefined,\n model:\n args.model === undefined\n ? undefined\n : typeof args.model === \"string\"\n ? args.model\n : null,\n mcpTools: args.mcpTools,\n },\n );\n await refreshEventSubscriptions();\n return JSON.stringify({\n updated: true,\n name: definition.name,\n scope: definition.scope,\n triggerType: definition.meta.triggerType,\n enabled: definition.meta.enabled,\n schedule: definition.meta.schedule || null,\n nextRun: definition.meta.nextRun ?? null,\n createdBy: definition.meta.createdBy,\n runAs: definition.meta.runAs,\n model: definition.meta.model ?? null,\n mcpTools: definition.meta.mcpTools ?? [],\n originScopeId: definition.meta.originScopeId ?? null,\n deliveryPlatform: definition.meta.deliveryPlatform ?? null,\n deliveryDestination: definition.meta.deliveryDestination ?? null,\n deliveryThreadRef: definition.meta.deliveryThreadRef ?? null,\n deliveryTenantId: definition.meta.deliveryTenantId ?? null,\n });\n } catch (error) {\n return `Error: ${(error as Error).message}`;\n }\n}\n\nasync function handleDelete(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n const name = typeof args.name === \"string\" ? args.name : \"\";\n try {\n await deleteAutomation(\n { userEmail: getCurrentUser(), orgId: getRequestOrgId() },\n automationScope(args.scope),\n name,\n );\n await refreshEventSubscriptions();\n return JSON.stringify({ deleted: true, name });\n } catch (error) {\n return `Error: ${(error as Error).message}`;\n }\n}\n\nasync function handleFireTest(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n // Dynamic import to avoid circular dependency at module load time\n const { emit } = await import(\"../event-bus/index.js\");\n\n let data: Record<string, unknown> = {};\n if (typeof args.data === \"string\" && args.data) {\n try {\n data = JSON.parse(args.data);\n } catch {\n return \"Error: invalid JSON in data parameter.\";\n }\n }\n\n // Scope the test event to the current user so only their automations fire,\n // not automations owned by other users in the same process.\n const owner = getCurrentUser();\n emit(\"test.event.fired\", { data }, { owner });\n return `Test event fired with payload: ${JSON.stringify({ data })}. Any automations subscribed to \"test.event.fired\" will be evaluated.`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Consolidated tool entry */\n/* ------------------------------------------------------------------ */\n\nconst VALID_ACTIONS = [\n \"list-events\",\n \"list\",\n \"define\",\n \"update\",\n \"delete\",\n \"fire-test\",\n] as const;\n\nexport function createAutomationToolEntries(\n getCurrentUser: () => string,\n): Record<string, ActionEntry> {\n return {\n \"manage-automations\": {\n tool: {\n description: `Manage automations (event-triggered and scheduled tasks). Use the \"action\" parameter to choose an operation:\n\n- **list-events**: List all registered event types that automations can subscribe to. Returns event names, descriptions, and payload schemas. Call this BEFORE defining an automation to discover available events.\n- **list**: List all automations (triggers). Shows trigger, status, model, MCP allowlist, and delivery metadata. Optional params: scope, domain, enabled_only.\n- **define**: Create a new automation. IMPORTANT: Always confirm with the user before calling — show them a summary of what will be created. Required params: name, trigger_type, body. Optional: scope, event, schedule, condition, mode, domain, delegated_policy_id, model, mcpTools.\n- **update**: Update an existing automation's settings without changing its creator (enabled, schedule, condition, body, policy, model, MCP allowlist). Required param: name. Use the same scope it was created in.\n- **delete**: Delete an automation. Always confirm with the user first. Required param: name.\n- **fire-test**: Fire a test event to validate automations. Emits a test.event.fired event. Optional param: data (JSON string).`,\n parameters: {\n type: \"object\" as const,\n properties: {\n action: {\n type: \"string\",\n description:\n \"The operation to perform: list-events, list, define, update, delete, or fire-test.\",\n enum: [...VALID_ACTIONS],\n },\n name: {\n type: \"string\",\n description:\n \"Slug name for the automation (lowercase, hyphens). Used by define, update, and delete.\",\n },\n scope: {\n type: \"string\",\n description:\n \"Personal or organization scope. Organization automations are visible to the active organization but always execute as their creator.\",\n enum: [\"personal\", \"organization\"],\n },\n trigger_type: {\n type: \"string\",\n description: '\"event\" or \"schedule\". Required for define.',\n enum: [\"event\", \"schedule\"],\n },\n event: {\n type: \"string\",\n description:\n \"For event triggers: the event name to subscribe to. Call with action=list-events first to see available events.\",\n },\n schedule: {\n type: \"string\",\n description:\n 'For schedule triggers: cron expression. Example: \"0 9 * * 1-5\" (9am weekdays).',\n },\n condition: {\n type: \"string\",\n description:\n 'Natural-language condition. Example: \"attendee email ends with @builder.io\". Leave empty for unconditional. Used by define and update.',\n },\n mode: {\n type: \"string\",\n description:\n '\"agentic\" (full agent loop, can use tools) — the only supported mode. Used by define.',\n enum: [\"agentic\"],\n },\n domain: {\n type: \"string\",\n description:\n \"Domain tag for grouping (mail, calendar, clips, etc.). Used by define and list.\",\n },\n model: {\n type: \"string\",\n description:\n \"Optional model id for this automation. The default model is used when omitted.\",\n },\n mcpTools: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n 'Optional explicit MCP capabilities. Use exact advertised tool names, for example [\"mcp__meeting-notes__list_meetings\"]. Credentials stay in the connector.',\n },\n delegated_policy_id: {\n type: \"string\",\n description:\n \"Optional app-owned stored policy id. It is passed by the trusted trigger runtime, never as action input. Only use an id documented by the app.\",\n },\n body: {\n type: \"string\",\n description:\n \"The natural-language instructions for what to do when the automation fires. This becomes the agent's prompt in agentic mode. Used by define and update.\",\n },\n enabled: {\n type: \"string\",\n description:\n '\"true\" or \"false\" to enable/disable. Used by update.',\n },\n enabled_only: {\n type: \"string\",\n description:\n '\"true\" to show only enabled automations. Used by list.',\n },\n data: {\n type: \"string\",\n description:\n 'JSON data to include as the test event payload. Used by fire-test. Example: \\'{\"email\": \"test@example.com\"}\\'.',\n },\n },\n required: [\"action\"],\n },\n },\n planMode: {\n effect: (args) =>\n args.action === \"list\" || args.action === \"list-events\"\n ? \"read\"\n : \"write\",\n allowedValues: { action: [\"list-events\", \"list\"] },\n description: \"Plan mode allows listing automations and event types.\",\n },\n run: async (args: Record<string, unknown>) => {\n const action = args.action;\n\n switch (action) {\n case \"list-events\":\n return handleListEvents();\n case \"list\":\n return handleList(args, getCurrentUser);\n case \"define\":\n return handleDefine(args, getCurrentUser);\n case \"update\":\n return handleUpdate(args, getCurrentUser);\n case \"delete\":\n return handleDelete(args, getCurrentUser);\n case \"fire-test\":\n return handleFireTest(args, getCurrentUser);\n default:\n return `Error: unknown action \"${action}\". Valid actions: ${VALID_ACTIONS.join(\", \")}.`;\n }\n },\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/triggers/actions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework-level agent actions for the automations system.\n *\n * These are registered as native tools (not template actions) so they're\n * available in every template. The agent uses them to create, list, and\n * manage automations from chat.\n *\n * All six operations are consolidated into a single `manage-automations` tool\n * with an `action` discriminator to keep the tool registry compact.\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport {\n defineAutomation,\n deleteAutomation,\n listAutomationDefinitions,\n updateAutomation,\n type AutomationScope,\n} from \"../automations/service.js\";\nimport { listEvents } from \"../event-bus/index.js\";\nimport { describeCron, effectiveTimezone } from \"../jobs/cron.js\";\nimport {\n getIntegrationRequestContext,\n getRequestOrgId,\n} from \"../server/request-context.js\";\nimport { refreshEventSubscriptions } from \"./dispatcher.js\";\n\n/* ------------------------------------------------------------------ */\n/* Individual action handlers */\n/* ------------------------------------------------------------------ */\n\nasync function handleListEvents(): Promise<string> {\n const events = listEvents();\n if (events.length === 0) {\n return \"No events registered yet. Events are registered by integrations (mail, calendar, clips, etc.).\";\n }\n const lines = events.map((e) => {\n let schemaStr = \"\";\n try {\n const s = e.payloadSchema as any;\n if (s?._zod?.def?.shape) {\n const fields = Object.keys(s._zod.def.shape);\n schemaStr = ` Fields: ${fields.join(\", \")}`;\n }\n } catch {\n // ignore\n }\n const example = e.example\n ? `\\n Example: ${JSON.stringify(e.example)}`\n : \"\";\n return `- **${e.name}**: ${e.description}${schemaStr}${example}`;\n });\n return lines.join(\"\\n\");\n}\n\nasync function handleList(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n const scope = automationScope(args.scope);\n const definitions = await listAutomationDefinitions(\n { userEmail: getCurrentUser(), orgId: getRequestOrgId() },\n scope,\n );\n const automations = definitions\n .filter(({ meta }) => !args.domain || meta.domain === args.domain)\n .filter(({ meta }) => args.enabled_only !== \"true\" || meta.enabled)\n .map(({ name, meta, body, canUpdate }) => ({\n name,\n scope,\n triggerType: meta.triggerType,\n event: meta.event ?? null,\n schedule: meta.schedule || null,\n timezone: meta.timezone ? effectiveTimezone(meta.timezone) : null,\n scheduleDescription: meta.schedule\n ? describeCron(meta.schedule, effectiveTimezone(meta.timezone))\n : null,\n condition: meta.condition ?? null,\n mode: meta.mode,\n domain: meta.domain ?? null,\n enabled: meta.enabled,\n lastRun: meta.lastRun ?? null,\n lastStatus: meta.lastStatus ?? null,\n lastError: meta.lastError ?? null,\n nextRun: meta.nextRun ?? null,\n createdBy: meta.createdBy ?? null,\n runAs: meta.runAs ?? null,\n model: meta.model ?? null,\n mcpTools: meta.mcpTools ?? [],\n originScopeId: meta.originScopeId ?? null,\n deliveryPlatform: meta.deliveryPlatform ?? null,\n deliveryDestination: meta.deliveryDestination ?? null,\n deliveryThreadRef: meta.deliveryThreadRef ?? null,\n deliveryTenantId: meta.deliveryTenantId ?? null,\n body,\n canUpdate,\n }));\n return JSON.stringify(automations, null, 2);\n}\n\nfunction automationScope(value: unknown): AutomationScope {\n if (value === undefined || value === null || value === \"\") return \"personal\";\n if (value === \"personal\" || value === \"organization\") return value;\n throw new Error('scope must be \"personal\" or \"organization\".');\n}\n\nfunction automationTriggerType(value: unknown): \"schedule\" | \"event\" {\n if (value === \"schedule\" || value === \"event\") return value;\n throw new Error('trigger_type must be \"schedule\" or \"event\".');\n}\n\nasync function handleDefine(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n if (args.mode === \"deterministic\") {\n return (\n \"Error: Deterministic mode was removed — it was never implemented and \" +\n \"automations that set it never fired. Create the automation without \" +\n \"mode (agentic), and describe the exact fixed steps in the automation body.\"\n );\n }\n const integration = getIntegrationRequestContext();\n try {\n const definition = await defineAutomation(\n { userEmail: getCurrentUser(), orgId: getRequestOrgId() },\n {\n name: typeof args.name === \"string\" ? args.name : \"\",\n scope: automationScope(args.scope),\n triggerType: automationTriggerType(args.trigger_type),\n body: typeof args.body === \"string\" ? args.body : \"\",\n schedule: typeof args.schedule === \"string\" ? args.schedule : undefined,\n timezone: typeof args.timezone === \"string\" ? args.timezone : undefined,\n event: typeof args.event === \"string\" ? args.event : undefined,\n condition:\n typeof args.condition === \"string\" ? args.condition : undefined,\n domain: typeof args.domain === \"string\" ? args.domain : undefined,\n delegatedPolicyId:\n typeof args.delegated_policy_id === \"string\"\n ? args.delegated_policy_id\n : undefined,\n model: typeof args.model === \"string\" ? args.model : undefined,\n mcpTools: args.mcpTools,\n delivery: integration\n ? {\n originScopeId: integration.scopeId,\n platform: integration.incoming.platform,\n destination:\n typeof integration.incoming.platformContext.channelId ===\n \"string\"\n ? integration.incoming.platformContext.channelId\n : undefined,\n threadRef:\n typeof integration.incoming.threadRef === \"string\"\n ? integration.incoming.threadRef\n : undefined,\n tenantId: integration.incoming.tenantId,\n }\n : undefined,\n },\n );\n\n await refreshEventSubscriptions();\n return JSON.stringify({\n created: true,\n name: definition.name,\n scope: definition.scope,\n triggerType: definition.meta.triggerType,\n event: definition.meta.event ?? null,\n schedule: definition.meta.schedule || null,\n timezone: definition.meta.timezone ?? null,\n nextRun: definition.meta.nextRun ?? null,\n createdBy: definition.meta.createdBy,\n runAs: definition.meta.runAs,\n model: definition.meta.model ?? null,\n mcpTools: definition.meta.mcpTools ?? [],\n originScopeId: definition.meta.originScopeId ?? null,\n deliveryPlatform: definition.meta.deliveryPlatform ?? null,\n deliveryDestination: definition.meta.deliveryDestination ?? null,\n deliveryThreadRef: definition.meta.deliveryThreadRef ?? null,\n deliveryTenantId: definition.meta.deliveryTenantId ?? null,\n });\n } catch (error) {\n return `Error: ${(error as Error).message}`;\n }\n}\n\nasync function handleUpdate(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n try {\n const definition = await updateAutomation(\n { userEmail: getCurrentUser(), orgId: getRequestOrgId() },\n {\n name: typeof args.name === \"string\" ? args.name : \"\",\n scope: automationScope(args.scope),\n enabled:\n args.enabled === undefined\n ? undefined\n : args.enabled === true || args.enabled === \"true\",\n condition:\n args.condition === undefined\n ? undefined\n : typeof args.condition === \"string\"\n ? args.condition\n : null,\n delegatedPolicyId:\n args.delegated_policy_id === undefined\n ? undefined\n : typeof args.delegated_policy_id === \"string\"\n ? args.delegated_policy_id\n : null,\n body: typeof args.body === \"string\" ? args.body : undefined,\n schedule: typeof args.schedule === \"string\" ? args.schedule : undefined,\n timezone: typeof args.timezone === \"string\" ? args.timezone : undefined,\n model:\n args.model === undefined\n ? undefined\n : typeof args.model === \"string\"\n ? args.model\n : null,\n mcpTools: args.mcpTools,\n },\n );\n await refreshEventSubscriptions();\n return JSON.stringify({\n updated: true,\n name: definition.name,\n scope: definition.scope,\n triggerType: definition.meta.triggerType,\n enabled: definition.meta.enabled,\n schedule: definition.meta.schedule || null,\n timezone: definition.meta.timezone ?? null,\n nextRun: definition.meta.nextRun ?? null,\n createdBy: definition.meta.createdBy,\n runAs: definition.meta.runAs,\n model: definition.meta.model ?? null,\n mcpTools: definition.meta.mcpTools ?? [],\n originScopeId: definition.meta.originScopeId ?? null,\n deliveryPlatform: definition.meta.deliveryPlatform ?? null,\n deliveryDestination: definition.meta.deliveryDestination ?? null,\n deliveryThreadRef: definition.meta.deliveryThreadRef ?? null,\n deliveryTenantId: definition.meta.deliveryTenantId ?? null,\n });\n } catch (error) {\n return `Error: ${(error as Error).message}`;\n }\n}\n\nasync function handleDelete(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n const name = typeof args.name === \"string\" ? args.name : \"\";\n try {\n await deleteAutomation(\n { userEmail: getCurrentUser(), orgId: getRequestOrgId() },\n automationScope(args.scope),\n name,\n );\n await refreshEventSubscriptions();\n return JSON.stringify({ deleted: true, name });\n } catch (error) {\n return `Error: ${(error as Error).message}`;\n }\n}\n\nasync function handleFireTest(\n args: Record<string, unknown>,\n getCurrentUser: () => string,\n): Promise<string> {\n // Dynamic import to avoid circular dependency at module load time\n const { emit } = await import(\"../event-bus/index.js\");\n\n let data: Record<string, unknown> = {};\n if (typeof args.data === \"string\" && args.data) {\n try {\n data = JSON.parse(args.data);\n } catch {\n return \"Error: invalid JSON in data parameter.\";\n }\n }\n\n // Scope the test event to the current user so only their automations fire,\n // not automations owned by other users in the same process.\n const owner = getCurrentUser();\n emit(\"test.event.fired\", { data }, { owner });\n return `Test event fired with payload: ${JSON.stringify({ data })}. Any automations subscribed to \"test.event.fired\" will be evaluated.`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Consolidated tool entry */\n/* ------------------------------------------------------------------ */\n\nconst VALID_ACTIONS = [\n \"list-events\",\n \"list\",\n \"define\",\n \"update\",\n \"delete\",\n \"fire-test\",\n] as const;\n\nexport function createAutomationToolEntries(\n getCurrentUser: () => string,\n): Record<string, ActionEntry> {\n return {\n \"manage-automations\": {\n tool: {\n description: `Manage automations (event-triggered and scheduled tasks). Use the \"action\" parameter to choose an operation:\n\n- **list-events**: List all registered event types that automations can subscribe to. Returns event names, descriptions, and payload schemas. Call this BEFORE defining an automation to discover available events.\n- **list**: List all automations (triggers). Shows trigger, status, model, MCP allowlist, and delivery metadata. Optional params: scope, domain, enabled_only.\n- **define**: Create a new automation. IMPORTANT: Always confirm with the user before calling — show them a summary of what will be created. Required params: name, trigger_type, body. Optional: scope, event, schedule, timezone, condition, mode, domain, delegated_policy_id, model, mcpTools.\n- **update**: Update an existing automation's settings without changing its creator (enabled, schedule, timezone, condition, body, policy, model, MCP allowlist). Required param: name. Use the same scope it was created in.\n- **delete**: Delete an automation. Always confirm with the user first. Required param: name.\n- **fire-test**: Fire a test event to validate automations. Emits a test.event.fired event. Optional param: data (JSON string).`,\n parameters: {\n type: \"object\" as const,\n properties: {\n action: {\n type: \"string\",\n description:\n \"The operation to perform: list-events, list, define, update, delete, or fire-test.\",\n enum: [...VALID_ACTIONS],\n },\n name: {\n type: \"string\",\n description:\n \"Slug name for the automation (lowercase, hyphens). Used by define, update, and delete.\",\n },\n scope: {\n type: \"string\",\n description:\n \"Personal or organization scope. Organization automations are visible to the active organization but always execute as their creator.\",\n enum: [\"personal\", \"organization\"],\n },\n trigger_type: {\n type: \"string\",\n description: '\"event\" or \"schedule\". Required for define.',\n enum: [\"event\", \"schedule\"],\n },\n event: {\n type: \"string\",\n description:\n \"For event triggers: the event name to subscribe to. Call with action=list-events first to see available events.\",\n },\n timezone: {\n type: \"string\",\n description:\n \"IANA timezone the cron clock time is read in, e.g. 'America/New_York'. Optional; defaults to the user's saved scheduling timezone, then the caller's browser zone. Always pass this when the user names a time of day.\",\n },\n schedule: {\n type: \"string\",\n description:\n 'For schedule triggers: cron expression. Example: \"0 9 * * 1-5\" (9am weekdays).',\n },\n condition: {\n type: \"string\",\n description:\n 'Natural-language condition. Example: \"attendee email ends with @builder.io\". Leave empty for unconditional. Used by define and update.',\n },\n mode: {\n type: \"string\",\n description:\n '\"agentic\" (full agent loop, can use tools) — the only supported mode. Used by define.',\n enum: [\"agentic\"],\n },\n domain: {\n type: \"string\",\n description:\n \"Domain tag for grouping (mail, calendar, clips, etc.). Used by define and list.\",\n },\n model: {\n type: \"string\",\n description:\n \"Optional model id for this automation. The default model is used when omitted.\",\n },\n mcpTools: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n 'Optional explicit MCP capabilities. Use exact advertised tool names, for example [\"mcp__meeting-notes__list_meetings\"]. Credentials stay in the connector.',\n },\n delegated_policy_id: {\n type: \"string\",\n description:\n \"Optional app-owned stored policy id. It is passed by the trusted trigger runtime, never as action input. Only use an id documented by the app.\",\n },\n body: {\n type: \"string\",\n description:\n \"The natural-language instructions for what to do when the automation fires. This becomes the agent's prompt in agentic mode. Used by define and update.\",\n },\n enabled: {\n type: \"string\",\n description:\n '\"true\" or \"false\" to enable/disable. Used by update.',\n },\n enabled_only: {\n type: \"string\",\n description:\n '\"true\" to show only enabled automations. Used by list.',\n },\n data: {\n type: \"string\",\n description:\n 'JSON data to include as the test event payload. Used by fire-test. Example: \\'{\"email\": \"test@example.com\"}\\'.',\n },\n },\n required: [\"action\"],\n },\n },\n planMode: {\n effect: (args) =>\n args.action === \"list\" || args.action === \"list-events\"\n ? \"read\"\n : \"write\",\n allowedValues: { action: [\"list-events\", \"list\"] },\n description: \"Plan mode allows listing automations and event types.\",\n },\n run: async (args: Record<string, unknown>) => {\n const action = args.action;\n\n switch (action) {\n case \"list-events\":\n return handleListEvents();\n case \"list\":\n return handleList(args, getCurrentUser);\n case \"define\":\n return handleDefine(args, getCurrentUser);\n case \"update\":\n return handleUpdate(args, getCurrentUser);\n case \"delete\":\n return handleDelete(args, getCurrentUser);\n case \"fire-test\":\n return handleFireTest(args, getCurrentUser);\n default:\n return `Error: unknown action \"${action}\". Valid actions: ${VALID_ACTIONS.join(\", \")}.`;\n }\n },\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/triggers/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EAGL,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC9B,MAAM,yCAAyC,CAAC;AAWjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG;IACxD,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd,CAUA;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,MAAM,GACX,MAAM,CAER;AAID,MAAM,WAAW,qBAAsB,SAAQ,wBAAwB;IACrE;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,CACpB,UAAU,CAAC,EAAE,2BAA2B,KACrC,MAAM,EAAE,GAAG,SAAS,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/triggers/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EAGL,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC9B,MAAM,yCAAyC,CAAC;AAWjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG;IACxD,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd,CAUA;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,MAAM,GACX,MAAM,CAER;AAID,MAAM,WAAW,qBAAsB,SAAQ,wBAAwB;IACrE;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,CACpB,UAAU,CAAC,EAAE,2BAA2B,KACrC,MAAM,EAAE,GAAG,SAAS,CAAC;CAC3B;AAyCD;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgC/D"}
|
|
@@ -39,6 +39,21 @@ const _eventSubscriptions = new Map();
|
|
|
39
39
|
// deployments; multi-instance would need a conditional DB update.
|
|
40
40
|
const _dispatchingTriggers = new Set();
|
|
41
41
|
let _deps = null;
|
|
42
|
+
/**
|
|
43
|
+
* Record that a tick evaluated this trigger and declined to dispatch it.
|
|
44
|
+
* `lastRun` stays untouched — nothing ran — and an unchanged outcome is not
|
|
45
|
+
* re-persisted, so a permanently blocked trigger neither reports phantom runs
|
|
46
|
+
* nor rewrites its resource on every matching event.
|
|
47
|
+
*/
|
|
48
|
+
async function recordTriggerSkip(resource, meta, body, status, reason) {
|
|
49
|
+
const unchanged = meta.lastStatus === status && meta.lastError === reason;
|
|
50
|
+
meta.lastCheck = new Date().toISOString();
|
|
51
|
+
meta.lastStatus = status;
|
|
52
|
+
meta.lastError = reason;
|
|
53
|
+
if (unchanged)
|
|
54
|
+
return;
|
|
55
|
+
await resourcePut(resource.owner, resource.path, buildTriggerContent(meta, body));
|
|
56
|
+
}
|
|
42
57
|
/**
|
|
43
58
|
* Initialize the trigger dispatcher. Call once at server startup.
|
|
44
59
|
* Loads all event-triggered jobs and subscribes to their events.
|
|
@@ -116,18 +131,11 @@ async function handleEvent(eventName, payload, eventMeta) {
|
|
|
116
131
|
resolved = await resolveAutomationExecutionIdentity(resource.owner, meta);
|
|
117
132
|
}
|
|
118
133
|
catch {
|
|
119
|
-
meta
|
|
120
|
-
meta.lastStatus = "skipped";
|
|
121
|
-
meta.lastError =
|
|
122
|
-
"Could not verify the automation execution identity.";
|
|
123
|
-
await resourcePut(resource.owner, resource.path, buildTriggerContent(meta, body));
|
|
134
|
+
await recordTriggerSkip(resource, meta, body, "skipped", "Could not verify the automation execution identity.");
|
|
124
135
|
continue;
|
|
125
136
|
}
|
|
126
137
|
if (!resolved.ok) {
|
|
127
|
-
meta
|
|
128
|
-
meta.lastStatus = "skipped";
|
|
129
|
-
meta.lastError = resolved.reason;
|
|
130
|
-
await resourcePut(resource.owner, resource.path, buildTriggerContent(meta, body));
|
|
138
|
+
await recordTriggerSkip(resource, meta, body, "skipped", resolved.reason);
|
|
131
139
|
continue;
|
|
132
140
|
}
|
|
133
141
|
if (!automationMatchesEventOwner(resolved.identity, eventMeta.owner)) {
|
|
@@ -140,20 +148,14 @@ async function handleEvent(eventName, payload, eventMeta) {
|
|
|
140
148
|
const userApiKey = await getOwnerActiveApiKey(owner);
|
|
141
149
|
const apiKey = userApiKey || _deps.apiKey;
|
|
142
150
|
if (!apiKey) {
|
|
143
|
-
meta
|
|
144
|
-
meta.lastStatus = "error";
|
|
145
|
-
meta.lastError = "No API key is available for this automation";
|
|
146
|
-
await resourcePut(resource.owner, resource.path, buildTriggerContent(meta, body));
|
|
151
|
+
await recordTriggerSkip(resource, meta, body, "error", "No API key is available for this automation");
|
|
147
152
|
console.warn(`[triggers] ${meta.lastError}: "${resource.path}"`);
|
|
148
153
|
continue;
|
|
149
154
|
}
|
|
150
155
|
// Evaluate condition
|
|
151
156
|
const matches = await evaluateCondition(meta.condition, payload, apiKey);
|
|
152
157
|
if (!matches) {
|
|
153
|
-
meta
|
|
154
|
-
meta.lastStatus = "skipped";
|
|
155
|
-
meta.lastError = undefined;
|
|
156
|
-
await resourcePut(resource.owner, resource.path, buildTriggerContent(meta, body));
|
|
158
|
+
await recordTriggerSkip(resource, meta, body, "skipped", undefined);
|
|
157
159
|
continue;
|
|
158
160
|
}
|
|
159
161
|
// Dispatch. Guard against concurrent duplicate dispatch of the same
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/triggers/dispatcher.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Trigger dispatcher — bridges the event bus to the automation system.\n *\n * On startup, loads all event-triggered jobs from the resources store,\n * subscribes to their events, and dispatches them (condition eval → agent\n * loop) when matching events fire.\n */\n\nimport { getOwnerActiveApiKey } from \"../agent/production-agent.js\";\nimport {\n automationMatchesEventOwner,\n resolveAutomationExecutionIdentity,\n type AutomationExecutionIdentity,\n} from \"../automations/service.js\";\nimport { subscribe, unsubscribe } from \"../event-bus/index.js\";\nimport type { EventMeta } from \"../event-bus/types.js\";\nimport {\n isBackgroundAutomationRunActive,\n runBackgroundAutomation,\n type BackgroundAutomationContext,\n type BackgroundAutomationDeps,\n} from \"../jobs/background-automation-runner.js\";\nimport {\n buildJobResourceContent,\n parseJobResource,\n} from \"../jobs/frontmatter.js\";\nimport {\n resourceListAllOwners,\n resourcePut,\n type Resource,\n} from \"../resources/store.js\";\nimport { evaluateCondition } from \"./condition-evaluator.js\";\nimport type { TriggerFrontmatter } from \"./types.js\";\n\nexport function parseTriggerFrontmatter(content: string): {\n meta: TriggerFrontmatter;\n body: string;\n} {\n const { meta, body } = parseJobResource(content);\n return {\n meta: {\n ...meta,\n triggerType: meta.triggerType ?? \"schedule\",\n mode: meta.mode ?? \"agentic\",\n },\n body,\n };\n}\n\nexport function buildTriggerContent(\n meta: TriggerFrontmatter,\n body: string,\n): string {\n return buildJobResourceContent(meta, body);\n}\n\n// ─── Dispatcher deps (same pattern as SchedulerDeps) ────────────────────────\n\nexport interface TriggerDispatcherDeps extends BackgroundAutomationDeps {\n /**\n * Tool names to expose on the FIRST engine request for a trigger run. See\n * `SchedulerDeps.getInitialToolNames` (`jobs/scheduler.ts`) — same\n * semantics. Omit to keep the full `getActions()` set visible up front\n * (current behavior).\n */\n getInitialToolNames?: (\n automation?: BackgroundAutomationContext,\n ) => string[] | undefined;\n}\n\n// Track active subscriptions (eventName -> subscription id) to avoid\n// double-subscribing AND so subscriptions for events that no longer have any\n// enabled trigger can be torn down — otherwise deleted/disabled triggers leave\n// phantom bus listeners that fire handleEvent forever.\nconst _eventSubscriptions = new Map<string, string>();\n// In-flight agentic dispatches keyed by `${owner}:${path}`. Guards against the\n// check-then-write TOCTOU window in handleEvent: two near-simultaneous fires of\n// the same event both pass the `lastStatus !== \"running\"` check (which has\n// several awaits before the DB is marked running) and would otherwise launch\n// two concurrent agent runs for one trigger. Sufficient for single-process\n// deployments; multi-instance would need a conditional DB update.\nconst _dispatchingTriggers = new Set<string>();\nlet _deps: TriggerDispatcherDeps | null = null;\n\n/**\n * Initialize the trigger dispatcher. Call once at server startup.\n * Loads all event-triggered jobs and subscribes to their events.\n */\nexport async function initTriggerDispatcher(\n deps: TriggerDispatcherDeps,\n): Promise<void> {\n _deps = deps;\n await refreshEventSubscriptions();\n}\n\n/**\n * Refresh event subscriptions from the resource store.\n * Call after creating/updating triggers.\n */\nexport async function refreshEventSubscriptions(): Promise<void> {\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n const eventNames = new Set<string>();\n\n for (const resource of jobResources) {\n if (!resource.path.endsWith(\".md\")) continue;\n const { meta } = parseTriggerFrontmatter(resource.content);\n if (meta.triggerType === \"event\" && meta.event && meta.enabled) {\n eventNames.add(meta.event);\n }\n }\n\n // Tear down subscriptions whose event no longer has any enabled trigger.\n for (const [eventName, subId] of [..._eventSubscriptions]) {\n if (!eventNames.has(eventName)) {\n unsubscribe(subId);\n _eventSubscriptions.delete(eventName);\n }\n }\n\n for (const eventName of eventNames) {\n if (!_eventSubscriptions.has(eventName)) {\n const subId = subscribe(eventName, (payload, eventMeta) =>\n handleEvent(eventName, payload, eventMeta),\n );\n _eventSubscriptions.set(eventName, subId);\n }\n }\n } catch (err) {\n console.error(\"[triggers] Failed to refresh event subscriptions:\", err);\n }\n}\n\nasync function handleEvent(\n eventName: string,\n payload: unknown,\n eventMeta: EventMeta,\n): Promise<void> {\n if (!_deps) return;\n\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n const matchingTriggers = jobResources.filter((r) => {\n if (!r.path.endsWith(\".md\")) return false;\n const { meta } = parseTriggerFrontmatter(r.content);\n return (\n meta.triggerType === \"event\" &&\n meta.event === eventName &&\n meta.enabled &&\n !isBackgroundAutomationRunActive(meta)\n );\n });\n\n for (const resource of matchingTriggers) {\n const { meta, body } = parseTriggerFrontmatter(resource.content);\n if (!body.trim()) continue;\n\n let identity: AutomationExecutionIdentity;\n if (resource.owner === \"__shared__\") {\n // Compatibility for old workspace-wide event resources. New personal\n // and organization automations always require an event owner.\n const userEmail = meta.createdBy || resource.owner;\n identity = {\n userEmail,\n orgId: meta.orgId,\n eventOwner: userEmail.toLowerCase(),\n };\n } else {\n let resolved;\n try {\n resolved = await resolveAutomationExecutionIdentity(\n resource.owner,\n meta,\n );\n } catch {\n meta.lastRun = new Date().toISOString();\n meta.lastStatus = \"skipped\";\n meta.lastError =\n \"Could not verify the automation execution identity.\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n continue;\n }\n if (!resolved.ok) {\n meta.lastRun = new Date().toISOString();\n meta.lastStatus = \"skipped\";\n meta.lastError = resolved.reason;\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n continue;\n }\n if (!automationMatchesEventOwner(resolved.identity, eventMeta.owner)) {\n continue;\n }\n identity = resolved.identity;\n }\n\n // Resolve API key for condition evaluation\n const owner = identity.userEmail;\n const userApiKey = await getOwnerActiveApiKey(owner);\n const apiKey = userApiKey || _deps.apiKey;\n if (!apiKey) {\n meta.lastRun = new Date().toISOString();\n meta.lastStatus = \"error\";\n meta.lastError = \"No API key is available for this automation\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n console.warn(`[triggers] ${meta.lastError}: \"${resource.path}\"`);\n continue;\n }\n\n // Evaluate condition\n const matches = await evaluateCondition(meta.condition, payload, apiKey);\n if (!matches) {\n meta.lastRun = new Date().toISOString();\n meta.lastStatus = \"skipped\";\n meta.lastError = undefined;\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n continue;\n }\n\n // Dispatch. Guard against concurrent duplicate dispatch of the same\n // trigger (TOCTOU on lastStatus) with an in-process lock keyed on the\n // trigger's identity.\n const dispatchKey = `${resource.owner}:${resource.path}`;\n if (_dispatchingTriggers.has(dispatchKey)) continue;\n if (meta.mode === \"agentic\") {\n _dispatchingTriggers.add(dispatchKey);\n try {\n await dispatchAgentic(\n resource,\n meta,\n body,\n payload,\n eventMeta,\n identity,\n );\n } finally {\n _dispatchingTriggers.delete(dispatchKey);\n }\n } else {\n console.warn(\n `[triggers] Deterministic mode not yet implemented for \"${resource.path}\" — skipping`,\n );\n }\n }\n } catch (err) {\n console.error(`[triggers] Error handling event \"${eventName}\":`, err);\n }\n}\n\nasync function dispatchAgentic(\n resource: Resource,\n meta: TriggerFrontmatter,\n body: string,\n payload: unknown,\n eventMeta: EventMeta,\n identity: AutomationExecutionIdentity,\n): Promise<void> {\n if (!_deps) return;\n\n const triggerName = resource.path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n const now = new Date();\n\n const jobUserEmail = identity.userEmail;\n const jobOrgId = identity.orgId;\n\n // Mark as running\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"running\";\n meta.lastError = undefined;\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n\n let payloadStr: string;\n try {\n payloadStr = JSON.stringify(payload, null, 2);\n } catch {\n payloadStr = String(payload);\n }\n\n const automation: BackgroundAutomationContext = {\n name: triggerName,\n meta,\n body,\n resource,\n };\n const requestContext =\n meta.originScopeId && meta.deliveryPlatform && meta.deliveryDestination\n ? {\n isIntegrationCaller: true as const,\n integration: {\n taskId: `automation:${triggerName}:${eventMeta.eventId}`,\n scopeId: meta.originScopeId,\n principalType: \"service\" as const,\n incoming: {\n platform: meta.deliveryPlatform,\n externalThreadId: `${meta.deliveryTenantId || \"unknown\"}:${meta.deliveryDestination}:${meta.deliveryThreadRef || \"root\"}`,\n text: \"\",\n tenantId: meta.deliveryTenantId,\n integrationScopeId: meta.originScopeId,\n platformContext: {\n channelId: meta.deliveryDestination,\n threadTs: meta.deliveryThreadRef,\n teamId: meta.deliveryTenantId,\n },\n threadRef: meta.deliveryThreadRef,\n timestamp: now.getTime(),\n },\n },\n }\n : undefined;\n\n try {\n await runBackgroundAutomation(\n {\n automation,\n ownerEmail: jobUserEmail,\n orgId: jobOrgId,\n prompt: `[Automation Trigger: ${triggerName}]\nEvent: ${meta.event}\nEvent ID: ${eventMeta.eventId}\nFired at: ${eventMeta.emittedAt}\n\nEvent payload:\n${payloadStr}\n\nExecute the following automation instructions:\n\n${body}`,\n threadTitle: `Trigger: ${triggerName} — ${now.toLocaleDateString()}`,\n runIdPrefix: `automation-${triggerName}`,\n usageLabel: `automation:${triggerName}`,\n usageRefId: eventMeta.eventId,\n requestContext,\n actionCaller: \"automation\",\n actionAutomation: {\n triggerId: resource.id,\n triggerName,\n policyId: meta.delegatedPolicyId,\n },\n },\n _deps,\n );\n\n meta.lastStatus = \"success\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n console.log(`[triggers] \"${triggerName}\" completed successfully`);\n } catch (err) {\n meta.lastStatus = \"error\";\n meta.lastError =\n err instanceof Error ? err.message.slice(0, 200) : \"Unknown error\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n console.error(`[triggers] \"${triggerName}\" failed:`, meta.lastError);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/triggers/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EACL,2BAA2B,EAC3B,kCAAkC,GAEnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EACL,+BAA+B,EAC/B,uBAAuB,GAGxB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,WAAW,GAEZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,MAAM,UAAU,uBAAuB,CAAC,OAAe;IAIrD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACjD,OAAO;QACL,IAAI,EAAE;YACJ,GAAG,IAAI;YACP,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,UAAU;YAC3C,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,SAAS;SAC7B;QACD,IAAI;KACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,IAAwB,EACxB,IAAY;IAEZ,OAAO,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAgBD,qEAAqE;AACrE,6EAA6E;AAC7E,+EAA+E;AAC/E,uDAAuD;AACvD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAkB,CAAC;AACtD,+EAA+E;AAC/E,gFAAgF;AAChF,2EAA2E;AAC3E,6EAA6E;AAC7E,2EAA2E;AAC3E,kEAAkE;AAClE,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;AAC/C,IAAI,KAAK,GAAiC,IAAI,CAAC;AAE/C;;;;;GAKG;AACH,KAAK,UAAU,iBAAiB,CAC9B,QAAkB,EAClB,IAAwB,EACxB,IAAY,EACZ,MAA2B,EAC3B,MAA0B;IAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC;IAC1E,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC;IACxB,IAAI,SAAS;QAAE,OAAO;IACtB,MAAM,WAAW,CACf,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,IAAI,EACb,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAChC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAA2B;IAE3B,KAAK,GAAG,IAAI,CAAC;IACb,MAAM,yBAAyB,EAAE,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC1D,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QAErC,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;YACpC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YAC7C,MAAM,EAAE,IAAI,EAAE,GAAG,uBAAuB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC3D,IAAI,IAAI,CAAC,WAAW,KAAK,OAAO,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC/D,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,yEAAyE;QACzE,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC/B,WAAW,CAAC,KAAK,CAAC,CAAC;gBACnB,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QAED,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,CACxD,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAC3C,CAAC;gBACF,mBAAmB,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,mDAAmD,EAAE,GAAG,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,SAAiB,EACjB,OAAgB,EAChB,SAAoB;IAEpB,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC1D,MAAM,gBAAgB,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACjD,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC1C,MAAM,EAAE,IAAI,EAAE,GAAG,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACpD,OAAO,CACL,IAAI,CAAC,WAAW,KAAK,OAAO;gBAC5B,IAAI,CAAC,KAAK,KAAK,SAAS;gBACxB,IAAI,CAAC,OAAO;gBACZ,CAAC,+BAA+B,CAAC,IAAI,CAAC,CACvC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;YACxC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,uBAAuB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACjE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,SAAS;YAE3B,IAAI,QAAqC,CAAC;YAC1C,IAAI,QAAQ,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;gBACpC,qEAAqE;gBACrE,8DAA8D;gBAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC;gBACnD,QAAQ,GAAG;oBACT,SAAS;oBACT,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,UAAU,EAAE,SAAS,CAAC,WAAW,EAAE;iBACpC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,IAAI,QAAQ,CAAC;gBACb,IAAI,CAAC;oBACH,QAAQ,GAAG,MAAM,kCAAkC,CACjD,QAAQ,CAAC,KAAK,EACd,IAAI,CACL,CAAC;gBACJ,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,iBAAiB,CACrB,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,qDAAqD,CACtD,CAAC;oBACF,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,MAAM,iBAAiB,CACrB,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,QAAQ,CAAC,MAAM,CAChB,CAAC;oBACF,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,2BAA2B,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;oBACrE,SAAS;gBACX,CAAC;gBACD,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;YAC/B,CAAC;YAED,2CAA2C;YAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC;YACjC,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,KAAK,CAAC,CAAC;YACrD,MAAM,MAAM,GAAG,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC;YAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,iBAAiB,CACrB,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,6CAA6C,CAC9C,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,SAAS,MAAM,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;gBACjE,SAAS;YACX,CAAC;YAED,qBAAqB;YACrB,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YACzE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBACpE,SAAS;YACX,CAAC;YAED,oEAAoE;YACpE,sEAAsE;YACtE,sBAAsB;YACtB,MAAM,WAAW,GAAG,GAAG,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YACzD,IAAI,oBAAoB,CAAC,GAAG,CAAC,WAAW,CAAC;gBAAE,SAAS;YACpD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5B,oBAAoB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACtC,IAAI,CAAC;oBACH,MAAM,eAAe,CACnB,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,SAAS,EACT,QAAQ,CACT,CAAC;gBACJ,CAAC;wBAAS,CAAC;oBACT,oBAAoB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CACV,0DAA0D,QAAQ,CAAC,IAAI,cAAc,CACtF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oCAAoC,SAAS,IAAI,EAAE,GAAG,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,QAAkB,EAClB,IAAwB,EACxB,IAAY,EACZ,OAAgB,EAChB,SAAoB,EACpB,QAAqC;IAErC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC9E,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC;IACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC;IAEhC,kBAAkB;IAClB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;IAC5B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC3B,MAAM,WAAW,CACf,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,IAAI,EACb,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAChC,CAAC;IAEF,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,UAAU,GAAgC;QAC9C,IAAI,EAAE,WAAW;QACjB,IAAI;QACJ,IAAI;QACJ,QAAQ;KACT,CAAC;IACF,MAAM,cAAc,GAClB,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,mBAAmB;QACrE,CAAC,CAAC;YACE,mBAAmB,EAAE,IAAa;YAClC,WAAW,EAAE;gBACX,MAAM,EAAE,cAAc,WAAW,IAAI,SAAS,CAAC,OAAO,EAAE;gBACxD,OAAO,EAAE,IAAI,CAAC,aAAa;gBAC3B,aAAa,EAAE,SAAkB;gBACjC,QAAQ,EAAE;oBACR,QAAQ,EAAE,IAAI,CAAC,gBAAgB;oBAC/B,gBAAgB,EAAE,GAAG,IAAI,CAAC,gBAAgB,IAAI,SAAS,IAAI,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,iBAAiB,IAAI,MAAM,EAAE;oBACzH,IAAI,EAAE,EAAE;oBACR,QAAQ,EAAE,IAAI,CAAC,gBAAgB;oBAC/B,kBAAkB,EAAE,IAAI,CAAC,aAAa;oBACtC,eAAe,EAAE;wBACf,SAAS,EAAE,IAAI,CAAC,mBAAmB;wBACnC,QAAQ,EAAE,IAAI,CAAC,iBAAiB;wBAChC,MAAM,EAAE,IAAI,CAAC,gBAAgB;qBAC9B;oBACD,SAAS,EAAE,IAAI,CAAC,iBAAiB;oBACjC,SAAS,EAAE,GAAG,CAAC,OAAO,EAAE;iBACzB;aACF;SACF;QACH,CAAC,CAAC,SAAS,CAAC;IAEhB,IAAI,CAAC;QACH,MAAM,uBAAuB,CAC3B;YACE,UAAU;YACV,UAAU,EAAE,YAAY;YACxB,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,wBAAwB,WAAW;SAC1C,IAAI,CAAC,KAAK;YACP,SAAS,CAAC,OAAO;YACjB,SAAS,CAAC,SAAS;;;EAG7B,UAAU;;;;EAIV,IAAI,EAAE;YACA,WAAW,EAAE,YAAY,WAAW,MAAM,GAAG,CAAC,kBAAkB,EAAE,EAAE;YACpE,WAAW,EAAE,cAAc,WAAW,EAAE;YACxC,UAAU,EAAE,cAAc,WAAW,EAAE;YACvC,UAAU,EAAE,SAAS,CAAC,OAAO;YAC7B,cAAc;YACd,YAAY,EAAE,YAAY;YAC1B,gBAAgB,EAAE;gBAChB,SAAS,EAAE,QAAQ,CAAC,EAAE;gBACtB,WAAW;gBACX,QAAQ,EAAE,IAAI,CAAC,iBAAiB;aACjC;SACF,EACD,KAAK,CACN,CAAC;QAEF,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,MAAM,WAAW,CACf,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,IAAI,EACb,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAChC,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,eAAe,WAAW,0BAA0B,CAAC,CAAC;IACpE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC;QAC1B,IAAI,CAAC,SAAS;YACZ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;QACrE,MAAM,WAAW,CACf,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,IAAI,EACb,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAChC,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,eAAe,WAAW,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACvE,CAAC;AACH,CAAC","sourcesContent":["/**\n * Trigger dispatcher — bridges the event bus to the automation system.\n *\n * On startup, loads all event-triggered jobs from the resources store,\n * subscribes to their events, and dispatches them (condition eval → agent\n * loop) when matching events fire.\n */\n\nimport { getOwnerActiveApiKey } from \"../agent/production-agent.js\";\nimport {\n automationMatchesEventOwner,\n resolveAutomationExecutionIdentity,\n type AutomationExecutionIdentity,\n} from \"../automations/service.js\";\nimport { subscribe, unsubscribe } from \"../event-bus/index.js\";\nimport type { EventMeta } from \"../event-bus/types.js\";\nimport {\n isBackgroundAutomationRunActive,\n runBackgroundAutomation,\n type BackgroundAutomationContext,\n type BackgroundAutomationDeps,\n} from \"../jobs/background-automation-runner.js\";\nimport {\n buildJobResourceContent,\n parseJobResource,\n} from \"../jobs/frontmatter.js\";\nimport {\n resourceListAllOwners,\n resourcePut,\n type Resource,\n} from \"../resources/store.js\";\nimport { evaluateCondition } from \"./condition-evaluator.js\";\nimport type { TriggerFrontmatter } from \"./types.js\";\n\nexport function parseTriggerFrontmatter(content: string): {\n meta: TriggerFrontmatter;\n body: string;\n} {\n const { meta, body } = parseJobResource(content);\n return {\n meta: {\n ...meta,\n triggerType: meta.triggerType ?? \"schedule\",\n mode: meta.mode ?? \"agentic\",\n },\n body,\n };\n}\n\nexport function buildTriggerContent(\n meta: TriggerFrontmatter,\n body: string,\n): string {\n return buildJobResourceContent(meta, body);\n}\n\n// ─── Dispatcher deps (same pattern as SchedulerDeps) ────────────────────────\n\nexport interface TriggerDispatcherDeps extends BackgroundAutomationDeps {\n /**\n * Tool names to expose on the FIRST engine request for a trigger run. See\n * `SchedulerDeps.getInitialToolNames` (`jobs/scheduler.ts`) — same\n * semantics. Omit to keep the full `getActions()` set visible up front\n * (current behavior).\n */\n getInitialToolNames?: (\n automation?: BackgroundAutomationContext,\n ) => string[] | undefined;\n}\n\n// Track active subscriptions (eventName -> subscription id) to avoid\n// double-subscribing AND so subscriptions for events that no longer have any\n// enabled trigger can be torn down — otherwise deleted/disabled triggers leave\n// phantom bus listeners that fire handleEvent forever.\nconst _eventSubscriptions = new Map<string, string>();\n// In-flight agentic dispatches keyed by `${owner}:${path}`. Guards against the\n// check-then-write TOCTOU window in handleEvent: two near-simultaneous fires of\n// the same event both pass the `lastStatus !== \"running\"` check (which has\n// several awaits before the DB is marked running) and would otherwise launch\n// two concurrent agent runs for one trigger. Sufficient for single-process\n// deployments; multi-instance would need a conditional DB update.\nconst _dispatchingTriggers = new Set<string>();\nlet _deps: TriggerDispatcherDeps | null = null;\n\n/**\n * Record that a tick evaluated this trigger and declined to dispatch it.\n * `lastRun` stays untouched — nothing ran — and an unchanged outcome is not\n * re-persisted, so a permanently blocked trigger neither reports phantom runs\n * nor rewrites its resource on every matching event.\n */\nasync function recordTriggerSkip(\n resource: Resource,\n meta: TriggerFrontmatter,\n body: string,\n status: \"skipped\" | \"error\",\n reason: string | undefined,\n): Promise<void> {\n const unchanged = meta.lastStatus === status && meta.lastError === reason;\n meta.lastCheck = new Date().toISOString();\n meta.lastStatus = status;\n meta.lastError = reason;\n if (unchanged) return;\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n}\n\n/**\n * Initialize the trigger dispatcher. Call once at server startup.\n * Loads all event-triggered jobs and subscribes to their events.\n */\nexport async function initTriggerDispatcher(\n deps: TriggerDispatcherDeps,\n): Promise<void> {\n _deps = deps;\n await refreshEventSubscriptions();\n}\n\n/**\n * Refresh event subscriptions from the resource store.\n * Call after creating/updating triggers.\n */\nexport async function refreshEventSubscriptions(): Promise<void> {\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n const eventNames = new Set<string>();\n\n for (const resource of jobResources) {\n if (!resource.path.endsWith(\".md\")) continue;\n const { meta } = parseTriggerFrontmatter(resource.content);\n if (meta.triggerType === \"event\" && meta.event && meta.enabled) {\n eventNames.add(meta.event);\n }\n }\n\n // Tear down subscriptions whose event no longer has any enabled trigger.\n for (const [eventName, subId] of [..._eventSubscriptions]) {\n if (!eventNames.has(eventName)) {\n unsubscribe(subId);\n _eventSubscriptions.delete(eventName);\n }\n }\n\n for (const eventName of eventNames) {\n if (!_eventSubscriptions.has(eventName)) {\n const subId = subscribe(eventName, (payload, eventMeta) =>\n handleEvent(eventName, payload, eventMeta),\n );\n _eventSubscriptions.set(eventName, subId);\n }\n }\n } catch (err) {\n console.error(\"[triggers] Failed to refresh event subscriptions:\", err);\n }\n}\n\nasync function handleEvent(\n eventName: string,\n payload: unknown,\n eventMeta: EventMeta,\n): Promise<void> {\n if (!_deps) return;\n\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n const matchingTriggers = jobResources.filter((r) => {\n if (!r.path.endsWith(\".md\")) return false;\n const { meta } = parseTriggerFrontmatter(r.content);\n return (\n meta.triggerType === \"event\" &&\n meta.event === eventName &&\n meta.enabled &&\n !isBackgroundAutomationRunActive(meta)\n );\n });\n\n for (const resource of matchingTriggers) {\n const { meta, body } = parseTriggerFrontmatter(resource.content);\n if (!body.trim()) continue;\n\n let identity: AutomationExecutionIdentity;\n if (resource.owner === \"__shared__\") {\n // Compatibility for old workspace-wide event resources. New personal\n // and organization automations always require an event owner.\n const userEmail = meta.createdBy || resource.owner;\n identity = {\n userEmail,\n orgId: meta.orgId,\n eventOwner: userEmail.toLowerCase(),\n };\n } else {\n let resolved;\n try {\n resolved = await resolveAutomationExecutionIdentity(\n resource.owner,\n meta,\n );\n } catch {\n await recordTriggerSkip(\n resource,\n meta,\n body,\n \"skipped\",\n \"Could not verify the automation execution identity.\",\n );\n continue;\n }\n if (!resolved.ok) {\n await recordTriggerSkip(\n resource,\n meta,\n body,\n \"skipped\",\n resolved.reason,\n );\n continue;\n }\n if (!automationMatchesEventOwner(resolved.identity, eventMeta.owner)) {\n continue;\n }\n identity = resolved.identity;\n }\n\n // Resolve API key for condition evaluation\n const owner = identity.userEmail;\n const userApiKey = await getOwnerActiveApiKey(owner);\n const apiKey = userApiKey || _deps.apiKey;\n if (!apiKey) {\n await recordTriggerSkip(\n resource,\n meta,\n body,\n \"error\",\n \"No API key is available for this automation\",\n );\n console.warn(`[triggers] ${meta.lastError}: \"${resource.path}\"`);\n continue;\n }\n\n // Evaluate condition\n const matches = await evaluateCondition(meta.condition, payload, apiKey);\n if (!matches) {\n await recordTriggerSkip(resource, meta, body, \"skipped\", undefined);\n continue;\n }\n\n // Dispatch. Guard against concurrent duplicate dispatch of the same\n // trigger (TOCTOU on lastStatus) with an in-process lock keyed on the\n // trigger's identity.\n const dispatchKey = `${resource.owner}:${resource.path}`;\n if (_dispatchingTriggers.has(dispatchKey)) continue;\n if (meta.mode === \"agentic\") {\n _dispatchingTriggers.add(dispatchKey);\n try {\n await dispatchAgentic(\n resource,\n meta,\n body,\n payload,\n eventMeta,\n identity,\n );\n } finally {\n _dispatchingTriggers.delete(dispatchKey);\n }\n } else {\n console.warn(\n `[triggers] Deterministic mode not yet implemented for \"${resource.path}\" — skipping`,\n );\n }\n }\n } catch (err) {\n console.error(`[triggers] Error handling event \"${eventName}\":`, err);\n }\n}\n\nasync function dispatchAgentic(\n resource: Resource,\n meta: TriggerFrontmatter,\n body: string,\n payload: unknown,\n eventMeta: EventMeta,\n identity: AutomationExecutionIdentity,\n): Promise<void> {\n if (!_deps) return;\n\n const triggerName = resource.path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n const now = new Date();\n\n const jobUserEmail = identity.userEmail;\n const jobOrgId = identity.orgId;\n\n // Mark as running\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"running\";\n meta.lastError = undefined;\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n\n let payloadStr: string;\n try {\n payloadStr = JSON.stringify(payload, null, 2);\n } catch {\n payloadStr = String(payload);\n }\n\n const automation: BackgroundAutomationContext = {\n name: triggerName,\n meta,\n body,\n resource,\n };\n const requestContext =\n meta.originScopeId && meta.deliveryPlatform && meta.deliveryDestination\n ? {\n isIntegrationCaller: true as const,\n integration: {\n taskId: `automation:${triggerName}:${eventMeta.eventId}`,\n scopeId: meta.originScopeId,\n principalType: \"service\" as const,\n incoming: {\n platform: meta.deliveryPlatform,\n externalThreadId: `${meta.deliveryTenantId || \"unknown\"}:${meta.deliveryDestination}:${meta.deliveryThreadRef || \"root\"}`,\n text: \"\",\n tenantId: meta.deliveryTenantId,\n integrationScopeId: meta.originScopeId,\n platformContext: {\n channelId: meta.deliveryDestination,\n threadTs: meta.deliveryThreadRef,\n teamId: meta.deliveryTenantId,\n },\n threadRef: meta.deliveryThreadRef,\n timestamp: now.getTime(),\n },\n },\n }\n : undefined;\n\n try {\n await runBackgroundAutomation(\n {\n automation,\n ownerEmail: jobUserEmail,\n orgId: jobOrgId,\n prompt: `[Automation Trigger: ${triggerName}]\nEvent: ${meta.event}\nEvent ID: ${eventMeta.eventId}\nFired at: ${eventMeta.emittedAt}\n\nEvent payload:\n${payloadStr}\n\nExecute the following automation instructions:\n\n${body}`,\n threadTitle: `Trigger: ${triggerName} — ${now.toLocaleDateString()}`,\n runIdPrefix: `automation-${triggerName}`,\n usageLabel: `automation:${triggerName}`,\n usageRefId: eventMeta.eventId,\n requestContext,\n actionCaller: \"automation\",\n actionAutomation: {\n triggerId: resource.id,\n triggerName,\n policyId: meta.delegatedPolicyId,\n },\n },\n _deps,\n );\n\n meta.lastStatus = \"success\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n console.log(`[triggers] \"${triggerName}\" completed successfully`);\n } catch (err) {\n meta.lastStatus = \"error\";\n meta.lastError =\n err instanceof Error ? err.message.slice(0, 200) : \"Unknown error\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n console.error(`[triggers] \"${triggerName}\" failed:`, meta.lastError);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/triggers/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/triggers/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;AA4BZ,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,yBAAyB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AA6JD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA4BhC;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,CA8D9B;AAWD,wBAAgB,wBAAwB;;;;IA8DvC"}
|
package/dist/triggers/routes.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineEventHandler, getMethod, setResponseStatus, } from "h3";
|
|
2
2
|
import { canUpdateAutomationResource } from "../automations/service.js";
|
|
3
3
|
import { getDbExec } from "../db/client.js";
|
|
4
|
-
import { nextOccurrence, describeCron, isValidCron } from "../jobs/cron.js";
|
|
4
|
+
import { nextOccurrence, describeCron, effectiveTimezone, isValidCron, } from "../jobs/cron.js";
|
|
5
5
|
import { buildJobResourceContent, parseJobResource, } from "../jobs/frontmatter.js";
|
|
6
6
|
import { getOrgContext } from "../org/context.js";
|
|
7
7
|
import { organizationIdFromResourceOwner, organizationResourceOwner, resourceGetByPath, resourceListAllOwners, resourcePut, SHARED_OWNER, } from "../resources/store.js";
|
|
@@ -31,11 +31,11 @@ function normalizeAutomationPath(input) {
|
|
|
31
31
|
}
|
|
32
32
|
return path;
|
|
33
33
|
}
|
|
34
|
-
function scheduleDescription(schedule) {
|
|
34
|
+
function scheduleDescription(schedule, timezone) {
|
|
35
35
|
if (!schedule)
|
|
36
36
|
return undefined;
|
|
37
37
|
try {
|
|
38
|
-
return describeCron(schedule);
|
|
38
|
+
return describeCron(schedule, effectiveTimezone(timezone));
|
|
39
39
|
}
|
|
40
40
|
catch {
|
|
41
41
|
return schedule;
|
|
@@ -49,7 +49,7 @@ function nextRunForMeta(meta) {
|
|
|
49
49
|
meta.schedule &&
|
|
50
50
|
isValidCron(meta.schedule)) {
|
|
51
51
|
try {
|
|
52
|
-
return nextOccurrence(meta.schedule).toISOString();
|
|
52
|
+
return nextOccurrence(meta.schedule, undefined, meta.timezone).toISOString();
|
|
53
53
|
}
|
|
54
54
|
catch {
|
|
55
55
|
return undefined;
|
|
@@ -121,7 +121,7 @@ async function resourceToAutomationItem(event, userEmail, resource) {
|
|
|
121
121
|
triggerType: meta.triggerType,
|
|
122
122
|
event: meta.event,
|
|
123
123
|
schedule: meta.schedule || undefined,
|
|
124
|
-
scheduleDescription: scheduleDescription(meta.schedule),
|
|
124
|
+
scheduleDescription: scheduleDescription(meta.schedule, meta.timezone),
|
|
125
125
|
condition: meta.condition,
|
|
126
126
|
mode: meta.mode,
|
|
127
127
|
domain: meta.domain,
|
|
@@ -191,7 +191,7 @@ export async function setAutomationEnabledForOwner(event, userEmail, input) {
|
|
|
191
191
|
meta.triggerType !== "event" &&
|
|
192
192
|
meta.schedule &&
|
|
193
193
|
isValidCron(meta.schedule)) {
|
|
194
|
-
parsed.meta.nextRun = nextOccurrence(meta.schedule).toISOString();
|
|
194
|
+
parsed.meta.nextRun = nextOccurrence(meta.schedule, undefined, meta.timezone).toISOString();
|
|
195
195
|
}
|
|
196
196
|
const updatedContent = buildJobResourceContent(parsed.meta, parsed.body);
|
|
197
197
|
await resourcePut(resource.owner, resource.path, updatedContent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/triggers/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\n\nimport { canUpdateAutomationResource } from \"../automations/service.js\";\nimport { getDbExec } from \"../db/client.js\";\nimport { nextOccurrence, describeCron, isValidCron } from \"../jobs/cron.js\";\nimport {\n buildJobResourceContent,\n parseJobResource,\n type JobFrontmatter,\n} from \"../jobs/frontmatter.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport {\n organizationIdFromResourceOwner,\n organizationResourceOwner,\n resourceGetByPath,\n resourceListAllOwners,\n resourcePut,\n SHARED_OWNER,\n type Resource,\n} from \"../resources/store.js\";\nimport { getSession } from \"../server/auth.js\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport { refreshEventSubscriptions } from \"./dispatcher.js\";\nimport type { TriggerFrontmatter } from \"./types.js\";\n\nexport interface AutomationRouteItem {\n id: string;\n name: string;\n path: string;\n owner: string;\n canUpdate: boolean;\n triggerType: TriggerFrontmatter[\"triggerType\"];\n event?: string;\n schedule?: string;\n scheduleDescription?: string;\n condition?: string;\n mode: TriggerFrontmatter[\"mode\"];\n domain?: string;\n enabled: boolean;\n lastStatus?: TriggerFrontmatter[\"lastStatus\"];\n lastRun?: string;\n lastError?: string;\n nextRun?: string;\n createdBy?: string;\n body: string;\n}\n\ninterface SetAutomationEnabledInput {\n owner?: string;\n path?: string;\n name?: string;\n enabled: boolean;\n}\n\nfunction automationName(path: string): string {\n return path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n}\n\nfunction asTriggerFrontmatter(meta: JobFrontmatter): TriggerFrontmatter {\n return {\n ...meta,\n triggerType: meta.triggerType ?? \"schedule\",\n mode: meta.mode ?? \"agentic\",\n };\n}\n\nfunction normalizeAutomationPath(input: SetAutomationEnabledInput): string {\n const rawPath = input.path ?? (input.name ? `jobs/${input.name}.md` : \"\");\n const path = rawPath.replace(/^\\/+/, \"\");\n if (\n !path.startsWith(\"jobs/\") ||\n !path.endsWith(\".md\") ||\n path.endsWith(\".keep\") ||\n path.includes(\"..\")\n ) {\n throw Object.assign(\n new Error(\"A valid jobs/*.md automation path is required\"),\n {\n statusCode: 400,\n },\n );\n }\n return path;\n}\n\nfunction scheduleDescription(schedule: string | undefined): string | undefined {\n if (!schedule) return undefined;\n try {\n return describeCron(schedule);\n } catch {\n return schedule;\n }\n}\n\nfunction nextRunForMeta(meta: TriggerFrontmatter): string | undefined {\n if (meta.nextRun) return meta.nextRun;\n if (\n meta.enabled &&\n meta.triggerType !== \"event\" &&\n meta.schedule &&\n isValidCron(meta.schedule)\n ) {\n try {\n return nextOccurrence(meta.schedule).toISOString();\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\nasync function currentUserCanUpdateAutomation(\n event: H3Event,\n userEmail: string,\n resource: Resource,\n meta: TriggerFrontmatter,\n): Promise<boolean> {\n const resourceOwner = resource.owner;\n if (resourceOwner === userEmail) return true;\n const resourceOrgId = organizationIdFromResourceOwner(resourceOwner);\n if (resourceOrgId) {\n try {\n const org = await getOrgContext(event);\n if (org.orgId !== resourceOrgId) return false;\n return await canUpdateAutomationResource(\n { userEmail, orgId: resourceOrgId },\n resource,\n );\n } catch {\n return false;\n }\n }\n if (resourceOwner !== SHARED_OWNER) return false;\n\n if (meta.orgId) {\n const activeOrgId = await getOrgContext(event)\n .then((context) => context.orgId)\n .catch(() => null);\n if (activeOrgId !== meta.orgId) return false;\n }\n\n if (\n meta.createdBy &&\n meta.createdBy.toLowerCase() === userEmail.toLowerCase()\n ) {\n return true;\n }\n\n let orgId = meta.orgId;\n if (!orgId) {\n try {\n orgId = (await getOrgContext(event)).orgId ?? undefined;\n } catch {\n orgId = undefined;\n }\n }\n if (!orgId) return false;\n\n try {\n const { rows } = await getDbExec().execute({\n sql: `SELECT role FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,\n args: [orgId, userEmail.toLowerCase()],\n });\n const role = String((rows[0] as any)?.role ?? \"\").toLowerCase();\n return role === \"owner\" || role === \"admin\";\n } catch {\n return false;\n }\n}\n\nasync function resourceToAutomationItem(\n event: H3Event,\n userEmail: string,\n resource: Resource,\n): Promise<AutomationRouteItem> {\n const parsed = parseJobResource(resource.content);\n const meta = asTriggerFrontmatter(parsed.meta);\n return {\n id: resource.id,\n name: automationName(resource.path),\n path: resource.path,\n owner: resource.owner,\n canUpdate: await currentUserCanUpdateAutomation(\n event,\n userEmail,\n resource,\n meta,\n ),\n triggerType: meta.triggerType,\n event: meta.event,\n schedule: meta.schedule || undefined,\n scheduleDescription: scheduleDescription(meta.schedule),\n condition: meta.condition,\n mode: meta.mode,\n domain: meta.domain,\n enabled: meta.enabled,\n lastStatus: meta.lastStatus,\n lastRun: meta.lastRun,\n lastError: meta.lastError,\n nextRun: nextRunForMeta(meta),\n createdBy: meta.createdBy,\n body: parsed.body,\n };\n}\n\nexport async function listAutomationsForOwner(\n event: H3Event,\n userEmail: string,\n): Promise<AutomationRouteItem[]> {\n const allResources = await resourceListAllOwners(\"jobs/\");\n const activeOrgId = await getOrgContext(event)\n .then((context) => context.orgId)\n .catch(() => null);\n const activeOrgOwner = activeOrgId\n ? organizationResourceOwner(activeOrgId)\n : null;\n const resources = allResources.filter((resource) => {\n if (!resource.path.endsWith(\".md\") || resource.path.endsWith(\".keep\")) {\n return false;\n }\n if (\n resource.owner !== userEmail &&\n resource.owner !== SHARED_OWNER &&\n resource.owner !== activeOrgOwner\n ) {\n return false;\n }\n if (resource.owner !== SHARED_OWNER) return true;\n const { meta } = parseJobResource(resource.content);\n return !meta.orgId || meta.orgId === activeOrgId;\n });\n return Promise.all(\n resources.map((resource) =>\n resourceToAutomationItem(event, userEmail, resource),\n ),\n );\n}\n\nexport async function setAutomationEnabledForOwner(\n event: H3Event,\n userEmail: string,\n input: SetAutomationEnabledInput,\n): Promise<AutomationRouteItem> {\n if (typeof input.enabled !== \"boolean\") {\n throw Object.assign(new Error(\"enabled must be a boolean\"), {\n statusCode: 400,\n });\n }\n\n const path = normalizeAutomationPath(input);\n const activeOrgId = await getOrgContext(event)\n .then((context) => context.orgId)\n .catch(() => null);\n const activeOrgOwner = activeOrgId\n ? organizationResourceOwner(activeOrgId)\n : null;\n const requestedOwner =\n input.owner === SHARED_OWNER\n ? SHARED_OWNER\n : input.owner === activeOrgOwner\n ? activeOrgOwner\n : userEmail;\n const resource = await resourceGetByPath(requestedOwner, path);\n if (!resource) {\n throw Object.assign(new Error(\"Automation not found\"), { statusCode: 404 });\n }\n\n const parsed = parseJobResource(resource.content);\n const meta = asTriggerFrontmatter(parsed.meta);\n const allowed = await currentUserCanUpdateAutomation(\n event,\n userEmail,\n resource,\n meta,\n );\n if (!allowed) {\n throw Object.assign(\n new Error(\"Only the automation creator or an org admin can update it.\"),\n { statusCode: 403 },\n );\n }\n\n parsed.meta.enabled = input.enabled;\n if (\n parsed.meta.enabled &&\n meta.triggerType !== \"event\" &&\n meta.schedule &&\n isValidCron(meta.schedule)\n ) {\n parsed.meta.nextRun = nextOccurrence(meta.schedule).toISOString();\n }\n\n const updatedContent = buildJobResourceContent(parsed.meta, parsed.body);\n await resourcePut(resource.owner, resource.path, updatedContent);\n await refreshEventSubscriptions();\n\n return resourceToAutomationItem(event, userEmail, {\n ...resource,\n content: updatedContent,\n });\n}\n\nfunction routeError(event: H3Event, err: unknown, fallback: string) {\n const statusCode =\n typeof (err as any)?.statusCode === \"number\"\n ? (err as any).statusCode\n : 500;\n setResponseStatus(event, statusCode);\n return { error: (err as any)?.message ?? fallback };\n}\n\nexport function createAutomationsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.path || event.url?.pathname || \"\")\n .split(\"?\")[0]\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Unauthenticated\" };\n }\n\n if (\n (pathname === \"fire-test\" || pathname.endsWith(\"/fire-test\")) &&\n method === \"POST\"\n ) {\n try {\n const { emit } = await import(\"../event-bus/index.js\");\n const body = (await readBody(event).catch(() => ({}))) as Record<\n string,\n unknown\n >;\n emit(\n \"test.event.fired\",\n { data: body.data ?? {} },\n { owner: session.email },\n );\n return { ok: true };\n } catch (err) {\n return routeError(event, err, \"Failed to emit test event\");\n }\n }\n\n if (method === \"GET\") {\n try {\n return await listAutomationsForOwner(event, session.email);\n } catch (err) {\n return routeError(event, err, \"Failed to list automations\");\n }\n }\n\n if (method === \"PATCH\" || method === \"PUT\") {\n try {\n const body = (await readBody(event).catch(\n () => ({}),\n )) as SetAutomationEnabledInput | null;\n return await setAutomationEnabledForOwner(event, session.email, {\n owner: body?.owner,\n path: body?.path,\n name: body?.name,\n enabled: (body as any)?.enabled,\n } as SetAutomationEnabledInput);\n } catch (err) {\n return routeError(event, err, \"Failed to update automation\");\n }\n }\n\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/triggers/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n defineEventHandler,\n getMethod,\n setResponseStatus,\n type H3Event,\n} from \"h3\";\n\nimport { canUpdateAutomationResource } from \"../automations/service.js\";\nimport { getDbExec } from \"../db/client.js\";\nimport {\n nextOccurrence,\n describeCron,\n effectiveTimezone,\n isValidCron,\n} from \"../jobs/cron.js\";\nimport {\n buildJobResourceContent,\n parseJobResource,\n type JobFrontmatter,\n} from \"../jobs/frontmatter.js\";\nimport { getOrgContext } from \"../org/context.js\";\nimport {\n organizationIdFromResourceOwner,\n organizationResourceOwner,\n resourceGetByPath,\n resourceListAllOwners,\n resourcePut,\n SHARED_OWNER,\n type Resource,\n} from \"../resources/store.js\";\nimport { getSession } from \"../server/auth.js\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport { refreshEventSubscriptions } from \"./dispatcher.js\";\nimport type { TriggerFrontmatter } from \"./types.js\";\n\nexport interface AutomationRouteItem {\n id: string;\n name: string;\n path: string;\n owner: string;\n canUpdate: boolean;\n triggerType: TriggerFrontmatter[\"triggerType\"];\n event?: string;\n schedule?: string;\n scheduleDescription?: string;\n condition?: string;\n mode: TriggerFrontmatter[\"mode\"];\n domain?: string;\n enabled: boolean;\n lastStatus?: TriggerFrontmatter[\"lastStatus\"];\n lastRun?: string;\n lastError?: string;\n nextRun?: string;\n createdBy?: string;\n body: string;\n}\n\ninterface SetAutomationEnabledInput {\n owner?: string;\n path?: string;\n name?: string;\n enabled: boolean;\n}\n\nfunction automationName(path: string): string {\n return path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n}\n\nfunction asTriggerFrontmatter(meta: JobFrontmatter): TriggerFrontmatter {\n return {\n ...meta,\n triggerType: meta.triggerType ?? \"schedule\",\n mode: meta.mode ?? \"agentic\",\n };\n}\n\nfunction normalizeAutomationPath(input: SetAutomationEnabledInput): string {\n const rawPath = input.path ?? (input.name ? `jobs/${input.name}.md` : \"\");\n const path = rawPath.replace(/^\\/+/, \"\");\n if (\n !path.startsWith(\"jobs/\") ||\n !path.endsWith(\".md\") ||\n path.endsWith(\".keep\") ||\n path.includes(\"..\")\n ) {\n throw Object.assign(\n new Error(\"A valid jobs/*.md automation path is required\"),\n {\n statusCode: 400,\n },\n );\n }\n return path;\n}\n\nfunction scheduleDescription(schedule?: string, timezone?: string) {\n if (!schedule) return undefined;\n try {\n return describeCron(schedule, effectiveTimezone(timezone));\n } catch {\n return schedule;\n }\n}\n\nfunction nextRunForMeta(meta: TriggerFrontmatter): string | undefined {\n if (meta.nextRun) return meta.nextRun;\n if (\n meta.enabled &&\n meta.triggerType !== \"event\" &&\n meta.schedule &&\n isValidCron(meta.schedule)\n ) {\n try {\n return nextOccurrence(\n meta.schedule,\n undefined,\n meta.timezone,\n ).toISOString();\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\nasync function currentUserCanUpdateAutomation(\n event: H3Event,\n userEmail: string,\n resource: Resource,\n meta: TriggerFrontmatter,\n): Promise<boolean> {\n const resourceOwner = resource.owner;\n if (resourceOwner === userEmail) return true;\n const resourceOrgId = organizationIdFromResourceOwner(resourceOwner);\n if (resourceOrgId) {\n try {\n const org = await getOrgContext(event);\n if (org.orgId !== resourceOrgId) return false;\n return await canUpdateAutomationResource(\n { userEmail, orgId: resourceOrgId },\n resource,\n );\n } catch {\n return false;\n }\n }\n if (resourceOwner !== SHARED_OWNER) return false;\n\n if (meta.orgId) {\n const activeOrgId = await getOrgContext(event)\n .then((context) => context.orgId)\n .catch(() => null);\n if (activeOrgId !== meta.orgId) return false;\n }\n\n if (\n meta.createdBy &&\n meta.createdBy.toLowerCase() === userEmail.toLowerCase()\n ) {\n return true;\n }\n\n let orgId = meta.orgId;\n if (!orgId) {\n try {\n orgId = (await getOrgContext(event)).orgId ?? undefined;\n } catch {\n orgId = undefined;\n }\n }\n if (!orgId) return false;\n\n try {\n const { rows } = await getDbExec().execute({\n sql: `SELECT role FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,\n args: [orgId, userEmail.toLowerCase()],\n });\n const role = String((rows[0] as any)?.role ?? \"\").toLowerCase();\n return role === \"owner\" || role === \"admin\";\n } catch {\n return false;\n }\n}\n\nasync function resourceToAutomationItem(\n event: H3Event,\n userEmail: string,\n resource: Resource,\n): Promise<AutomationRouteItem> {\n const parsed = parseJobResource(resource.content);\n const meta = asTriggerFrontmatter(parsed.meta);\n return {\n id: resource.id,\n name: automationName(resource.path),\n path: resource.path,\n owner: resource.owner,\n canUpdate: await currentUserCanUpdateAutomation(\n event,\n userEmail,\n resource,\n meta,\n ),\n triggerType: meta.triggerType,\n event: meta.event,\n schedule: meta.schedule || undefined,\n scheduleDescription: scheduleDescription(meta.schedule, meta.timezone),\n condition: meta.condition,\n mode: meta.mode,\n domain: meta.domain,\n enabled: meta.enabled,\n lastStatus: meta.lastStatus,\n lastRun: meta.lastRun,\n lastError: meta.lastError,\n nextRun: nextRunForMeta(meta),\n createdBy: meta.createdBy,\n body: parsed.body,\n };\n}\n\nexport async function listAutomationsForOwner(\n event: H3Event,\n userEmail: string,\n): Promise<AutomationRouteItem[]> {\n const allResources = await resourceListAllOwners(\"jobs/\");\n const activeOrgId = await getOrgContext(event)\n .then((context) => context.orgId)\n .catch(() => null);\n const activeOrgOwner = activeOrgId\n ? organizationResourceOwner(activeOrgId)\n : null;\n const resources = allResources.filter((resource) => {\n if (!resource.path.endsWith(\".md\") || resource.path.endsWith(\".keep\")) {\n return false;\n }\n if (\n resource.owner !== userEmail &&\n resource.owner !== SHARED_OWNER &&\n resource.owner !== activeOrgOwner\n ) {\n return false;\n }\n if (resource.owner !== SHARED_OWNER) return true;\n const { meta } = parseJobResource(resource.content);\n return !meta.orgId || meta.orgId === activeOrgId;\n });\n return Promise.all(\n resources.map((resource) =>\n resourceToAutomationItem(event, userEmail, resource),\n ),\n );\n}\n\nexport async function setAutomationEnabledForOwner(\n event: H3Event,\n userEmail: string,\n input: SetAutomationEnabledInput,\n): Promise<AutomationRouteItem> {\n if (typeof input.enabled !== \"boolean\") {\n throw Object.assign(new Error(\"enabled must be a boolean\"), {\n statusCode: 400,\n });\n }\n\n const path = normalizeAutomationPath(input);\n const activeOrgId = await getOrgContext(event)\n .then((context) => context.orgId)\n .catch(() => null);\n const activeOrgOwner = activeOrgId\n ? organizationResourceOwner(activeOrgId)\n : null;\n const requestedOwner =\n input.owner === SHARED_OWNER\n ? SHARED_OWNER\n : input.owner === activeOrgOwner\n ? activeOrgOwner\n : userEmail;\n const resource = await resourceGetByPath(requestedOwner, path);\n if (!resource) {\n throw Object.assign(new Error(\"Automation not found\"), { statusCode: 404 });\n }\n\n const parsed = parseJobResource(resource.content);\n const meta = asTriggerFrontmatter(parsed.meta);\n const allowed = await currentUserCanUpdateAutomation(\n event,\n userEmail,\n resource,\n meta,\n );\n if (!allowed) {\n throw Object.assign(\n new Error(\"Only the automation creator or an org admin can update it.\"),\n { statusCode: 403 },\n );\n }\n\n parsed.meta.enabled = input.enabled;\n if (\n parsed.meta.enabled &&\n meta.triggerType !== \"event\" &&\n meta.schedule &&\n isValidCron(meta.schedule)\n ) {\n parsed.meta.nextRun = nextOccurrence(\n meta.schedule,\n undefined,\n meta.timezone,\n ).toISOString();\n }\n\n const updatedContent = buildJobResourceContent(parsed.meta, parsed.body);\n await resourcePut(resource.owner, resource.path, updatedContent);\n await refreshEventSubscriptions();\n\n return resourceToAutomationItem(event, userEmail, {\n ...resource,\n content: updatedContent,\n });\n}\n\nfunction routeError(event: H3Event, err: unknown, fallback: string) {\n const statusCode =\n typeof (err as any)?.statusCode === \"number\"\n ? (err as any).statusCode\n : 500;\n setResponseStatus(event, statusCode);\n return { error: (err as any)?.message ?? fallback };\n}\n\nexport function createAutomationsHandler() {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n const pathname = (event.path || event.url?.pathname || \"\")\n .split(\"?\")[0]\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Unauthenticated\" };\n }\n\n if (\n (pathname === \"fire-test\" || pathname.endsWith(\"/fire-test\")) &&\n method === \"POST\"\n ) {\n try {\n const { emit } = await import(\"../event-bus/index.js\");\n const body = (await readBody(event).catch(() => ({}))) as Record<\n string,\n unknown\n >;\n emit(\n \"test.event.fired\",\n { data: body.data ?? {} },\n { owner: session.email },\n );\n return { ok: true };\n } catch (err) {\n return routeError(event, err, \"Failed to emit test event\");\n }\n }\n\n if (method === \"GET\") {\n try {\n return await listAutomationsForOwner(event, session.email);\n } catch (err) {\n return routeError(event, err, \"Failed to list automations\");\n }\n }\n\n if (method === \"PATCH\" || method === \"PUT\") {\n try {\n const body = (await readBody(event).catch(\n () => ({}),\n )) as SetAutomationEnabledInput | null;\n return await setAutomationEnabledForOwner(event, session.email, {\n owner: body?.owner,\n path: body?.path,\n name: body?.name,\n enabled: (body as any)?.enabled,\n } as SetAutomationEnabledInput);\n } catch (err) {\n return routeError(event, err, \"Failed to update automation\");\n }\n }\n\n setResponseStatus(event, 405);\n return { error: \"Method not allowed\" };\n });\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ViteUserConfig } from "vitest/config";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the worker lid from the environment, throwing on anything that is
|
|
4
|
+
* neither a percentage nor a worker count. A bad value must not quietly become
|
|
5
|
+
* the default — that reads as "configured" while running at some other size.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveMaxWorkers(env?: NodeJS.ProcessEnv): string | number;
|
|
8
|
+
declare const vitestBaseConfig: ViteUserConfig;
|
|
9
|
+
export default vitestBaseConfig;
|
|
10
|
+
//# sourceMappingURL=vitest-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-config.d.ts","sourceRoot":"","sources":["../src/vitest-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAuBpD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,MAAM,CA6BjB;AAED,QAAA,MAAM,gBAAgB,EAAE,cAIvB,CAAC;eAEa,gBAAgB"}
|