@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
|
@@ -82,6 +82,31 @@ const _eventSubscriptions = new Map<string, string>();
|
|
|
82
82
|
const _dispatchingTriggers = new Set<string>();
|
|
83
83
|
let _deps: TriggerDispatcherDeps | null = null;
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Record that a tick evaluated this trigger and declined to dispatch it.
|
|
87
|
+
* `lastRun` stays untouched — nothing ran — and an unchanged outcome is not
|
|
88
|
+
* re-persisted, so a permanently blocked trigger neither reports phantom runs
|
|
89
|
+
* nor rewrites its resource on every matching event.
|
|
90
|
+
*/
|
|
91
|
+
async function recordTriggerSkip(
|
|
92
|
+
resource: Resource,
|
|
93
|
+
meta: TriggerFrontmatter,
|
|
94
|
+
body: string,
|
|
95
|
+
status: "skipped" | "error",
|
|
96
|
+
reason: string | undefined,
|
|
97
|
+
): Promise<void> {
|
|
98
|
+
const unchanged = meta.lastStatus === status && meta.lastError === reason;
|
|
99
|
+
meta.lastCheck = new Date().toISOString();
|
|
100
|
+
meta.lastStatus = status;
|
|
101
|
+
meta.lastError = reason;
|
|
102
|
+
if (unchanged) return;
|
|
103
|
+
await resourcePut(
|
|
104
|
+
resource.owner,
|
|
105
|
+
resource.path,
|
|
106
|
+
buildTriggerContent(meta, body),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
85
110
|
/**
|
|
86
111
|
* Initialize the trigger dispatcher. Call once at server startup.
|
|
87
112
|
* Loads all event-triggered jobs and subscribes to their events.
|
|
@@ -173,25 +198,22 @@ async function handleEvent(
|
|
|
173
198
|
meta,
|
|
174
199
|
);
|
|
175
200
|
} catch {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
resource.path,
|
|
183
|
-
buildTriggerContent(meta, body),
|
|
201
|
+
await recordTriggerSkip(
|
|
202
|
+
resource,
|
|
203
|
+
meta,
|
|
204
|
+
body,
|
|
205
|
+
"skipped",
|
|
206
|
+
"Could not verify the automation execution identity.",
|
|
184
207
|
);
|
|
185
208
|
continue;
|
|
186
209
|
}
|
|
187
210
|
if (!resolved.ok) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
buildTriggerContent(meta, body),
|
|
211
|
+
await recordTriggerSkip(
|
|
212
|
+
resource,
|
|
213
|
+
meta,
|
|
214
|
+
body,
|
|
215
|
+
"skipped",
|
|
216
|
+
resolved.reason,
|
|
195
217
|
);
|
|
196
218
|
continue;
|
|
197
219
|
}
|
|
@@ -206,13 +228,12 @@ async function handleEvent(
|
|
|
206
228
|
const userApiKey = await getOwnerActiveApiKey(owner);
|
|
207
229
|
const apiKey = userApiKey || _deps.apiKey;
|
|
208
230
|
if (!apiKey) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
buildTriggerContent(meta, body),
|
|
231
|
+
await recordTriggerSkip(
|
|
232
|
+
resource,
|
|
233
|
+
meta,
|
|
234
|
+
body,
|
|
235
|
+
"error",
|
|
236
|
+
"No API key is available for this automation",
|
|
216
237
|
);
|
|
217
238
|
console.warn(`[triggers] ${meta.lastError}: "${resource.path}"`);
|
|
218
239
|
continue;
|
|
@@ -221,14 +242,7 @@ async function handleEvent(
|
|
|
221
242
|
// Evaluate condition
|
|
222
243
|
const matches = await evaluateCondition(meta.condition, payload, apiKey);
|
|
223
244
|
if (!matches) {
|
|
224
|
-
meta
|
|
225
|
-
meta.lastStatus = "skipped";
|
|
226
|
-
meta.lastError = undefined;
|
|
227
|
-
await resourcePut(
|
|
228
|
-
resource.owner,
|
|
229
|
-
resource.path,
|
|
230
|
-
buildTriggerContent(meta, body),
|
|
231
|
-
);
|
|
245
|
+
await recordTriggerSkip(resource, meta, body, "skipped", undefined);
|
|
232
246
|
continue;
|
|
233
247
|
}
|
|
234
248
|
|
|
@@ -7,7 +7,12 @@ import {
|
|
|
7
7
|
|
|
8
8
|
import { canUpdateAutomationResource } from "../automations/service.js";
|
|
9
9
|
import { getDbExec } from "../db/client.js";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
nextOccurrence,
|
|
12
|
+
describeCron,
|
|
13
|
+
effectiveTimezone,
|
|
14
|
+
isValidCron,
|
|
15
|
+
} from "../jobs/cron.js";
|
|
11
16
|
import {
|
|
12
17
|
buildJobResourceContent,
|
|
13
18
|
parseJobResource,
|
|
@@ -88,10 +93,10 @@ function normalizeAutomationPath(input: SetAutomationEnabledInput): string {
|
|
|
88
93
|
return path;
|
|
89
94
|
}
|
|
90
95
|
|
|
91
|
-
function scheduleDescription(schedule
|
|
96
|
+
function scheduleDescription(schedule?: string, timezone?: string) {
|
|
92
97
|
if (!schedule) return undefined;
|
|
93
98
|
try {
|
|
94
|
-
return describeCron(schedule);
|
|
99
|
+
return describeCron(schedule, effectiveTimezone(timezone));
|
|
95
100
|
} catch {
|
|
96
101
|
return schedule;
|
|
97
102
|
}
|
|
@@ -106,7 +111,11 @@ function nextRunForMeta(meta: TriggerFrontmatter): string | undefined {
|
|
|
106
111
|
isValidCron(meta.schedule)
|
|
107
112
|
) {
|
|
108
113
|
try {
|
|
109
|
-
return nextOccurrence(
|
|
114
|
+
return nextOccurrence(
|
|
115
|
+
meta.schedule,
|
|
116
|
+
undefined,
|
|
117
|
+
meta.timezone,
|
|
118
|
+
).toISOString();
|
|
110
119
|
} catch {
|
|
111
120
|
return undefined;
|
|
112
121
|
}
|
|
@@ -194,7 +203,7 @@ async function resourceToAutomationItem(
|
|
|
194
203
|
triggerType: meta.triggerType,
|
|
195
204
|
event: meta.event,
|
|
196
205
|
schedule: meta.schedule || undefined,
|
|
197
|
-
scheduleDescription: scheduleDescription(meta.schedule),
|
|
206
|
+
scheduleDescription: scheduleDescription(meta.schedule, meta.timezone),
|
|
198
207
|
condition: meta.condition,
|
|
199
208
|
mode: meta.mode,
|
|
200
209
|
domain: meta.domain,
|
|
@@ -292,7 +301,11 @@ export async function setAutomationEnabledForOwner(
|
|
|
292
301
|
meta.schedule &&
|
|
293
302
|
isValidCron(meta.schedule)
|
|
294
303
|
) {
|
|
295
|
-
parsed.meta.nextRun = nextOccurrence(
|
|
304
|
+
parsed.meta.nextRun = nextOccurrence(
|
|
305
|
+
meta.schedule,
|
|
306
|
+
undefined,
|
|
307
|
+
meta.timezone,
|
|
308
|
+
).toISOString();
|
|
296
309
|
}
|
|
297
310
|
|
|
298
311
|
const updatedContent = buildJobResourceContent(parsed.meta, parsed.body);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ViteUserConfig } from "vitest/config";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base vitest config that caps a suite's worker pool at a share of the machine.
|
|
5
|
+
*
|
|
6
|
+
* Vitest sizes its pool at `cores - 1` with no awareness of peer processes, so
|
|
7
|
+
* several suites running at once — concurrent agent sessions, or a workspace
|
|
8
|
+
* running packages in parallel — each try to claim the whole box. Set
|
|
9
|
+
* `VITEST_CONCURRENCY` to a percentage or a worker count to change the lid; a
|
|
10
|
+
* package that needs its own value sets `test.maxWorkers` in its own config,
|
|
11
|
+
* which wins the merge.
|
|
12
|
+
*
|
|
13
|
+
* This ships from core rather than living at the monorepo root because template
|
|
14
|
+
* directories are scaffolded out verbatim as standalone apps — a config that
|
|
15
|
+
* reaches above the template would resolve to nothing in the generated app.
|
|
16
|
+
*
|
|
17
|
+
* Keep this module free of runtime imports so loading it costs a config file
|
|
18
|
+
* nothing beyond reading the environment.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const DEFAULT_MAX_WORKERS = "25%";
|
|
22
|
+
const ENV_KEYS = ["VITEST_CONCURRENCY", "AGENT_NATIVE_VITEST_CONCURRENCY"];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the worker lid from the environment, throwing on anything that is
|
|
26
|
+
* neither a percentage nor a worker count. A bad value must not quietly become
|
|
27
|
+
* the default — that reads as "configured" while running at some other size.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveMaxWorkers(
|
|
30
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
31
|
+
): string | number {
|
|
32
|
+
const rawMaxWorkers = env.VITEST_MAX_WORKERS;
|
|
33
|
+
if (rawMaxWorkers?.includes("%")) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`VITEST_MAX_WORKERS=${rawMaxWorkers} is not a percentage to vitest — it parses as ` +
|
|
36
|
+
`${Number.parseInt(rawMaxWorkers)} workers. Use VITEST_CONCURRENCY for percentages, ` +
|
|
37
|
+
`or an integer for VITEST_MAX_WORKERS.`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const key = ENV_KEYS.find((name) => env[name]);
|
|
42
|
+
if (!key) return DEFAULT_MAX_WORKERS;
|
|
43
|
+
|
|
44
|
+
const value = env[key]!.trim();
|
|
45
|
+
if (/^\d+%$/.test(value)) {
|
|
46
|
+
const percent = Number.parseInt(value);
|
|
47
|
+
if (percent < 1 || percent > 100) {
|
|
48
|
+
throw new Error(`${key}=${value} is out of range — use 1% to 100%.`);
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const count = Number(value);
|
|
54
|
+
if (!Number.isInteger(count) || count < 1) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`${key}=${value} is not a percentage like "25%" or a worker count like "2".`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return count;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const vitestBaseConfig: ViteUserConfig = {
|
|
63
|
+
test: {
|
|
64
|
+
maxWorkers: resolveMaxWorkers(),
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default vitestBaseConfig;
|
|
@@ -3,6 +3,8 @@ import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
|
|
|
3
3
|
import { TeamPage } from "@agent-native/core/client/org";
|
|
4
4
|
import {
|
|
5
5
|
AccountSettingsCard,
|
|
6
|
+
SettingsGroup,
|
|
7
|
+
SettingsRow,
|
|
6
8
|
SettingsTabsPage,
|
|
7
9
|
useAgentSettingsTabs,
|
|
8
10
|
type SettingsTabItem,
|
|
@@ -68,47 +70,41 @@ export default function Settings() {
|
|
|
68
70
|
generalSearchEntries={generalSearchEntries}
|
|
69
71
|
general={
|
|
70
72
|
<div className="mx-auto w-full max-w-2xl space-y-6">
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<Link to="/catalog">
|
|
107
|
-
{t("settings.openDashboardTemplates")}
|
|
108
|
-
</Link>
|
|
109
|
-
</Button>
|
|
110
|
-
</CardContent>
|
|
111
|
-
</Card>
|
|
73
|
+
<SettingsGroup className="bg-card border-border/50">
|
|
74
|
+
<SettingsRow
|
|
75
|
+
id="credentials"
|
|
76
|
+
label={t("settings.credentials")}
|
|
77
|
+
description={t("settings.credentialsDescription")}
|
|
78
|
+
control={
|
|
79
|
+
<Button variant="outline" size="sm" asChild>
|
|
80
|
+
<Link to="/data-sources">
|
|
81
|
+
{t("settings.manageDataSources")}
|
|
82
|
+
</Link>
|
|
83
|
+
</Button>
|
|
84
|
+
}
|
|
85
|
+
/>
|
|
86
|
+
<SettingsRow
|
|
87
|
+
id="dashboard-templates"
|
|
88
|
+
label={t("settings.dashboardTemplates")}
|
|
89
|
+
description={t("settings.dashboardTemplatesDescription")}
|
|
90
|
+
control={
|
|
91
|
+
<Button variant="outline" size="sm" asChild>
|
|
92
|
+
<Link to="/catalog">
|
|
93
|
+
{t("settings.openDashboardTemplates")}
|
|
94
|
+
</Link>
|
|
95
|
+
</Button>
|
|
96
|
+
}
|
|
97
|
+
/>
|
|
98
|
+
<SettingsRow
|
|
99
|
+
id="language"
|
|
100
|
+
label={t("settings.languageTitle")}
|
|
101
|
+
control={
|
|
102
|
+
<div className="w-56">
|
|
103
|
+
<LanguagePicker label={t("settings.languageLabel")} />
|
|
104
|
+
</div>
|
|
105
|
+
}
|
|
106
|
+
/>
|
|
107
|
+
</SettingsGroup>
|
|
112
108
|
|
|
113
109
|
{replayStorageStatus.data?.configured ? (
|
|
114
110
|
<Card
|
|
@@ -129,18 +125,6 @@ export default function Settings() {
|
|
|
129
125
|
</Card>
|
|
130
126
|
) : null}
|
|
131
127
|
|
|
132
|
-
<Card id="language" className="bg-card border-border/50 scroll-mt-16">
|
|
133
|
-
<CardHeader>
|
|
134
|
-
<CardTitle className="text-base">
|
|
135
|
-
{t("settings.languageTitle")}
|
|
136
|
-
</CardTitle>
|
|
137
|
-
</CardHeader>
|
|
138
|
-
<CardContent className="max-w-xs space-y-1.5">
|
|
139
|
-
<Label>{t("settings.languageLabel")}</Label>
|
|
140
|
-
<LanguagePicker label={t("settings.languageLabel")} />
|
|
141
|
-
</CardContent>
|
|
142
|
-
</Card>
|
|
143
|
-
|
|
144
128
|
<Card id="about" className="bg-card border-border/50 scroll-mt-16">
|
|
145
129
|
<CardHeader>
|
|
146
130
|
<CardTitle className="text-base">{t("settings.about")}</CardTitle>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { notifyWithDelivery } from "@agent-native/core/notifications";
|
|
1
2
|
import { runWithRequestContext } from "@agent-native/core/server/request-context";
|
|
2
3
|
|
|
3
4
|
import { sendDashboardReportSubscription } from "../lib/dashboard-report";
|
|
@@ -57,6 +58,46 @@ async function persistDashboardReportCaptureOutcome(
|
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Tell the owner when a scheduled report is finally given up on. Retries stay
|
|
63
|
+
* silent — only an exhausted retry window means the report they expected will
|
|
64
|
+
* never arrive, and a log line alone leaves them waiting on nothing.
|
|
65
|
+
*/
|
|
66
|
+
async function notifyDashboardReportGaveUp(
|
|
67
|
+
sub: {
|
|
68
|
+
id: string;
|
|
69
|
+
ownerEmail: string;
|
|
70
|
+
orgId?: string | null;
|
|
71
|
+
dashboardId?: string;
|
|
72
|
+
},
|
|
73
|
+
reason: string,
|
|
74
|
+
): Promise<void> {
|
|
75
|
+
try {
|
|
76
|
+
await notifyWithDelivery(
|
|
77
|
+
{
|
|
78
|
+
severity: "warning",
|
|
79
|
+
title: "Scheduled dashboard report failed",
|
|
80
|
+
body: `The scheduled report for subscription ${sub.id} could not be delivered: ${reason}`,
|
|
81
|
+
channels: ["inbox", "email"],
|
|
82
|
+
metadata: {
|
|
83
|
+
kind: "dashboard_report_failure",
|
|
84
|
+
subscriptionId: sub.id,
|
|
85
|
+
path: "/dashboard-reports",
|
|
86
|
+
// The email channel is a no-op without explicit recipients.
|
|
87
|
+
emailRecipients: [sub.ownerEmail],
|
|
88
|
+
emailSubject: "Your scheduled dashboard report did not send",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{ owner: sub.ownerEmail },
|
|
92
|
+
);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
console.error(
|
|
95
|
+
`[dashboard-report] Could not notify owner of subscription ${sub.id} about the failure:`,
|
|
96
|
+
err instanceof Error ? err.message : String(err),
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
60
101
|
function maxReportsPerSweep(): number {
|
|
61
102
|
if (serverlessDashboardReportRuntime()) {
|
|
62
103
|
return SERVERLESS_MAX_REPORTS_PER_SWEEP;
|
|
@@ -127,6 +168,7 @@ export async function runDashboardReportsOnce(): Promise<{
|
|
|
127
168
|
});
|
|
128
169
|
} else {
|
|
129
170
|
await persistDashboardReportResult(sub, "error", retryMessage);
|
|
171
|
+
await notifyDashboardReportGaveUp(sub, degradedReason);
|
|
130
172
|
}
|
|
131
173
|
continue;
|
|
132
174
|
}
|
|
@@ -155,6 +197,7 @@ export async function runDashboardReportsOnce(): Promise<{
|
|
|
155
197
|
});
|
|
156
198
|
} else {
|
|
157
199
|
await persistDashboardReportResult(sub, "error", message);
|
|
200
|
+
await notifyDashboardReportGaveUp(sub, message);
|
|
158
201
|
}
|
|
159
202
|
}
|
|
160
203
|
}
|
|
@@ -996,12 +996,16 @@ async function notifyNewIssue(
|
|
|
996
996
|
severity: issue.level === "fatal" ? "critical" : "warning",
|
|
997
997
|
title: `New error: ${issue.title}`,
|
|
998
998
|
body: "A new JavaScript error was captured in your app.",
|
|
999
|
-
channels: ["inbox"],
|
|
999
|
+
channels: ["inbox", "email"],
|
|
1000
1000
|
metadata: {
|
|
1001
1001
|
kind: "error_issue",
|
|
1002
1002
|
issueId: issue.issueId,
|
|
1003
1003
|
level: issue.level,
|
|
1004
1004
|
path: `/monitoring?view=errors&issue=${issue.issueId}`,
|
|
1005
|
+
// The email channel is a no-op without explicit recipients, so a
|
|
1006
|
+
// captured issue would otherwise never leave the in-app inbox.
|
|
1007
|
+
emailRecipients: [scope.ownerEmail],
|
|
1008
|
+
emailSubject: `New error in your app: ${issue.title}`,
|
|
1005
1009
|
},
|
|
1006
1010
|
},
|
|
1007
1011
|
// The notification inbox is owner-scoped; the issue's owner is the analytics
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import baseConfig from "@agent-native/core/vitest-config";
|
|
4
|
+
import { defineConfig, mergeConfig } from "vitest/config";
|
|
4
5
|
|
|
5
|
-
export default
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export default mergeConfig(
|
|
7
|
+
baseConfig,
|
|
8
|
+
defineConfig({
|
|
9
|
+
resolve: {
|
|
10
|
+
alias: {
|
|
11
|
+
"@": path.resolve(__dirname, "./app"),
|
|
12
|
+
"@shared": path.resolve(__dirname, "./shared"),
|
|
13
|
+
},
|
|
10
14
|
},
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
},
|
|
16
|
-
|
|
15
|
+
test: {
|
|
16
|
+
include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
|
|
17
|
+
exclude: ["**/node_modules/**", "**/.git/**", "**/dist/**"],
|
|
18
|
+
},
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
@@ -4,6 +4,7 @@ import { eq } from "drizzle-orm";
|
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
6
6
|
import { getDb, schema } from "../server/db/index.js";
|
|
7
|
+
import { notifyGenerationRunFinished } from "../server/lib/generation-run-notifications.js";
|
|
7
8
|
import { nowIso, parseJson } from "../server/lib/json.js";
|
|
8
9
|
import { completeVideoGenerationRun } from "../server/lib/video-runs.js";
|
|
9
10
|
import { serializeAsset, serializeGenerationRun } from "./_helpers.js";
|
|
@@ -88,6 +89,7 @@ async function refreshImageRun(
|
|
|
88
89
|
.set({ status: "completed", completedAt })
|
|
89
90
|
.where(eq(schema.assetGenerationRuns.id, run.id));
|
|
90
91
|
nextRun = { ...run, status: "completed", completedAt };
|
|
92
|
+
await notifyGenerationRunFinished(nextRun, "completed");
|
|
91
93
|
}
|
|
92
94
|
await syncImageVariantSlot(nextRun, "ready", { asset: outputAsset });
|
|
93
95
|
return { run: nextRun, assets };
|
|
@@ -119,6 +121,7 @@ async function refreshImageRun(
|
|
|
119
121
|
await syncImageVariantSlot(failedRun, "failed", {
|
|
120
122
|
error: INTERRUPTED_IMAGE_RUN_ERROR,
|
|
121
123
|
});
|
|
124
|
+
await notifyGenerationRunFinished(failedRun, "failed");
|
|
122
125
|
return { run: failedRun, assets: [] };
|
|
123
126
|
}
|
|
124
127
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@agent-native/toolkit/ui/switch";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { agentNativePath } from "@agent-native/core/client/api-path";
|
|
2
|
+
import type { AssetsUserPrefs } from "@shared/assets-user-prefs";
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
|
|
5
|
+
const PREFS_PATH = "/_agent-native/assets/user-prefs";
|
|
6
|
+
|
|
7
|
+
export interface AssetsPrefsState {
|
|
8
|
+
prefs: AssetsUserPrefs;
|
|
9
|
+
loading: boolean;
|
|
10
|
+
/** Applies the patch optimistically and rolls back if the write fails. */
|
|
11
|
+
save: (patch: AssetsUserPrefs) => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function useAssetsPrefs(): AssetsPrefsState {
|
|
15
|
+
const [prefs, setPrefs] = useState<AssetsUserPrefs>({});
|
|
16
|
+
const [loading, setLoading] = useState(true);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
let cancelled = false;
|
|
20
|
+
void (async () => {
|
|
21
|
+
try {
|
|
22
|
+
const res = await fetch(agentNativePath(PREFS_PATH));
|
|
23
|
+
const json = res.ok ? await res.json() : null;
|
|
24
|
+
if (cancelled) return;
|
|
25
|
+
if (json && typeof json === "object" && !("error" in json)) {
|
|
26
|
+
setPrefs(json as AssetsUserPrefs);
|
|
27
|
+
}
|
|
28
|
+
} finally {
|
|
29
|
+
if (!cancelled) setLoading(false);
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
32
|
+
return () => {
|
|
33
|
+
cancelled = true;
|
|
34
|
+
};
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
const save = useCallback(
|
|
38
|
+
async (patch: AssetsUserPrefs) => {
|
|
39
|
+
const previous = prefs;
|
|
40
|
+
setPrefs((current) => ({ ...current, ...patch }));
|
|
41
|
+
const res = await fetch(agentNativePath(PREFS_PATH), {
|
|
42
|
+
method: "PUT",
|
|
43
|
+
headers: { "Content-Type": "application/json" },
|
|
44
|
+
body: JSON.stringify(patch),
|
|
45
|
+
});
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
setPrefs(previous);
|
|
48
|
+
throw new Error(`Save failed (${res.status})`);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
[prefs],
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return { prefs, loading, save };
|
|
55
|
+
}
|
|
@@ -628,6 +628,9 @@ const enUS = {
|
|
|
628
628
|
languageDescription:
|
|
629
629
|
"Choose the interface language for this Assets workspace.",
|
|
630
630
|
languageLabel: "Interface language",
|
|
631
|
+
emailNotifications: "Email notifications",
|
|
632
|
+
emailNotificationsDescription:
|
|
633
|
+
"Get an email when a generation you started finishes or fails.",
|
|
631
634
|
setupTitle: "Assets setup",
|
|
632
635
|
setupDescription: "Two essentials: generation and durable storage.",
|
|
633
636
|
setupReady: "ready",
|
|
@@ -3926,6 +3929,9 @@ export const messagesByLocale = {
|
|
|
3926
3929
|
languageTitle: "语言",
|
|
3927
3930
|
languageDescription: "选择此 Assets 工作区的界面语言。",
|
|
3928
3931
|
languageLabel: "界面语言",
|
|
3932
|
+
emailNotifications: "邮件通知",
|
|
3933
|
+
emailNotificationsDescription:
|
|
3934
|
+
"当你发起的生成完成或失败时,收到邮件通知。",
|
|
3929
3935
|
|
|
3930
3936
|
addBuilderGeminiOrOpenAI:
|
|
3931
3937
|
"在生成新资产之前添加 Builder、Gemini 或 OpenAI。",
|
|
@@ -4727,6 +4733,9 @@ export const messagesByLocale = {
|
|
|
4727
4733
|
languageDescription:
|
|
4728
4734
|
"Elige el idioma de la interfaz para este workspace.",
|
|
4729
4735
|
languageLabel: "Idioma de la interfaz",
|
|
4736
|
+
emailNotifications: "Notificaciones por correo",
|
|
4737
|
+
emailNotificationsDescription:
|
|
4738
|
+
"Recibe un correo cuando una generación que iniciaste termine o falle.",
|
|
4730
4739
|
|
|
4731
4740
|
addBuilderGeminiOrOpenAI:
|
|
4732
4741
|
"Agregue Builder, Gemini o OpenAI antes de generar nuevos activos.",
|
|
@@ -5191,6 +5200,9 @@ export const messagesByLocale = {
|
|
|
5191
5200
|
languageDescription:
|
|
5192
5201
|
"Choisissez la langue de l'interface pour cet espace Assets.",
|
|
5193
5202
|
languageLabel: "Langue de l'interface",
|
|
5203
|
+
emailNotifications: "Notifications par e-mail",
|
|
5204
|
+
emailNotificationsDescription:
|
|
5205
|
+
"Recevez un e-mail lorsqu’une génération que vous avez lancée se termine ou échoue.",
|
|
5194
5206
|
|
|
5195
5207
|
addBuilderGeminiOrOpenAI:
|
|
5196
5208
|
"Ajoutez Builder, Gemini ou OpenAI avant de générer de nouveaux actifs.",
|
|
@@ -5644,6 +5656,9 @@ export const messagesByLocale = {
|
|
|
5644
5656
|
languageDescription:
|
|
5645
5657
|
"Wähle die Oberflächensprache für diesen Assets-Workspace.",
|
|
5646
5658
|
languageLabel: "Oberflächensprache",
|
|
5659
|
+
emailNotifications: "E-Mail-Benachrichtigungen",
|
|
5660
|
+
emailNotificationsDescription:
|
|
5661
|
+
"Erhalte eine E-Mail, wenn eine von dir gestartete Generierung fertig ist oder fehlschlägt.",
|
|
5647
5662
|
setupTitle: "Assets-Einrichtung",
|
|
5648
5663
|
setupDescription:
|
|
5649
5664
|
"Zwei Grundlagen: Generierung und dauerhafter Speicher.",
|
|
@@ -5993,6 +6008,9 @@ export const messagesByLocale = {
|
|
|
5993
6008
|
languageDescription:
|
|
5994
6009
|
"この Assets ワークスペースのインターフェース言語を選択します。",
|
|
5995
6010
|
languageLabel: "インターフェース言語",
|
|
6011
|
+
emailNotifications: "メール通知",
|
|
6012
|
+
emailNotificationsDescription:
|
|
6013
|
+
"開始した生成が完了または失敗したときにメールを受け取ります。",
|
|
5996
6014
|
setupTitle: "Assets の設定",
|
|
5997
6015
|
setupDescription: "必要なものは生成と永続ストレージの 2 つです。",
|
|
5998
6016
|
setupReady: "準備完了",
|
|
@@ -6338,6 +6356,9 @@ export const messagesByLocale = {
|
|
|
6338
6356
|
languageDescription:
|
|
6339
6357
|
"이 Assets 워크스페이스의 인터페이스 언어를 선택하세요.",
|
|
6340
6358
|
languageLabel: "인터페이스 언어",
|
|
6359
|
+
emailNotifications: "이메일 알림",
|
|
6360
|
+
emailNotificationsDescription:
|
|
6361
|
+
"내가 시작한 생성이 완료되거나 실패하면 이메일을 받습니다.",
|
|
6341
6362
|
setupTitle: "Assets 설정",
|
|
6342
6363
|
setupDescription: "필수 항목 두 가지: 생성과 영구 저장소.",
|
|
6343
6364
|
setupReady: "준비됨",
|
|
@@ -6685,6 +6706,9 @@ export const messagesByLocale = {
|
|
|
6685
6706
|
languageDescription:
|
|
6686
6707
|
"Escolha o idioma da interface deste workspace de Assets.",
|
|
6687
6708
|
languageLabel: "Idioma da interface",
|
|
6709
|
+
emailNotifications: "Notificações por e-mail",
|
|
6710
|
+
emailNotificationsDescription:
|
|
6711
|
+
"Receba um e-mail quando uma geração que você iniciou terminar ou falhar.",
|
|
6688
6712
|
|
|
6689
6713
|
addBuilderGeminiOrOpenAI:
|
|
6690
6714
|
"Adicione Builder, Gemini ou OpenAI antes de gerar novos ativos.",
|
|
@@ -7130,6 +7154,9 @@ export const messagesByLocale = {
|
|
|
7130
7154
|
languageTitle: "भाषा",
|
|
7131
7155
|
languageDescription: "इस Assets workspace की इंटरफ़ेस भाषा चुनें।",
|
|
7132
7156
|
languageLabel: "इंटरफ़ेस भाषा",
|
|
7157
|
+
emailNotifications: "ईमेल सूचनाएँ",
|
|
7158
|
+
emailNotificationsDescription:
|
|
7159
|
+
"आपके द्वारा शुरू किया गया जनरेशन पूरा या विफल होने पर ईमेल पाएँ।",
|
|
7133
7160
|
setupTitle: "Assets सेटअप",
|
|
7134
7161
|
setupDescription: "दो जरूरी चीजें: generation और durable storage.",
|
|
7135
7162
|
setupReady: "तैयार",
|
|
@@ -7475,6 +7502,9 @@ export const messagesByLocale = {
|
|
|
7475
7502
|
languageTitle: "اللغة",
|
|
7476
7503
|
languageDescription: "اختر لغة الواجهة لمساحة عمل Assets هذه.",
|
|
7477
7504
|
languageLabel: "لغة الواجهة",
|
|
7505
|
+
emailNotifications: "إشعارات البريد الإلكتروني",
|
|
7506
|
+
emailNotificationsDescription:
|
|
7507
|
+
"احصل على بريد إلكتروني عند اكتمال عملية إنشاء بدأتها أو فشلها.",
|
|
7478
7508
|
|
|
7479
7509
|
addBuilderGeminiOrOpenAI:
|
|
7480
7510
|
"قم بإضافة Builder، أو Gemini، أو OpenAI قبل إنشاء أصول جديدة.",
|