@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentJobsTab.js","sourceRoot":"","sources":["../../../src/client/agent-page/AgentJobsTab.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Button } from \"@agent-native/toolkit/ui/button\";\nimport {\n IconBolt,\n IconCalendarEvent,\n IconClock,\n IconEye,\n IconLoader2,\n IconPlayerPause,\n IconPlayerPlay,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { useState } from \"react\";\n\nimport { AgentAskPopover } from \"../AgentAskPopover.js\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"../components/ui/dialog.js\";\nimport { useFormatters, useT } from \"../i18n.js\";\nimport { automationCreationContext } from \"../settings/AutomationsSection.js\";\nimport { AgentEmptyState } from \"./AgentEmptyState.js\";\nimport { AgentTabFrame } from \"./AgentTabFrame.js\";\nimport type { AgentPageTabProps } from \"./types.js\";\nimport {\n useAutomations,\n useManageAutomation,\n useManageRecurringJob,\n useRecurringJobs,\n type Automation,\n type RecurringJob,\n} from \"./use-jobs.js\";\n\ntype ListedAutomation =\n | {\n kind: \"recurring\";\n resource: RecurringJob;\n triggerType: \"schedule\";\n }\n | {\n kind: \"automation\";\n resource: Automation;\n triggerType: \"event\" | \"schedule\";\n };\n\nfunction listRecurringJobs(jobs: RecurringJob[]): ListedAutomation[] {\n return jobs.map((resource) => ({\n kind: \"recurring\",\n resource,\n triggerType: \"schedule\",\n }));\n}\n\nfunction listAutomations(automations: Automation[]): ListedAutomation[] {\n return automations.map((resource) => ({\n kind: \"automation\",\n resource,\n triggerType: resource.triggerType,\n }));\n}\n\nexport function organizationAutomationCreationContext(): string {\n return \"The user wants to create a new organization automation. Use manage-automations with action=define and scope=organization to create it. Ask clarifying questions if needed about whether it runs on a schedule or event, any conditions, and what actions to take.\";\n}\n\nexport function AgentJobsTab({ canManageOrg = false }: AgentPageTabProps) {\n const t = useT();\n const formatters = useFormatters();\n const personalJobsQuery = useRecurringJobs(\"user\");\n const personalAutomationsQuery = useAutomations(\"user\");\n const organizationJobsQuery = useRecurringJobs(\"org\");\n const organizationAutomationsQuery = useAutomations(\"org\");\n const personalJobsMutation = useManageRecurringJob(\"user\");\n const personalAutomationsMutation = useManageAutomation(\"user\");\n const organizationJobsMutation = useManageRecurringJob(\"org\");\n const organizationAutomationsMutation = useManageAutomation(\"org\");\n const [deleteTarget, setDeleteTarget] = useState<ListedAutomation | null>(\n null,\n );\n const [detailsTarget, setDetailsTarget] = useState<ListedAutomation | null>(\n null,\n );\n\n const formatDateTime = (value: string | null) => {\n if (!value || Number.isNaN(new Date(value).getTime())) return null;\n return formatters.formatDate(value, {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n };\n\n const personalEntries = [\n ...listRecurringJobs(personalJobsQuery.data ?? []),\n ...listAutomations(personalAutomationsQuery.data ?? []),\n ];\n const organizationEntries = [\n ...listRecurringJobs(organizationJobsQuery.data ?? []),\n ...listAutomations(organizationAutomationsQuery.data ?? []),\n ];\n const mutationPending =\n personalJobsMutation.isPending ||\n personalAutomationsMutation.isPending ||\n organizationJobsMutation.isPending ||\n organizationAutomationsMutation.isPending;\n\n const mutateEntry = (\n entry: ListedAutomation,\n operation: \"update\" | \"delete\",\n enabled?: boolean,\n onSuccess?: () => void,\n ) => {\n const input = {\n operation,\n name: entry.resource.name,\n scope: entry.resource.scope,\n ...(enabled === undefined ? {} : { enabled }),\n };\n const options = onSuccess ? { onSuccess } : undefined;\n\n if (entry.kind === \"automation\") {\n const mutation =\n entry.resource.scope === \"organization\"\n ? organizationAutomationsMutation\n : personalAutomationsMutation;\n mutation.mutate(input, options);\n } else if (entry.resource.scope === \"organization\") {\n organizationJobsMutation.mutate(input, options);\n } else {\n personalJobsMutation.mutate(input, options);\n }\n };\n\n const renderSection = ({\n title,\n description,\n entries,\n loading,\n errors,\n organization = false,\n }: {\n title: string;\n description: string;\n entries: ListedAutomation[];\n loading: boolean;\n errors: unknown[];\n organization?: boolean;\n }) => (\n <section className=\"space-y-4\">\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div className=\"min-w-0\">\n <h2 className=\"text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground/70\">\n {title}\n </h2>\n <p className=\"mt-2 max-w-2xl text-sm text-muted-foreground\">\n {description}\n </p>\n </div>\n {organization ? (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {!canManageOrg ? (\n <span className=\"text-xs text-muted-foreground\">\n {t(\"jobs.organizationMemberNote\", {\n defaultValue: \"You can manage automations you created.\",\n })}\n </span>\n ) : null}\n <AgentAskPopover\n context={organizationAutomationCreationContext()}\n prompt={t(\"jobs.organizationPrompt\", {\n defaultValue:\n \"Create a shared organization automation that does this: \",\n })}\n title={t(\"jobs.automationsCreateTitle\", {\n defaultValue: \"Create an automation\",\n })}\n label={t(\"jobs.newAutomation\", {\n defaultValue: \"New automation\",\n })}\n />\n </div>\n ) : null}\n </div>\n\n {errors.length > 0 ? (\n <p className=\"text-sm text-destructive\">\n {t(\"jobs.loadError\", {\n defaultValue: \"Could not load all automations.\",\n })}\n </p>\n ) : null}\n\n {loading && entries.length === 0 ? (\n <div\n className=\"flex items-center gap-2 text-sm text-muted-foreground\"\n aria-busy=\"true\"\n >\n <IconLoader2 className=\"size-4 animate-spin\" />\n {t(\"jobs.loading\", { defaultValue: \"Loading…\" })}\n </div>\n ) : entries.length === 0 && errors.length === 0 ? (\n <AgentEmptyState\n icon={IconCalendarEvent}\n title={\n organization\n ? t(\"jobs.organizationEmptyTitle\", {\n defaultValue: \"No organization automations yet\",\n })\n : t(\"jobs.automationsEmptyTitle\", {\n defaultValue: \"No automations yet\",\n })\n }\n description={\n organization\n ? t(\"jobs.organizationEmptyDescription\", {\n defaultValue:\n \"Describe a scheduled or event-triggered automation for this organization.\",\n })\n : t(\"jobs.automationsEmptyDescription\", {\n defaultValue: \"Describe what should happen and when.\",\n })\n }\n action={\n organization ? null : (\n <AgentAskPopover\n context={automationCreationContext()}\n prompt={t(\"jobs.automationPrompt\", {\n defaultValue: \"Create an automation that does this: \",\n })}\n title={t(\"jobs.automationsCreateTitle\", {\n defaultValue: \"Create an automation\",\n })}\n />\n )\n }\n />\n ) : (\n <div className=\"divide-y divide-border/60 border-y border-border/60\">\n {entries.map((entry) => {\n const resource = entry.resource;\n const lastRun = formatDateTime(resource.lastRun);\n const nextRun = formatDateTime(resource.nextRun);\n const triggerDescription =\n entry.kind === \"automation\" && entry.triggerType === \"event\"\n ? t(\"jobs.automationEventTrigger\", {\n defaultValue: \"On {{event}}\",\n event: entry.resource.event ?? \"event\",\n })\n : resource.scheduleDescription ||\n resource.schedule ||\n t(\"jobs.scheduledTrigger\", {\n defaultValue: \"Scheduled\",\n });\n const instructions =\n entry.kind === \"automation\"\n ? entry.resource.body\n : entry.resource.instructions;\n\n return (\n <article\n key={`${entry.kind}:${resource.id}`}\n className=\"py-4 first:pt-5 last:pb-5\"\n >\n <div className=\"flex items-start gap-3\">\n <div className=\"mt-0.5 text-muted-foreground\">\n {entry.triggerType === \"event\" ? (\n <IconBolt className=\"size-4\" />\n ) : (\n <IconClock className=\"size-4\" />\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h3 className=\"truncate text-sm font-medium\">\n {resource.name.replace(/-/g, \" \")}\n </h3>\n <span className=\"rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n {entry.triggerType === \"event\"\n ? t(\"jobs.eventTrigger\", {\n defaultValue: \"Event-triggered\",\n })\n : t(\"jobs.scheduledTrigger\", {\n defaultValue: \"Scheduled\",\n })}\n </span>\n <span\n className={\n resource.enabled\n ? \"rounded-full bg-emerald-500/15 px-2 py-0.5 text-[10px] font-medium text-emerald-600 dark:text-emerald-400\"\n : \"rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\"\n }\n >\n {resource.enabled\n ? t(\"jobs.enabled\", { defaultValue: \"Enabled\" })\n : t(\"jobs.paused\", { defaultValue: \"Paused\" })}\n </span>\n {resource.lastStatus ? (\n <span className=\"rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n {resource.lastStatus}\n </span>\n ) : null}\n </div>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {triggerDescription}\n </p>\n <p className=\"mt-1 line-clamp-2 text-xs text-muted-foreground/80\">\n {instructions}\n </p>\n {lastRun || nextRun ? (\n <div className=\"mt-2 flex flex-wrap gap-x-4 gap-y-1 text-[11px] text-muted-foreground\">\n {nextRun ? (\n <span>\n {t(\"jobs.nextRun\", { defaultValue: \"Next run\" })}:{\" \"}\n {nextRun}\n </span>\n ) : null}\n {lastRun ? (\n <span>\n {t(\"jobs.lastRun\", { defaultValue: \"Last run\" })}:{\" \"}\n {lastRun}\n </span>\n ) : null}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"cursor-pointer px-2 text-xs\"\n onClick={() => setDetailsTarget(entry)}\n >\n <IconEye className=\"size-3.5\" />\n {t(\"jobs.details\", { defaultValue: \"Details\" })}\n </Button>\n {resource.canUpdate ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"cursor-pointer px-2 text-xs\"\n disabled={mutationPending}\n onClick={() =>\n mutateEntry(entry, \"update\", !resource.enabled)\n }\n >\n {resource.enabled ? (\n <IconPlayerPause className=\"size-3.5\" />\n ) : (\n <IconPlayerPlay className=\"size-3.5\" />\n )}\n {resource.enabled\n ? t(\"jobs.pause\", { defaultValue: \"Pause\" })\n : t(\"jobs.resume\", { defaultValue: \"Resume\" })}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8 cursor-pointer text-muted-foreground hover:text-destructive\"\n aria-label={t(\"jobs.delete\", {\n defaultValue: \"Delete\",\n })}\n onClick={() => setDeleteTarget(entry)}\n >\n <IconTrash className=\"size-3.5\" />\n </Button>\n </>\n ) : null}\n </div>\n </div>\n </article>\n );\n })}\n </div>\n )}\n </section>\n );\n\n const mutationError =\n personalJobsMutation.error ||\n personalAutomationsMutation.error ||\n organizationJobsMutation.error ||\n organizationAutomationsMutation.error;\n\n return (\n <AgentTabFrame\n title={t(\"jobs.pageTitle\", { defaultValue: \"Automations\" })}\n description={t(\"jobs.pageDescription\", {\n defaultValue:\n \"Manage agent tasks that run on a schedule or in response to events.\",\n })}\n actions={\n <AgentAskPopover\n context={automationCreationContext()}\n prompt={t(\"jobs.automationPrompt\", {\n defaultValue: \"Create an automation that does this: \",\n })}\n title={t(\"jobs.automationsCreateTitle\", {\n defaultValue: \"Create an automation\",\n })}\n label={t(\"jobs.newAutomation\", {\n defaultValue: \"New automation\",\n })}\n />\n }\n >\n <div className=\"space-y-7\">\n {renderSection({\n title: t(\"jobs.personal\", { defaultValue: \"Personal\" }),\n description: t(\"jobs.personalDescription\", {\n defaultValue:\n \"Scheduled and event-triggered automations that run for you.\",\n }),\n entries: personalEntries,\n loading:\n personalJobsQuery.isLoading || personalAutomationsQuery.isLoading,\n errors: [\n personalJobsQuery.error,\n personalAutomationsQuery.error,\n ].filter(Boolean),\n })}\n <div className=\"border-t border-border/70 pt-6\">\n {renderSection({\n title: t(\"jobs.organization\", { defaultValue: \"Organization\" }),\n description: t(\"jobs.organizationDescription\", {\n defaultValue:\n \"Scheduled and event-triggered automations shared with this organization.\",\n }),\n entries: organizationEntries,\n loading:\n organizationJobsQuery.isLoading ||\n organizationAutomationsQuery.isLoading,\n errors: [\n organizationJobsQuery.error,\n organizationAutomationsQuery.error,\n ].filter(Boolean),\n organization: true,\n })}\n </div>\n {mutationError ? (\n <p className=\"text-sm text-destructive\">\n {mutationError.message ||\n t(\"jobs.updateError\", {\n defaultValue: \"Could not update automation.\",\n })}\n </p>\n ) : null}\n </div>\n\n <Dialog\n open={deleteTarget !== null}\n onOpenChange={(open) => {\n if (!open && !mutationPending) setDeleteTarget(null);\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {t(\"jobs.deleteAutomationTitle\", {\n defaultValue: \"Delete automation?\",\n })}\n </DialogTitle>\n <DialogDescription>\n {t(\"jobs.deleteAutomationDescription\", {\n defaultValue:\n \"This permanently removes the automation and cannot be undone.\",\n })}\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"cursor-pointer\"\n disabled={mutationPending}\n onClick={() => setDeleteTarget(null)}\n >\n {t(\"jobs.cancel\", { defaultValue: \"Cancel\" })}\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n className=\"cursor-pointer\"\n disabled={mutationPending}\n onClick={() => {\n if (!deleteTarget) return;\n mutateEntry(deleteTarget, \"delete\", undefined, () =>\n setDeleteTarget(null),\n );\n }}\n >\n {mutationPending ? (\n <IconLoader2 className=\"size-4 animate-spin\" />\n ) : null}\n {t(\"jobs.delete\", { defaultValue: \"Delete\" })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n <Dialog\n open={detailsTarget !== null}\n onOpenChange={(open) => {\n if (!open) setDetailsTarget(null);\n }}\n >\n <DialogContent className=\"max-w-2xl\">\n <DialogHeader>\n <DialogTitle>\n {detailsTarget?.resource.name.replace(/-/g, \" \") ??\n t(\"jobs.automationDetails\", {\n defaultValue: \"Automation details\",\n })}\n </DialogTitle>\n <DialogDescription>\n {detailsTarget\n ? detailsTarget.triggerType === \"event\"\n ? t(\"jobs.automationEventDetails\", {\n defaultValue: \"Runs when {{event}}.\",\n event:\n detailsTarget.kind === \"automation\"\n ? (detailsTarget.resource.event ?? \"an event fires\")\n : \"an event fires\",\n })\n : detailsTarget.resource.scheduleDescription ||\n detailsTarget.resource.schedule ||\n t(\"jobs.scheduledTrigger\", {\n defaultValue: \"Scheduled\",\n })\n : null}\n </DialogDescription>\n </DialogHeader>\n {detailsTarget ? (\n <div className=\"space-y-3\">\n {detailsTarget.kind === \"automation\" &&\n detailsTarget.resource.condition ? (\n <div>\n <p className=\"text-xs font-medium text-foreground\">\n {t(\"jobs.condition\", { defaultValue: \"Condition\" })}\n </p>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {detailsTarget.resource.condition}\n </p>\n </div>\n ) : null}\n <div>\n <p className=\"text-xs font-medium text-foreground\">\n {t(\"jobs.instructions\", { defaultValue: \"Instructions\" })}\n </p>\n <p className=\"mt-1 whitespace-pre-wrap text-sm text-muted-foreground\">\n {detailsTarget.kind === \"automation\"\n ? detailsTarget.resource.body\n : detailsTarget.resource.instructions}\n </p>\n </div>\n {(detailsTarget.resource.mcpTools ?? []).length > 0 ? (\n <div>\n <p className=\"text-xs font-medium text-foreground\">\n {t(\"jobs.mcpTools\", {\n defaultValue: \"Connected MCP tools\",\n })}\n </p>\n <div className=\"mt-1 flex flex-wrap gap-1.5\">\n {(detailsTarget.resource.mcpTools ?? []).map((toolName) => (\n <code\n key={toolName}\n className=\"rounded bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n {toolName}\n </code>\n ))}\n </div>\n </div>\n ) : null}\n </div>\n ) : null}\n </DialogContent>\n </Dialog>\n </AgentTabFrame>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AgentJobsTab.js","sourceRoot":"","sources":["../../../src/client/agent-page/AgentJobsTab.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Button } from \"@agent-native/toolkit/ui/button\";\nimport {\n IconBolt,\n IconCalendarEvent,\n IconClock,\n IconAlertTriangle,\n IconEye,\n IconLoader2,\n IconPencil,\n IconPlayerPause,\n IconPlayerPlay,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { useState } from \"react\";\n\nimport { AgentAskPopover } from \"../AgentAskPopover.js\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"../components/ui/dialog.js\";\nimport { useFormatters, useT } from \"../i18n.js\";\nimport { automationCreationContext } from \"../settings/AutomationsSection.js\";\nimport { AgentEmptyState } from \"./AgentEmptyState.js\";\nimport { AgentTabFrame } from \"./AgentTabFrame.js\";\nimport {\n AutomationDetailsDialog,\n type AutomationDetailsField,\n} from \"./AutomationDetailsDialog.js\";\nimport { AutomationScheduleDialog } from \"./AutomationScheduleDialog.js\";\nimport type { AgentPageTabProps } from \"./types.js\";\nimport {\n useAutomations,\n useManageAutomation,\n useManageRecurringJob,\n useRecurringJobs,\n type Automation,\n type RecurringJob,\n} from \"./use-jobs.js\";\n\ntype ListedAutomation =\n | {\n kind: \"recurring\";\n resource: RecurringJob;\n triggerType: \"schedule\";\n }\n | {\n kind: \"automation\";\n resource: Automation;\n triggerType: \"event\" | \"schedule\";\n };\n\nfunction listRecurringJobs(jobs: RecurringJob[]): ListedAutomation[] {\n return jobs.map((resource) => ({\n kind: \"recurring\",\n resource,\n triggerType: \"schedule\",\n }));\n}\n\nfunction listAutomations(automations: Automation[]): ListedAutomation[] {\n return automations.map((resource) => ({\n kind: \"automation\",\n resource,\n triggerType: resource.triggerType,\n }));\n}\n\ntype Translate = ReturnType<typeof useT>;\n\nfunction describeTrigger(entry: ListedAutomation, t: Translate): string {\n if (entry.kind === \"automation\" && entry.triggerType === \"event\") {\n return t(\"jobs.automationEventDetails\", {\n defaultValue: \"Runs when {{event}}.\",\n event: entry.resource.event ?? \"an event fires\",\n });\n }\n return (\n entry.resource.scheduleDescription ||\n entry.resource.schedule ||\n t(\"jobs.scheduledTrigger\", { defaultValue: \"Scheduled\" })\n );\n}\n\nfunction detailsFields(\n entry: ListedAutomation,\n t: Translate,\n formatDateTime: (value: string | null) => string | null,\n): AutomationDetailsField[] {\n const resource = entry.resource;\n const unset = t(\"jobs.notSet\", { defaultValue: \"—\" });\n const fields: AutomationDetailsField[] = [\n {\n label: t(\"jobs.status\", { defaultValue: \"Status\" }),\n value: resource.enabled\n ? t(\"jobs.enabled\", { defaultValue: \"Enabled\" })\n : t(\"jobs.paused\", { defaultValue: \"Paused\" }),\n },\n {\n label: t(\"jobs.trigger\", { defaultValue: \"Trigger\" }),\n value:\n entry.triggerType === \"event\"\n ? t(\"jobs.eventTrigger\", { defaultValue: \"Event-triggered\" })\n : t(\"jobs.scheduledTrigger\", { defaultValue: \"Scheduled\" }),\n },\n ];\n\n if (entry.triggerType === \"schedule\") {\n fields.push(\n {\n label: t(\"jobs.cronExpression\", { defaultValue: \"Cron expression\" }),\n value: resource.schedule || unset,\n mono: true,\n },\n {\n label: t(\"jobs.timezone\", { defaultValue: \"Timezone\" }),\n value: resource.timezone || unset,\n },\n );\n }\n\n fields.push(\n {\n label: t(\"jobs.nextRun\", { defaultValue: \"Next run\" }),\n value: formatDateTime(resource.nextRun) ?? unset,\n },\n {\n label: t(\"jobs.lastRun\", { defaultValue: \"Last run\" }),\n value:\n formatDateTime(resource.lastRun) ??\n t(\"jobs.neverRan\", { defaultValue: \"Never\" }),\n },\n {\n label: t(\"jobs.lastChecked\", { defaultValue: \"Last checked\" }),\n value: formatDateTime(resource.lastCheck) ?? unset,\n },\n {\n label: t(\"jobs.lastStatus\", { defaultValue: \"Last status\" }),\n value: resource.lastStatus || unset,\n },\n {\n label: t(\"jobs.scope\", { defaultValue: \"Scope\" }),\n value:\n resource.scope === \"organization\"\n ? t(\"jobs.organization\", { defaultValue: \"Organization\" })\n : t(\"jobs.personal\", { defaultValue: \"Personal\" }),\n },\n {\n label: t(\"jobs.createdBy\", { defaultValue: \"Created by\" }),\n value: resource.createdBy || unset,\n },\n );\n\n if (entry.kind === \"automation\") {\n fields.push({\n label: t(\"jobs.model\", { defaultValue: \"Model\" }),\n value: entry.resource.model || unset,\n });\n }\n\n return fields;\n}\n\nexport function organizationAutomationCreationContext(): string {\n return \"The user wants to create a new organization automation. Use manage-automations with action=define and scope=organization to create it. Ask clarifying questions if needed about whether it runs on a schedule or event, any conditions, and what actions to take.\";\n}\n\nexport function AgentJobsTab({ canManageOrg = false }: AgentPageTabProps) {\n const t = useT();\n const formatters = useFormatters();\n const personalJobsQuery = useRecurringJobs(\"user\");\n const personalAutomationsQuery = useAutomations(\"user\");\n const organizationJobsQuery = useRecurringJobs(\"org\");\n const organizationAutomationsQuery = useAutomations(\"org\");\n const personalJobsMutation = useManageRecurringJob(\"user\");\n const personalAutomationsMutation = useManageAutomation(\"user\");\n const organizationJobsMutation = useManageRecurringJob(\"org\");\n const organizationAutomationsMutation = useManageAutomation(\"org\");\n const [deleteTarget, setDeleteTarget] = useState<ListedAutomation | null>(\n null,\n );\n const [detailsTarget, setDetailsTarget] = useState<ListedAutomation | null>(\n null,\n );\n const [scheduleTarget, setScheduleTarget] = useState<ListedAutomation | null>(\n null,\n );\n\n const formatDateTime = (value: string | null) => {\n if (!value || Number.isNaN(new Date(value).getTime())) return null;\n return formatters.formatDate(value, {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n };\n\n const personalEntries = [\n ...listRecurringJobs(personalJobsQuery.data ?? []),\n ...listAutomations(personalAutomationsQuery.data ?? []),\n ];\n const organizationEntries = [\n ...listRecurringJobs(organizationJobsQuery.data ?? []),\n ...listAutomations(organizationAutomationsQuery.data ?? []),\n ];\n const mutationPending =\n personalJobsMutation.isPending ||\n personalAutomationsMutation.isPending ||\n organizationJobsMutation.isPending ||\n organizationAutomationsMutation.isPending;\n\n const mutateEntry = (\n entry: ListedAutomation,\n operation: \"update\" | \"delete\",\n patch?: { enabled?: boolean; schedule?: string },\n onSuccess?: () => void,\n ) => {\n const input = {\n operation,\n name: entry.resource.name,\n scope: entry.resource.scope,\n ...patch,\n };\n const options = onSuccess ? { onSuccess } : undefined;\n\n if (entry.kind === \"automation\") {\n const mutation =\n entry.resource.scope === \"organization\"\n ? organizationAutomationsMutation\n : personalAutomationsMutation;\n mutation.mutate(input, options);\n } else if (entry.resource.scope === \"organization\") {\n organizationJobsMutation.mutate(input, options);\n } else {\n personalJobsMutation.mutate(input, options);\n }\n };\n\n const renderSection = ({\n title,\n description,\n entries,\n loading,\n errors,\n organization = false,\n }: {\n title: string;\n description: string;\n entries: ListedAutomation[];\n loading: boolean;\n errors: unknown[];\n organization?: boolean;\n }) => (\n <section className=\"space-y-4\">\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div className=\"min-w-0\">\n <h2 className=\"text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground/70\">\n {title}\n </h2>\n <p className=\"mt-2 max-w-2xl text-sm text-muted-foreground\">\n {description}\n </p>\n </div>\n {organization ? (\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {!canManageOrg ? (\n <span className=\"text-xs text-muted-foreground\">\n {t(\"jobs.organizationMemberNote\", {\n defaultValue: \"You can manage automations you created.\",\n })}\n </span>\n ) : null}\n <AgentAskPopover\n context={organizationAutomationCreationContext()}\n prompt={t(\"jobs.organizationPrompt\", {\n defaultValue:\n \"Create a shared organization automation that does this: \",\n })}\n title={t(\"jobs.automationsCreateTitle\", {\n defaultValue: \"Create an automation\",\n })}\n label={t(\"jobs.newAutomation\", {\n defaultValue: \"New automation\",\n })}\n />\n </div>\n ) : null}\n </div>\n\n {errors.length > 0 ? (\n <p className=\"text-sm text-destructive\">\n {t(\"jobs.loadError\", {\n defaultValue: \"Could not load all automations.\",\n })}\n </p>\n ) : null}\n\n {loading && entries.length === 0 ? (\n <div\n className=\"flex items-center gap-2 text-sm text-muted-foreground\"\n aria-busy=\"true\"\n >\n <IconLoader2 className=\"size-4 animate-spin\" />\n {t(\"jobs.loading\", { defaultValue: \"Loading…\" })}\n </div>\n ) : entries.length === 0 && errors.length === 0 ? (\n <AgentEmptyState\n icon={IconCalendarEvent}\n title={\n organization\n ? t(\"jobs.organizationEmptyTitle\", {\n defaultValue: \"No organization automations yet\",\n })\n : t(\"jobs.automationsEmptyTitle\", {\n defaultValue: \"No automations yet\",\n })\n }\n description={\n organization\n ? t(\"jobs.organizationEmptyDescription\", {\n defaultValue:\n \"Describe a scheduled or event-triggered automation for this organization.\",\n })\n : t(\"jobs.automationsEmptyDescription\", {\n defaultValue: \"Describe what should happen and when.\",\n })\n }\n action={\n organization ? null : (\n <AgentAskPopover\n context={automationCreationContext()}\n prompt={t(\"jobs.automationPrompt\", {\n defaultValue: \"Create an automation that does this: \",\n })}\n title={t(\"jobs.automationsCreateTitle\", {\n defaultValue: \"Create an automation\",\n })}\n />\n )\n }\n />\n ) : (\n <div className=\"divide-y divide-border/60 border-y border-border/60\">\n {entries.map((entry) => {\n const resource = entry.resource;\n const lastRun = formatDateTime(resource.lastRun);\n const lastCheck = formatDateTime(resource.lastCheck);\n const nextRun = formatDateTime(resource.nextRun);\n const triggerDescription =\n entry.kind === \"automation\" && entry.triggerType === \"event\"\n ? t(\"jobs.automationEventTrigger\", {\n defaultValue: \"On {{event}}\",\n event: entry.resource.event ?? \"event\",\n })\n : resource.scheduleDescription ||\n resource.schedule ||\n t(\"jobs.scheduledTrigger\", {\n defaultValue: \"Scheduled\",\n });\n const instructions =\n entry.kind === \"automation\"\n ? entry.resource.body\n : entry.resource.instructions;\n\n return (\n <article\n key={`${entry.kind}:${resource.id}`}\n className=\"py-4 first:pt-5 last:pb-5\"\n >\n <div className=\"flex items-start gap-3\">\n <div className=\"mt-0.5 text-muted-foreground\">\n {entry.triggerType === \"event\" ? (\n <IconBolt className=\"size-4\" />\n ) : (\n <IconClock className=\"size-4\" />\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h3 className=\"truncate text-sm font-medium\">\n {resource.name.replace(/-/g, \" \")}\n </h3>\n <span className=\"rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n {entry.triggerType === \"event\"\n ? t(\"jobs.eventTrigger\", {\n defaultValue: \"Event-triggered\",\n })\n : t(\"jobs.scheduledTrigger\", {\n defaultValue: \"Scheduled\",\n })}\n </span>\n <span\n className={\n resource.enabled\n ? \"rounded-full bg-emerald-500/15 px-2 py-0.5 text-[10px] font-medium text-emerald-600 dark:text-emerald-400\"\n : \"rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\"\n }\n >\n {resource.enabled\n ? t(\"jobs.enabled\", { defaultValue: \"Enabled\" })\n : t(\"jobs.paused\", { defaultValue: \"Paused\" })}\n </span>\n {resource.lastStatus ? (\n <span className=\"rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground\">\n {resource.lastStatus}\n </span>\n ) : null}\n </div>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {triggerDescription}\n </p>\n <p className=\"mt-1 line-clamp-2 text-xs text-muted-foreground/80\">\n {instructions}\n </p>\n {lastRun || nextRun || lastCheck ? (\n <div className=\"mt-2 flex flex-wrap gap-x-4 gap-y-1 text-[11px] text-muted-foreground\">\n {nextRun ? (\n <span>\n {t(\"jobs.nextRun\", { defaultValue: \"Next run\" })}:{\" \"}\n {nextRun}\n </span>\n ) : null}\n <span>\n {t(\"jobs.lastRun\", { defaultValue: \"Last run\" })}:{\" \"}\n {lastRun ??\n t(\"jobs.neverRan\", { defaultValue: \"Never\" })}\n </span>\n {!lastRun && lastCheck ? (\n <span>\n {t(\"jobs.lastChecked\", {\n defaultValue: \"Last checked\",\n })}\n : {lastCheck}\n </span>\n ) : null}\n </div>\n ) : null}\n {resource.lastError ? (\n <p className=\"mt-2 flex items-start gap-1.5 text-[11px] text-destructive\">\n <IconAlertTriangle className=\"mt-px size-3 shrink-0\" />\n <span className=\"min-w-0 break-words\">\n {resource.lastError}\n </span>\n </p>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"cursor-pointer px-2 text-xs\"\n onClick={() => setDetailsTarget(entry)}\n >\n <IconEye className=\"size-3.5\" />\n {t(\"jobs.details\", { defaultValue: \"Details\" })}\n </Button>\n {resource.canUpdate ? (\n <>\n {entry.triggerType === \"schedule\" ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"cursor-pointer px-2 text-xs\"\n disabled={mutationPending}\n onClick={() => setScheduleTarget(entry)}\n >\n <IconPencil className=\"size-3.5\" />\n {t(\"jobs.edit\", { defaultValue: \"Edit\" })}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"cursor-pointer px-2 text-xs\"\n disabled={mutationPending}\n onClick={() =>\n mutateEntry(entry, \"update\", {\n enabled: !resource.enabled,\n })\n }\n >\n {resource.enabled ? (\n <IconPlayerPause className=\"size-3.5\" />\n ) : (\n <IconPlayerPlay className=\"size-3.5\" />\n )}\n {resource.enabled\n ? t(\"jobs.pause\", { defaultValue: \"Pause\" })\n : t(\"jobs.resume\", { defaultValue: \"Resume\" })}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8 cursor-pointer text-muted-foreground hover:text-destructive\"\n aria-label={t(\"jobs.delete\", {\n defaultValue: \"Delete\",\n })}\n onClick={() => setDeleteTarget(entry)}\n >\n <IconTrash className=\"size-3.5\" />\n </Button>\n </>\n ) : null}\n </div>\n </div>\n </article>\n );\n })}\n </div>\n )}\n </section>\n );\n\n const mutationError =\n personalJobsMutation.error ||\n personalAutomationsMutation.error ||\n organizationJobsMutation.error ||\n organizationAutomationsMutation.error;\n\n return (\n <AgentTabFrame\n title={t(\"jobs.pageTitle\", { defaultValue: \"Automations\" })}\n description={t(\"jobs.pageDescription\", {\n defaultValue:\n \"Manage agent tasks that run on a schedule or in response to events.\",\n })}\n actions={\n <AgentAskPopover\n context={automationCreationContext()}\n prompt={t(\"jobs.automationPrompt\", {\n defaultValue: \"Create an automation that does this: \",\n })}\n title={t(\"jobs.automationsCreateTitle\", {\n defaultValue: \"Create an automation\",\n })}\n label={t(\"jobs.newAutomation\", {\n defaultValue: \"New automation\",\n })}\n />\n }\n >\n <div className=\"space-y-7\">\n {renderSection({\n title: t(\"jobs.personal\", { defaultValue: \"Personal\" }),\n description: t(\"jobs.personalDescription\", {\n defaultValue:\n \"Scheduled and event-triggered automations that run for you.\",\n }),\n entries: personalEntries,\n loading:\n personalJobsQuery.isLoading || personalAutomationsQuery.isLoading,\n errors: [\n personalJobsQuery.error,\n personalAutomationsQuery.error,\n ].filter(Boolean),\n })}\n <div className=\"border-t border-border/70 pt-6\">\n {renderSection({\n title: t(\"jobs.organization\", { defaultValue: \"Organization\" }),\n description: t(\"jobs.organizationDescription\", {\n defaultValue:\n \"Scheduled and event-triggered automations shared with this organization.\",\n }),\n entries: organizationEntries,\n loading:\n organizationJobsQuery.isLoading ||\n organizationAutomationsQuery.isLoading,\n errors: [\n organizationJobsQuery.error,\n organizationAutomationsQuery.error,\n ].filter(Boolean),\n organization: true,\n })}\n </div>\n {mutationError ? (\n <p className=\"text-sm text-destructive\">\n {mutationError.message ||\n t(\"jobs.updateError\", {\n defaultValue: \"Could not update automation.\",\n })}\n </p>\n ) : null}\n </div>\n\n <Dialog\n open={deleteTarget !== null}\n onOpenChange={(open) => {\n if (!open && !mutationPending) setDeleteTarget(null);\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {t(\"jobs.deleteAutomationTitle\", {\n defaultValue: \"Delete automation?\",\n })}\n </DialogTitle>\n <DialogDescription>\n {t(\"jobs.deleteAutomationDescription\", {\n defaultValue:\n \"This permanently removes the automation and cannot be undone.\",\n })}\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"cursor-pointer\"\n disabled={mutationPending}\n onClick={() => setDeleteTarget(null)}\n >\n {t(\"jobs.cancel\", { defaultValue: \"Cancel\" })}\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n className=\"cursor-pointer\"\n disabled={mutationPending}\n onClick={() => {\n if (!deleteTarget) return;\n mutateEntry(deleteTarget, \"delete\", undefined, () =>\n setDeleteTarget(null),\n );\n }}\n >\n {mutationPending ? (\n <IconLoader2 className=\"size-4 animate-spin\" />\n ) : null}\n {t(\"jobs.delete\", { defaultValue: \"Delete\" })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n {detailsTarget ? (\n <AutomationDetailsDialog\n open\n name={detailsTarget.resource.name}\n scope={\n detailsTarget.resource.scope === \"organization\" ? \"org\" : \"user\"\n }\n triggerSummary={describeTrigger(detailsTarget, t)}\n fields={detailsFields(detailsTarget, t, formatDateTime)}\n condition={\n detailsTarget.kind === \"automation\"\n ? detailsTarget.resource.condition\n : null\n }\n instructions={\n detailsTarget.kind === \"automation\"\n ? detailsTarget.resource.body\n : detailsTarget.resource.instructions\n }\n mcpTools={detailsTarget.resource.mcpTools ?? []}\n lastError={detailsTarget.resource.lastError}\n formatTimestamp={(value) =>\n formatDateTime(new Date(value).toISOString()) ?? String(value)\n }\n onClose={() => setDetailsTarget(null)}\n />\n ) : null}\n\n {scheduleTarget ? (\n <AutomationScheduleDialog\n open\n name={scheduleTarget.resource.name}\n schedule={scheduleTarget.resource.schedule ?? \"\"}\n timezone={scheduleTarget.resource.timezone ?? null}\n saving={mutationPending}\n error={mutationError ? mutationError.message : null}\n onCancel={() => setScheduleTarget(null)}\n onSave={(next) =>\n mutateEntry(scheduleTarget, \"update\", next, () =>\n setScheduleTarget(null),\n )\n }\n />\n ) : null}\n </AgentTabFrame>\n );\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type JobsScope } from "./use-jobs.js";
|
|
2
|
+
export interface AutomationDetailsField {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
mono?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface AutomationDetailsDialogProps {
|
|
8
|
+
open: boolean;
|
|
9
|
+
name: string;
|
|
10
|
+
triggerSummary: string;
|
|
11
|
+
fields: AutomationDetailsField[];
|
|
12
|
+
condition: string | null;
|
|
13
|
+
instructions: string;
|
|
14
|
+
mcpTools: string[];
|
|
15
|
+
lastError: string | null;
|
|
16
|
+
scope: JobsScope;
|
|
17
|
+
formatTimestamp: (value: number) => string;
|
|
18
|
+
onClose: () => void;
|
|
19
|
+
}
|
|
20
|
+
export declare function AutomationDetailsDialog({ open, name, triggerSummary, fields, condition, instructions, mcpTools, lastError, scope, formatTimestamp, onClose, }: AutomationDetailsDialogProps): import("react").JSX.Element;
|
|
21
|
+
//# sourceMappingURL=AutomationDetailsDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationDetailsDialog.d.ts","sourceRoot":"","sources":["../../../src/client/agent-page/AutomationDetailsDialog.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAElE,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,sBAAsB,EAAE,CAAC;IACjC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,SAAS,CAAC;IACjB,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAgBD,wBAAgB,uBAAuB,CAAC,EACtC,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,MAAM,EACN,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,KAAK,EACL,eAAe,EACf,OAAO,GACR,EAAE,4BAA4B,+BAqJ9B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { IconAlertTriangle, IconLoader2 } from "@tabler/icons-react";
|
|
3
|
+
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "../components/ui/dialog.js";
|
|
4
|
+
import { useT } from "../i18n.js";
|
|
5
|
+
import { useAutomationRuns } from "./use-jobs.js";
|
|
6
|
+
function RunStatusDot({ status }) {
|
|
7
|
+
const tone = status === "success"
|
|
8
|
+
? "bg-emerald-500"
|
|
9
|
+
: status === "error"
|
|
10
|
+
? "bg-destructive"
|
|
11
|
+
: // An interrupted run never reported an outcome, so it reads as
|
|
12
|
+
// unknown rather than as still making progress.
|
|
13
|
+
status === "interrupted"
|
|
14
|
+
? "bg-muted-foreground"
|
|
15
|
+
: "bg-amber-500";
|
|
16
|
+
return _jsx("span", { className: `size-1.5 shrink-0 rounded-full ${tone}` });
|
|
17
|
+
}
|
|
18
|
+
export function AutomationDetailsDialog({ open, name, triggerSummary, fields, condition, instructions, mcpTools, lastError, scope, formatTimestamp, onClose, }) {
|
|
19
|
+
const t = useT();
|
|
20
|
+
const runsQuery = useAutomationRuns(scope, open ? name : null, open);
|
|
21
|
+
const runs = runsQuery.data ?? [];
|
|
22
|
+
return (_jsx(Dialog, { open: open, onOpenChange: (next) => {
|
|
23
|
+
if (!next)
|
|
24
|
+
onClose();
|
|
25
|
+
}, children: _jsxs(DialogContent, { className: "max-h-[85vh] max-w-2xl overflow-y-auto", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: name.replace(/-/g, " ") }), _jsx(DialogDescription, { children: triggerSummary })] }), _jsxs("div", { className: "space-y-4", children: [lastError ? (_jsxs("div", { className: "flex items-start gap-2 rounded-md border border-destructive/30 bg-destructive/5 p-2.5", children: [_jsx(IconAlertTriangle, { className: "mt-0.5 size-4 shrink-0 text-destructive" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-xs font-medium text-destructive", children: t("jobs.blockedTitle", {
|
|
26
|
+
defaultValue: "This automation is not running",
|
|
27
|
+
}) }), _jsx("p", { className: "mt-0.5 break-words text-xs text-muted-foreground", children: lastError })] })] })) : null, _jsx("dl", { className: "grid grid-cols-2 gap-x-4 gap-y-2", children: fields.map((field) => (_jsxs("div", { className: "min-w-0", children: [_jsx("dt", { className: "text-[11px] uppercase tracking-wide text-muted-foreground/70", children: field.label }), _jsx("dd", { className: `mt-0.5 break-words text-sm ${field.mono ? "font-mono text-xs" : ""}`, children: field.value })] }, field.label))) }), condition ? (_jsxs("div", { children: [_jsx("p", { className: "text-xs font-medium text-foreground", children: t("jobs.condition", { defaultValue: "Condition" }) }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: condition })] })) : null, _jsxs("div", { children: [_jsx("p", { className: "text-xs font-medium text-foreground", children: t("jobs.instructions", { defaultValue: "Instructions" }) }), _jsx("p", { className: "mt-1 max-h-56 overflow-y-auto whitespace-pre-wrap rounded-md bg-muted/50 p-2.5 text-sm text-muted-foreground", children: instructions })] }), mcpTools.length > 0 ? (_jsxs("div", { children: [_jsx("p", { className: "text-xs font-medium text-foreground", children: t("jobs.mcpTools", { defaultValue: "Connected MCP tools" }) }), _jsx("div", { className: "mt-1 flex flex-wrap gap-1.5", children: mcpTools.map((toolName) => (_jsx("code", { className: "rounded bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground", children: toolName }, toolName))) })] })) : null, _jsxs("div", { children: [_jsx("p", { className: "text-xs font-medium text-foreground", children: t("jobs.pastRuns", { defaultValue: "Past runs" }) }), runsQuery.isLoading ? (_jsxs("div", { className: "mt-2 flex items-center gap-2 text-xs text-muted-foreground", "aria-busy": "true", children: [_jsx(IconLoader2, { className: "size-3.5 animate-spin" }), t("jobs.loading", { defaultValue: "Loading…" })] })) : runsQuery.error ? (_jsx("p", { className: "mt-1 text-xs text-destructive", children: t("jobs.runsLoadError", {
|
|
28
|
+
defaultValue: "Could not load run history.",
|
|
29
|
+
}) })) : runs.length === 0 ? (_jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: t("jobs.noRuns", {
|
|
30
|
+
defaultValue: "This automation has not executed yet. Only real executions are recorded here.",
|
|
31
|
+
}) })) : (_jsx("ul", { className: "mt-2 divide-y divide-border/60 border-y border-border/60", children: runs.map((run) => (_jsxs("li", { className: "flex items-center gap-2 py-1.5 text-xs", children: [_jsx(RunStatusDot, { status: run.status }), _jsx("span", { className: "shrink-0 text-muted-foreground", children: formatTimestamp(run.startedAt) }), _jsx("span", { className: "shrink-0 font-medium", children: run.status }), run.error ? (_jsx("span", { className: "min-w-0 flex-1 truncate text-muted-foreground", title: run.error, children: run.error })) : (_jsx("span", { className: "min-w-0 flex-1" })), run.finishedAt ? (_jsxs("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: [Math.round((run.finishedAt - run.startedAt) / 1000), "s"] })) : null] }, run.id))) }))] })] })] }) }));
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=AutomationDetailsDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationDetailsDialog.js","sourceRoot":"","sources":["../../../src/client/agent-page/AutomationDetailsDialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAkB,MAAM,eAAe,CAAC;AAsBlE,SAAS,YAAY,CAAC,EAAE,MAAM,EAAsB;IAClD,MAAM,IAAI,GACR,MAAM,KAAK,SAAS;QAClB,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,MAAM,KAAK,OAAO;YAClB,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,+DAA+D;gBAC/D,gDAAgD;gBAChD,MAAM,KAAK,aAAa;oBACxB,CAAC,CAAC,qBAAqB;oBACvB,CAAC,CAAC,cAAc,CAAC;IACzB,OAAO,eAAM,SAAS,EAAE,kCAAkC,IAAI,EAAE,GAAI,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,EACtC,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,MAAM,EACN,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,KAAK,EACL,eAAe,EACf,OAAO,GACsB;IAC7B,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC;IAElC,OAAO,CACL,KAAC,MAAM,IACL,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE;YACrB,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,CAAC;QACvB,CAAC,YAED,MAAC,aAAa,IAAC,SAAS,EAAC,wCAAwC,aAC/D,MAAC,YAAY,eACX,KAAC,WAAW,cAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,GAAe,EACpD,KAAC,iBAAiB,cAAE,cAAc,GAAqB,IAC1C,EAEf,eAAK,SAAS,EAAC,WAAW,aACvB,SAAS,CAAC,CAAC,CAAC,CACX,eAAK,SAAS,EAAC,uFAAuF,aACpG,KAAC,iBAAiB,IAAC,SAAS,EAAC,yCAAyC,GAAG,EACzE,eAAK,SAAS,EAAC,SAAS,aACtB,YAAG,SAAS,EAAC,sCAAsC,YAChD,CAAC,CAAC,mBAAmB,EAAE;gDACtB,YAAY,EAAE,gCAAgC;6CAC/C,CAAC,GACA,EACJ,YAAG,SAAS,EAAC,kDAAkD,YAC5D,SAAS,GACR,IACA,IACF,CACP,CAAC,CAAC,CAAC,IAAI,EAER,aAAI,SAAS,EAAC,kCAAkC,YAC7C,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACrB,eAAuB,SAAS,EAAC,SAAS,aACxC,aAAI,SAAS,EAAC,8DAA8D,YACzE,KAAK,CAAC,KAAK,GACT,EACL,aACE,SAAS,EAAE,8BACT,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EACrC,EAAE,YAED,KAAK,CAAC,KAAK,GACT,KAVG,KAAK,CAAC,KAAK,CAWf,CACP,CAAC,GACC,EAEJ,SAAS,CAAC,CAAC,CAAC,CACX,0BACE,YAAG,SAAS,EAAC,qCAAqC,YAC/C,CAAC,CAAC,gBAAgB,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,GACjD,EACJ,YAAG,SAAS,EAAC,oCAAoC,YAAE,SAAS,GAAK,IAC7D,CACP,CAAC,CAAC,CAAC,IAAI,EAER,0BACE,YAAG,SAAS,EAAC,qCAAqC,YAC/C,CAAC,CAAC,mBAAmB,EAAE,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC,GACvD,EACJ,YAAG,SAAS,EAAC,8GAA8G,YACxH,YAAY,GACX,IACA,EAEL,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACrB,0BACE,YAAG,SAAS,EAAC,qCAAqC,YAC/C,CAAC,CAAC,eAAe,EAAE,EAAE,YAAY,EAAE,qBAAqB,EAAE,CAAC,GAC1D,EACJ,cAAK,SAAS,EAAC,6BAA6B,YACzC,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAC1B,eAEE,SAAS,EAAC,kEAAkE,YAE3E,QAAQ,IAHJ,QAAQ,CAIR,CACR,CAAC,GACE,IACF,CACP,CAAC,CAAC,CAAC,IAAI,EAER,0BACE,YAAG,SAAS,EAAC,qCAAqC,YAC/C,CAAC,CAAC,eAAe,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,GAChD,EACH,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CACrB,eACE,SAAS,EAAC,4DAA4D,eAC5D,MAAM,aAEhB,KAAC,WAAW,IAAC,SAAS,EAAC,uBAAuB,GAAG,EAChD,CAAC,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,IAC5C,CACP,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CACpB,YAAG,SAAS,EAAC,+BAA+B,YACzC,CAAC,CAAC,oBAAoB,EAAE;wCACvB,YAAY,EAAE,6BAA6B;qCAC5C,CAAC,GACA,CACL,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACtB,YAAG,SAAS,EAAC,oCAAoC,YAC9C,CAAC,CAAC,aAAa,EAAE;wCAChB,YAAY,EACV,+EAA+E;qCAClF,CAAC,GACA,CACL,CAAC,CAAC,CAAC,CACF,aAAI,SAAS,EAAC,0DAA0D,YACrE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,cAEE,SAAS,EAAC,wCAAwC,aAElD,KAAC,YAAY,IAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAI,EACpC,eAAM,SAAS,EAAC,gCAAgC,YAC7C,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,GAC1B,EACP,eAAM,SAAS,EAAC,sBAAsB,YAAE,GAAG,CAAC,MAAM,GAAQ,EACzD,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CACX,eACE,SAAS,EAAC,+CAA+C,EACzD,KAAK,EAAE,GAAG,CAAC,KAAK,YAEf,GAAG,CAAC,KAAK,GACL,CACR,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAC,gBAAgB,GAAG,CACpC,EACA,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAChB,gBAAM,SAAS,EAAC,6CAA6C,aAC1D,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,SAC/C,CACR,CAAC,CAAC,CAAC,IAAI,KAtBH,GAAG,CAAC,EAAE,CAuBR,CACN,CAAC,GACC,CACN,IACG,IACF,IACQ,GACT,CACV,CAAC;AACJ,CAAC","sourcesContent":["import { IconAlertTriangle, IconLoader2 } from \"@tabler/icons-react\";\n\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from \"../components/ui/dialog.js\";\nimport { useT } from \"../i18n.js\";\nimport { useAutomationRuns, type JobsScope } from \"./use-jobs.js\";\n\nexport interface AutomationDetailsField {\n label: string;\n value: string;\n mono?: boolean;\n}\n\nexport interface AutomationDetailsDialogProps {\n open: boolean;\n name: string;\n triggerSummary: string;\n fields: AutomationDetailsField[];\n condition: string | null;\n instructions: string;\n mcpTools: string[];\n lastError: string | null;\n scope: JobsScope;\n formatTimestamp: (value: number) => string;\n onClose: () => void;\n}\n\nfunction RunStatusDot({ status }: { status: string }) {\n const tone =\n status === \"success\"\n ? \"bg-emerald-500\"\n : status === \"error\"\n ? \"bg-destructive\"\n : // An interrupted run never reported an outcome, so it reads as\n // unknown rather than as still making progress.\n status === \"interrupted\"\n ? \"bg-muted-foreground\"\n : \"bg-amber-500\";\n return <span className={`size-1.5 shrink-0 rounded-full ${tone}`} />;\n}\n\nexport function AutomationDetailsDialog({\n open,\n name,\n triggerSummary,\n fields,\n condition,\n instructions,\n mcpTools,\n lastError,\n scope,\n formatTimestamp,\n onClose,\n}: AutomationDetailsDialogProps) {\n const t = useT();\n const runsQuery = useAutomationRuns(scope, open ? name : null, open);\n const runs = runsQuery.data ?? [];\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next) onClose();\n }}\n >\n <DialogContent className=\"max-h-[85vh] max-w-2xl overflow-y-auto\">\n <DialogHeader>\n <DialogTitle>{name.replace(/-/g, \" \")}</DialogTitle>\n <DialogDescription>{triggerSummary}</DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4\">\n {lastError ? (\n <div className=\"flex items-start gap-2 rounded-md border border-destructive/30 bg-destructive/5 p-2.5\">\n <IconAlertTriangle className=\"mt-0.5 size-4 shrink-0 text-destructive\" />\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-destructive\">\n {t(\"jobs.blockedTitle\", {\n defaultValue: \"This automation is not running\",\n })}\n </p>\n <p className=\"mt-0.5 break-words text-xs text-muted-foreground\">\n {lastError}\n </p>\n </div>\n </div>\n ) : null}\n\n <dl className=\"grid grid-cols-2 gap-x-4 gap-y-2\">\n {fields.map((field) => (\n <div key={field.label} className=\"min-w-0\">\n <dt className=\"text-[11px] uppercase tracking-wide text-muted-foreground/70\">\n {field.label}\n </dt>\n <dd\n className={`mt-0.5 break-words text-sm ${\n field.mono ? \"font-mono text-xs\" : \"\"\n }`}\n >\n {field.value}\n </dd>\n </div>\n ))}\n </dl>\n\n {condition ? (\n <div>\n <p className=\"text-xs font-medium text-foreground\">\n {t(\"jobs.condition\", { defaultValue: \"Condition\" })}\n </p>\n <p className=\"mt-1 text-sm text-muted-foreground\">{condition}</p>\n </div>\n ) : null}\n\n <div>\n <p className=\"text-xs font-medium text-foreground\">\n {t(\"jobs.instructions\", { defaultValue: \"Instructions\" })}\n </p>\n <p className=\"mt-1 max-h-56 overflow-y-auto whitespace-pre-wrap rounded-md bg-muted/50 p-2.5 text-sm text-muted-foreground\">\n {instructions}\n </p>\n </div>\n\n {mcpTools.length > 0 ? (\n <div>\n <p className=\"text-xs font-medium text-foreground\">\n {t(\"jobs.mcpTools\", { defaultValue: \"Connected MCP tools\" })}\n </p>\n <div className=\"mt-1 flex flex-wrap gap-1.5\">\n {mcpTools.map((toolName) => (\n <code\n key={toolName}\n className=\"rounded bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground\"\n >\n {toolName}\n </code>\n ))}\n </div>\n </div>\n ) : null}\n\n <div>\n <p className=\"text-xs font-medium text-foreground\">\n {t(\"jobs.pastRuns\", { defaultValue: \"Past runs\" })}\n </p>\n {runsQuery.isLoading ? (\n <div\n className=\"mt-2 flex items-center gap-2 text-xs text-muted-foreground\"\n aria-busy=\"true\"\n >\n <IconLoader2 className=\"size-3.5 animate-spin\" />\n {t(\"jobs.loading\", { defaultValue: \"Loading…\" })}\n </div>\n ) : runsQuery.error ? (\n <p className=\"mt-1 text-xs text-destructive\">\n {t(\"jobs.runsLoadError\", {\n defaultValue: \"Could not load run history.\",\n })}\n </p>\n ) : runs.length === 0 ? (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {t(\"jobs.noRuns\", {\n defaultValue:\n \"This automation has not executed yet. Only real executions are recorded here.\",\n })}\n </p>\n ) : (\n <ul className=\"mt-2 divide-y divide-border/60 border-y border-border/60\">\n {runs.map((run) => (\n <li\n key={run.id}\n className=\"flex items-center gap-2 py-1.5 text-xs\"\n >\n <RunStatusDot status={run.status} />\n <span className=\"shrink-0 text-muted-foreground\">\n {formatTimestamp(run.startedAt)}\n </span>\n <span className=\"shrink-0 font-medium\">{run.status}</span>\n {run.error ? (\n <span\n className=\"min-w-0 flex-1 truncate text-muted-foreground\"\n title={run.error}\n >\n {run.error}\n </span>\n ) : (\n <span className=\"min-w-0 flex-1\" />\n )}\n {run.finishedAt ? (\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">\n {Math.round((run.finishedAt - run.startedAt) / 1000)}s\n </span>\n ) : null}\n </li>\n ))}\n </ul>\n )}\n </div>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface AutomationScheduleDialogProps {
|
|
2
|
+
open: boolean;
|
|
3
|
+
name: string;
|
|
4
|
+
schedule: string;
|
|
5
|
+
timezone: string | null;
|
|
6
|
+
saving: boolean;
|
|
7
|
+
error?: string | null;
|
|
8
|
+
onCancel: () => void;
|
|
9
|
+
onSave: (next: {
|
|
10
|
+
schedule: string;
|
|
11
|
+
timezone: string;
|
|
12
|
+
}) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare function AutomationScheduleDialog({ open, name, schedule, timezone, saving, error, onCancel, onSave, }: AutomationScheduleDialogProps): import("react").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=AutomationScheduleDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationScheduleDialog.d.ts","sourceRoot":"","sources":["../../../src/client/agent-page/AutomationScheduleDialog.tsx"],"names":[],"mappings":"AA6BA,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAChE;AAED,wBAAgB,wBAAwB,CAAC,EACvC,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,KAAK,EACL,QAAQ,EACR,MAAM,GACP,EAAE,6BAA6B,+BAkI/B"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from "@agent-native/toolkit/ui/button";
|
|
3
|
+
import { Input } from "@agent-native/toolkit/ui/input";
|
|
4
|
+
import { IconLoader2 } from "@tabler/icons-react";
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "../components/ui/dialog.js";
|
|
7
|
+
import { useT } from "../i18n.js";
|
|
8
|
+
import { TimezoneSelect, browserTimezone } from "./TimezoneSelect.js";
|
|
9
|
+
const PRESETS = [
|
|
10
|
+
{ label: "Every hour", cron: "0 * * * *" },
|
|
11
|
+
{ label: "Every day at 8:00", cron: "0 8 * * *" },
|
|
12
|
+
{ label: "Every weekday at 9:00", cron: "0 9 * * 1-5" },
|
|
13
|
+
{ label: "Every Monday at 8:00", cron: "0 8 * * 1" },
|
|
14
|
+
];
|
|
15
|
+
const CRON_FIELD_COUNT = 5;
|
|
16
|
+
function looksLikeCron(value) {
|
|
17
|
+
return value.trim().split(/\s+/).length === CRON_FIELD_COUNT;
|
|
18
|
+
}
|
|
19
|
+
export function AutomationScheduleDialog({ open, name, schedule, timezone, saving, error, onCancel, onSave, }) {
|
|
20
|
+
const t = useT();
|
|
21
|
+
const [value, setValue] = useState(schedule);
|
|
22
|
+
const [zone, setZone] = useState(timezone || browserTimezone());
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!open)
|
|
25
|
+
return;
|
|
26
|
+
setValue(schedule);
|
|
27
|
+
setZone(timezone || browserTimezone());
|
|
28
|
+
}, [open, schedule, timezone]);
|
|
29
|
+
const trimmed = value.trim();
|
|
30
|
+
const valid = looksLikeCron(trimmed);
|
|
31
|
+
const changed = trimmed !== schedule.trim() || zone !== (timezone || browserTimezone());
|
|
32
|
+
return (_jsx(Dialog, { open: open, onOpenChange: (next) => {
|
|
33
|
+
if (!next && !saving)
|
|
34
|
+
onCancel();
|
|
35
|
+
}, children: _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: t("jobs.editScheduleTitle", {
|
|
36
|
+
defaultValue: "Edit schedule — {{name}}",
|
|
37
|
+
name: name.replace(/-/g, " "),
|
|
38
|
+
}) }), _jsx(DialogDescription, { children: t("jobs.editScheduleDescription", {
|
|
39
|
+
defaultValue: "The clock time below is read in the timezone you pick, so 8:00 means 8:00 there.",
|
|
40
|
+
}) })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("label", { className: "text-xs font-medium text-foreground", htmlFor: "automation-schedule", children: t("jobs.cronExpression", { defaultValue: "Cron expression" }) }), _jsx(Input, { id: "automation-schedule", className: "mt-1 font-mono text-sm", value: value, spellCheck: false, autoComplete: "off", disabled: saving, onChange: (event) => setValue(event.target.value) }), _jsx("p", { className: "mt-1 text-[11px] text-muted-foreground", children: t("jobs.cronFormatHint", {
|
|
41
|
+
defaultValue: "minute hour day-of-month month day-of-week",
|
|
42
|
+
}) })] }), _jsx("div", { className: "flex flex-wrap gap-1.5", children: PRESETS.map((preset) => (_jsx(Button, { type: "button", variant: "outline", size: "sm", className: "h-7 cursor-pointer text-[11px]", disabled: saving, onClick: () => setValue(preset.cron), children: preset.label }, preset.cron))) }), _jsxs("div", { children: [_jsx("label", { className: "text-xs font-medium text-foreground", htmlFor: "automation-timezone", children: t("jobs.timezone", { defaultValue: "Timezone" }) }), _jsx("div", { className: "mt-1", children: _jsx(TimezoneSelect, { id: "automation-timezone", value: zone, disabled: saving, onChange: setZone, suggested: [browserTimezone()] }) })] }), trimmed && !valid ? (_jsx("p", { className: "text-xs text-destructive", children: t("jobs.cronFieldCount", {
|
|
43
|
+
defaultValue: "A cron expression needs exactly 5 fields.",
|
|
44
|
+
}) })) : null, error ? _jsx("p", { className: "text-xs text-destructive", children: error }) : null] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", className: "cursor-pointer", disabled: saving, onClick: onCancel, children: t("jobs.cancel", { defaultValue: "Cancel" }) }), _jsxs(Button, { type: "button", className: "cursor-pointer", disabled: saving || !valid || !changed, onClick: () => onSave({ schedule: trimmed, timezone: zone }), children: [saving ? _jsx(IconLoader2, { className: "size-4 animate-spin" }) : null, t("jobs.saveSchedule", { defaultValue: "Save schedule" })] })] })] }) }));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=AutomationScheduleDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutomationScheduleDialog.js","sourceRoot":"","sources":["../../../src/client/agent-page/AutomationScheduleDialog.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Button } from \"@agent-native/toolkit/ui/button\";\nimport { Input } from \"@agent-native/toolkit/ui/input\";\nimport { IconLoader2 } from \"@tabler/icons-react\";\nimport { useEffect, useState } from \"react\";\n\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"../components/ui/dialog.js\";\nimport { useT } from \"../i18n.js\";\nimport { TimezoneSelect, browserTimezone } from \"./TimezoneSelect.js\";\n\nconst PRESETS: { label: string; cron: string }[] = [\n { label: \"Every hour\", cron: \"0 * * * *\" },\n { label: \"Every day at 8:00\", cron: \"0 8 * * *\" },\n { label: \"Every weekday at 9:00\", cron: \"0 9 * * 1-5\" },\n { label: \"Every Monday at 8:00\", cron: \"0 8 * * 1\" },\n];\n\nconst CRON_FIELD_COUNT = 5;\n\nfunction looksLikeCron(value: string): boolean {\n return value.trim().split(/\\s+/).length === CRON_FIELD_COUNT;\n}\n\nexport interface AutomationScheduleDialogProps {\n open: boolean;\n name: string;\n schedule: string;\n timezone: string | null;\n saving: boolean;\n error?: string | null;\n onCancel: () => void;\n onSave: (next: { schedule: string; timezone: string }) => void;\n}\n\nexport function AutomationScheduleDialog({\n open,\n name,\n schedule,\n timezone,\n saving,\n error,\n onCancel,\n onSave,\n}: AutomationScheduleDialogProps) {\n const t = useT();\n const [value, setValue] = useState(schedule);\n const [zone, setZone] = useState(timezone || browserTimezone());\n\n useEffect(() => {\n if (!open) return;\n setValue(schedule);\n setZone(timezone || browserTimezone());\n }, [open, schedule, timezone]);\n\n const trimmed = value.trim();\n const valid = looksLikeCron(trimmed);\n const changed =\n trimmed !== schedule.trim() || zone !== (timezone || browserTimezone());\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next && !saving) onCancel();\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {t(\"jobs.editScheduleTitle\", {\n defaultValue: \"Edit schedule — {{name}}\",\n name: name.replace(/-/g, \" \"),\n })}\n </DialogTitle>\n <DialogDescription>\n {t(\"jobs.editScheduleDescription\", {\n defaultValue:\n \"The clock time below is read in the timezone you pick, so 8:00 means 8:00 there.\",\n })}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-3\">\n <div>\n <label\n className=\"text-xs font-medium text-foreground\"\n htmlFor=\"automation-schedule\"\n >\n {t(\"jobs.cronExpression\", { defaultValue: \"Cron expression\" })}\n </label>\n <Input\n id=\"automation-schedule\"\n className=\"mt-1 font-mono text-sm\"\n value={value}\n spellCheck={false}\n autoComplete=\"off\"\n disabled={saving}\n onChange={(event) => setValue(event.target.value)}\n />\n <p className=\"mt-1 text-[11px] text-muted-foreground\">\n {t(\"jobs.cronFormatHint\", {\n defaultValue: \"minute hour day-of-month month day-of-week\",\n })}\n </p>\n </div>\n\n <div className=\"flex flex-wrap gap-1.5\">\n {PRESETS.map((preset) => (\n <Button\n key={preset.cron}\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-7 cursor-pointer text-[11px]\"\n disabled={saving}\n onClick={() => setValue(preset.cron)}\n >\n {preset.label}\n </Button>\n ))}\n </div>\n\n <div>\n <label\n className=\"text-xs font-medium text-foreground\"\n htmlFor=\"automation-timezone\"\n >\n {t(\"jobs.timezone\", { defaultValue: \"Timezone\" })}\n </label>\n <div className=\"mt-1\">\n <TimezoneSelect\n id=\"automation-timezone\"\n value={zone}\n disabled={saving}\n onChange={setZone}\n suggested={[browserTimezone()]}\n />\n </div>\n </div>\n\n {trimmed && !valid ? (\n <p className=\"text-xs text-destructive\">\n {t(\"jobs.cronFieldCount\", {\n defaultValue: \"A cron expression needs exactly 5 fields.\",\n })}\n </p>\n ) : null}\n {error ? <p className=\"text-xs text-destructive\">{error}</p> : null}\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"cursor-pointer\"\n disabled={saving}\n onClick={onCancel}\n >\n {t(\"jobs.cancel\", { defaultValue: \"Cancel\" })}\n </Button>\n <Button\n type=\"button\"\n className=\"cursor-pointer\"\n disabled={saving || !valid || !changed}\n onClick={() => onSave({ schedule: trimmed, timezone: zone })}\n >\n {saving ? <IconLoader2 className=\"size-4 animate-spin\" /> : null}\n {t(\"jobs.saveSchedule\", { defaultValue: \"Save schedule\" })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** The browser's IANA zone, or UTC when the runtime cannot report one. */
|
|
2
|
+
export declare function browserTimezone(): string;
|
|
3
|
+
export interface TimezoneSelectProps {
|
|
4
|
+
value: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
onChange: (timezone: string) => void;
|
|
7
|
+
/** Zones to surface above the full list, e.g. the currently stored one. */
|
|
8
|
+
suggested?: string[];
|
|
9
|
+
/**
|
|
10
|
+
* Label for a leading `system` choice. Settings offer it so the preference
|
|
11
|
+
* stays revertible; a schedule must name a concrete zone and omits it.
|
|
12
|
+
*/
|
|
13
|
+
systemLabel?: string;
|
|
14
|
+
id?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function TimezoneSelect({ value, disabled, onChange, suggested, systemLabel, id, }: TimezoneSelectProps): import("react").JSX.Element;
|
|
17
|
+
//# sourceMappingURL=TimezoneSelect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimezoneSelect.d.ts","sourceRoot":"","sources":["../../../src/client/agent-page/TimezoneSelect.tsx"],"names":[],"mappings":"AAmBA,0EAA0E;AAC1E,wBAAgB,eAAe,IAAI,MAAM,CAMxC;AAqED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,SAAc,EACd,WAAW,EACX,EAAE,GACH,EAAE,mBAAmB,+BA4HrB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from "@agent-native/toolkit/ui/command";
|
|
3
|
+
import { Popover, PopoverContent, PopoverTrigger, } from "@agent-native/toolkit/ui/popover";
|
|
4
|
+
import { IconCheck, IconChevronDown } from "@tabler/icons-react";
|
|
5
|
+
import { useMemo, useState } from "react";
|
|
6
|
+
const SYSTEM_VALUE = "system";
|
|
7
|
+
/** The browser's IANA zone, or UTC when the runtime cannot report one. */
|
|
8
|
+
export function browserTimezone() {
|
|
9
|
+
try {
|
|
10
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return "UTC";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function supportedTimezones() {
|
|
17
|
+
const supported = Intl.supportedValuesOf;
|
|
18
|
+
const zones = supported ? supported("timeZone") : [];
|
|
19
|
+
// Older runtimes omit supportedValuesOf; the browser zone plus UTC still
|
|
20
|
+
// covers the common case rather than leaving an empty, unusable menu.
|
|
21
|
+
const base = zones.length ? zones : [browserTimezone()];
|
|
22
|
+
return [...new Set(["UTC", ...base])];
|
|
23
|
+
}
|
|
24
|
+
function describeZone(zone, now) {
|
|
25
|
+
let parts;
|
|
26
|
+
try {
|
|
27
|
+
parts = new Intl.DateTimeFormat("en-US", {
|
|
28
|
+
timeZone: zone,
|
|
29
|
+
hour: "numeric",
|
|
30
|
+
minute: "2-digit",
|
|
31
|
+
hour12: true,
|
|
32
|
+
timeZoneName: "longOffset",
|
|
33
|
+
}).formatToParts(now);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// A zone this runtime cannot resolve would otherwise throw during render.
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const part = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
40
|
+
// `longOffset` collapses to a bare "GMT" at zero rather than "GMT+00:00".
|
|
41
|
+
const raw = part("timeZoneName");
|
|
42
|
+
const offsetLabel = raw === "GMT" ? "GMT+00:00" : raw;
|
|
43
|
+
const match = /^GMT([+-])(\d{2}):(\d{2})$/.exec(offsetLabel);
|
|
44
|
+
const offsetMinutes = match
|
|
45
|
+
? (match[1] === "-" ? -1 : 1) * (Number(match[2]) * 60 + Number(match[3]))
|
|
46
|
+
: 0;
|
|
47
|
+
return {
|
|
48
|
+
zone,
|
|
49
|
+
offsetMinutes,
|
|
50
|
+
offsetLabel,
|
|
51
|
+
timeLabel: `${part("hour")}:${part("minute")}${part("dayPeriod").toLowerCase()}`,
|
|
52
|
+
placeLabel: zone.replace(/_/g, " "),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function zoneOptions(extra, now) {
|
|
56
|
+
const zones = [...new Set([...extra, ...supportedTimezones()])];
|
|
57
|
+
return zones
|
|
58
|
+
.map((zone) => describeZone(zone, now))
|
|
59
|
+
.filter((option) => option !== null)
|
|
60
|
+
.sort((a, b) => a.offsetMinutes - b.offsetMinutes ||
|
|
61
|
+
a.placeLabel.localeCompare(b.placeLabel));
|
|
62
|
+
}
|
|
63
|
+
export function TimezoneSelect({ value, disabled, onChange, suggested = [], systemLabel, id, }) {
|
|
64
|
+
const [open, setOpen] = useState(false);
|
|
65
|
+
const detected = browserTimezone();
|
|
66
|
+
// 418 zones each need their own formatter, so only pay for that once the
|
|
67
|
+
// list is actually on screen. Reopening re-reads the clock.
|
|
68
|
+
const options = useMemo(() => {
|
|
69
|
+
if (!open)
|
|
70
|
+
return [];
|
|
71
|
+
const pinned = [...suggested, value].filter((zone) => zone && zone !== SYSTEM_VALUE);
|
|
72
|
+
return zoneOptions(pinned, new Date());
|
|
73
|
+
}, [open, suggested, value]);
|
|
74
|
+
const selected = useMemo(() => (value === SYSTEM_VALUE ? null : describeZone(value, new Date())), [value]);
|
|
75
|
+
const triggerLabel = value === SYSTEM_VALUE
|
|
76
|
+
? (systemLabel ?? SYSTEM_VALUE)
|
|
77
|
+
: selected
|
|
78
|
+
? `(${selected.offsetLabel}) ${selected.placeLabel}`
|
|
79
|
+
: value;
|
|
80
|
+
function choose(zone) {
|
|
81
|
+
setOpen(false);
|
|
82
|
+
if (zone !== value)
|
|
83
|
+
onChange(zone);
|
|
84
|
+
}
|
|
85
|
+
function renderZone(option, key) {
|
|
86
|
+
return (_jsxs(CommandItem, {
|
|
87
|
+
// Searched text: place and offset both need to match what users type.
|
|
88
|
+
// The key is folded in because the detected zone is listed twice, and
|
|
89
|
+
// cmdk treats two items with the same value as the same item.
|
|
90
|
+
value: `${option.placeLabel} ${option.offsetLabel} ${option.zone} ${key}`, onSelect: () => choose(option.zone), className: "gap-2", children: [_jsx(IconCheck, { className: `size-4 shrink-0 ${option.zone === value ? "opacity-100" : "opacity-0"}` }), _jsxs("span", { className: "w-24 shrink-0 tabular-nums text-muted-foreground", children: ["(", option.offsetLabel, ")"] }), _jsx("span", { className: "truncate", children: option.placeLabel }), _jsx("span", { className: "ms-auto shrink-0 tabular-nums text-muted-foreground", children: option.timeLabel })] }, key));
|
|
91
|
+
}
|
|
92
|
+
const detectedOption = options.find((option) => option.zone === detected);
|
|
93
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { id: id, type: "button", role: "combobox", "aria-expanded": open, disabled: disabled,
|
|
94
|
+
// Matches the text inputs it sits beside, not a button.
|
|
95
|
+
className: "flex h-10 w-full items-center justify-between gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx("span", { className: "truncate", children: triggerLabel }), _jsx(IconChevronDown, { className: "size-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { align: "start", className: "w-[--radix-popover-trigger-width] p-0", children: _jsxs(Command
|
|
96
|
+
// cmdk's default scorer matches loose subsequences, so "Perth" would
|
|
97
|
+
// otherwise surface most of the list.
|
|
98
|
+
, {
|
|
99
|
+
// cmdk's default scorer matches loose subsequences, so "Perth" would
|
|
100
|
+
// otherwise surface most of the list.
|
|
101
|
+
filter: (itemValue, search) => itemValue.toLowerCase().includes(search.toLowerCase().trim())
|
|
102
|
+
? 1
|
|
103
|
+
: 0, children: [_jsx(CommandInput, { placeholder: "Search a city or region\u2026" }), _jsxs(CommandList, { className: "max-h-72", children: [_jsx(CommandEmpty, { children: "No matching timezone." }), systemLabel || detectedOption ? (_jsxs(_Fragment, { children: [_jsxs(CommandGroup, { children: [systemLabel ? (_jsxs(CommandItem, { value: `${systemLabel} follow browser automatic`, onSelect: () => choose(SYSTEM_VALUE), className: "gap-2", children: [_jsx(IconCheck, { className: `size-4 shrink-0 ${value === SYSTEM_VALUE ? "opacity-100" : "opacity-0"}` }), _jsx("span", { className: "truncate", children: systemLabel })] })) : null, detectedOption
|
|
104
|
+
? renderZone(detectedOption, "detected")
|
|
105
|
+
: null] }), _jsx(CommandSeparator, {})] })) : null, _jsx(CommandGroup, { children: options.map((option) => renderZone(option, option.zone)) })] })] }) })] }));
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=TimezoneSelect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimezoneSelect.js","sourceRoot":"","sources":["../../../src/client/agent-page/TimezoneSelect.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from \"@agent-native/toolkit/ui/command\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@agent-native/toolkit/ui/popover\";\nimport { IconCheck, IconChevronDown } from \"@tabler/icons-react\";\nimport { useMemo, useState } from \"react\";\n\nconst SYSTEM_VALUE = \"system\";\n\n/** The browser's IANA zone, or UTC when the runtime cannot report one. */\nexport function browserTimezone(): string {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\";\n } catch {\n return \"UTC\";\n }\n}\n\nfunction supportedTimezones(): string[] {\n const supported = (\n Intl as unknown as { supportedValuesOf?: (key: string) => string[] }\n ).supportedValuesOf;\n const zones = supported ? supported(\"timeZone\") : [];\n // Older runtimes omit supportedValuesOf; the browser zone plus UTC still\n // covers the common case rather than leaving an empty, unusable menu.\n const base = zones.length ? zones : [browserTimezone()];\n return [...new Set([\"UTC\", ...base])];\n}\n\ninterface ZoneOption {\n zone: string;\n /** Minutes east of GMT, used to order the list the way a map reads. */\n offsetMinutes: number;\n offsetLabel: string;\n timeLabel: string;\n placeLabel: string;\n}\n\nfunction describeZone(zone: string, now: Date): ZoneOption | null {\n let parts: Intl.DateTimeFormatPart[];\n try {\n parts = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: zone,\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n timeZoneName: \"longOffset\",\n }).formatToParts(now);\n } catch {\n // A zone this runtime cannot resolve would otherwise throw during render.\n return null;\n }\n\n const part = (type: Intl.DateTimeFormatPartTypes) =>\n parts.find((p) => p.type === type)?.value ?? \"\";\n\n // `longOffset` collapses to a bare \"GMT\" at zero rather than \"GMT+00:00\".\n const raw = part(\"timeZoneName\");\n const offsetLabel = raw === \"GMT\" ? \"GMT+00:00\" : raw;\n const match = /^GMT([+-])(\\d{2}):(\\d{2})$/.exec(offsetLabel);\n const offsetMinutes = match\n ? (match[1] === \"-\" ? -1 : 1) * (Number(match[2]) * 60 + Number(match[3]))\n : 0;\n\n return {\n zone,\n offsetMinutes,\n offsetLabel,\n timeLabel: `${part(\"hour\")}:${part(\"minute\")}${part(\"dayPeriod\").toLowerCase()}`,\n placeLabel: zone.replace(/_/g, \" \"),\n };\n}\n\nfunction zoneOptions(extra: string[], now: Date): ZoneOption[] {\n const zones = [...new Set([...extra, ...supportedTimezones()])];\n return zones\n .map((zone) => describeZone(zone, now))\n .filter((option): option is ZoneOption => option !== null)\n .sort(\n (a, b) =>\n a.offsetMinutes - b.offsetMinutes ||\n a.placeLabel.localeCompare(b.placeLabel),\n );\n}\n\nexport interface TimezoneSelectProps {\n value: string;\n disabled?: boolean;\n onChange: (timezone: string) => void;\n /** Zones to surface above the full list, e.g. the currently stored one. */\n suggested?: string[];\n /**\n * Label for a leading `system` choice. Settings offer it so the preference\n * stays revertible; a schedule must name a concrete zone and omits it.\n */\n systemLabel?: string;\n id?: string;\n}\n\nexport function TimezoneSelect({\n value,\n disabled,\n onChange,\n suggested = [],\n systemLabel,\n id,\n}: TimezoneSelectProps) {\n const [open, setOpen] = useState(false);\n const detected = browserTimezone();\n\n // 418 zones each need their own formatter, so only pay for that once the\n // list is actually on screen. Reopening re-reads the clock.\n const options = useMemo(() => {\n if (!open) return [];\n const pinned = [...suggested, value].filter(\n (zone) => zone && zone !== SYSTEM_VALUE,\n );\n return zoneOptions(pinned, new Date());\n }, [open, suggested, value]);\n\n const selected = useMemo(\n () => (value === SYSTEM_VALUE ? null : describeZone(value, new Date())),\n [value],\n );\n\n const triggerLabel =\n value === SYSTEM_VALUE\n ? (systemLabel ?? SYSTEM_VALUE)\n : selected\n ? `(${selected.offsetLabel}) ${selected.placeLabel}`\n : value;\n\n function choose(zone: string) {\n setOpen(false);\n if (zone !== value) onChange(zone);\n }\n\n function renderZone(option: ZoneOption, key: string) {\n return (\n <CommandItem\n key={key}\n // Searched text: place and offset both need to match what users type.\n // The key is folded in because the detected zone is listed twice, and\n // cmdk treats two items with the same value as the same item.\n value={`${option.placeLabel} ${option.offsetLabel} ${option.zone} ${key}`}\n onSelect={() => choose(option.zone)}\n className=\"gap-2\"\n >\n <IconCheck\n className={`size-4 shrink-0 ${\n option.zone === value ? \"opacity-100\" : \"opacity-0\"\n }`}\n />\n <span className=\"w-24 shrink-0 tabular-nums text-muted-foreground\">\n ({option.offsetLabel})\n </span>\n <span className=\"truncate\">{option.placeLabel}</span>\n <span className=\"ms-auto shrink-0 tabular-nums text-muted-foreground\">\n {option.timeLabel}\n </span>\n </CommandItem>\n );\n }\n\n const detectedOption = options.find((option) => option.zone === detected);\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n id={id}\n type=\"button\"\n role=\"combobox\"\n aria-expanded={open}\n disabled={disabled}\n // Matches the text inputs it sits beside, not a button.\n className=\"flex h-10 w-full items-center justify-between gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <span className=\"truncate\">{triggerLabel}</span>\n <IconChevronDown className=\"size-4 shrink-0 opacity-50\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"w-[--radix-popover-trigger-width] p-0\"\n >\n <Command\n // cmdk's default scorer matches loose subsequences, so \"Perth\" would\n // otherwise surface most of the list.\n filter={(itemValue, search) =>\n itemValue.toLowerCase().includes(search.toLowerCase().trim())\n ? 1\n : 0\n }\n >\n <CommandInput placeholder=\"Search a city or region…\" />\n <CommandList className=\"max-h-72\">\n <CommandEmpty>No matching timezone.</CommandEmpty>\n {systemLabel || detectedOption ? (\n <>\n <CommandGroup>\n {systemLabel ? (\n <CommandItem\n value={`${systemLabel} follow browser automatic`}\n onSelect={() => choose(SYSTEM_VALUE)}\n className=\"gap-2\"\n >\n <IconCheck\n className={`size-4 shrink-0 ${\n value === SYSTEM_VALUE ? \"opacity-100\" : \"opacity-0\"\n }`}\n />\n <span className=\"truncate\">{systemLabel}</span>\n </CommandItem>\n ) : null}\n {detectedOption\n ? renderZone(detectedOption, \"detected\")\n : null}\n </CommandGroup>\n <CommandSeparator />\n </>\n ) : null}\n <CommandGroup>\n {options.map((option) => renderZone(option, option.zone))}\n </CommandGroup>\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|