@agent-native/core 0.134.0 → 0.135.0
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/docs/content/template-content-developers.mdx +1 -1
- 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/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-29-meeting-notes-no-longer-transcribe-the-other-side-twice-when.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/hooks/useMeetingTranscription.ts +37 -48
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +331 -36
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +7 -5
- package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +182 -106
- package/corpus/templates/clips/desktop/src/lib/upload-recovery.ts +129 -0
- package/corpus/templates/clips/desktop/src/overlays/live-transcript.tsx +43 -14
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +3 -3
- package/corpus/templates/clips/desktop/src-tauri/src/echo_guard.rs +443 -0
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -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/src-tauri/src/whisper_speech.rs +125 -16
- 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/.agents/skills/document-editing/references/databases.md +6 -4
- package/corpus/templates/content/actions/_database-membership-lock.ts +25 -0
- package/corpus/templates/content/actions/_database-row-batch.ts +6 -2
- package/corpus/templates/content/actions/_database-source-utils.ts +289 -129
- package/corpus/templates/content/actions/_database-utils.ts +12 -3
- package/corpus/templates/content/actions/add-comment.ts +15 -1
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +39 -21
- package/corpus/templates/content/actions/attach-content-database-source.ts +4 -1
- package/corpus/templates/content/actions/change-content-database-source-role.ts +3 -5
- package/corpus/templates/content/actions/duplicate-document-property.ts +59 -46
- package/corpus/templates/content/actions/execute-builder-source-execution.ts +77 -71
- package/corpus/templates/content/actions/list-documents.ts +1 -0
- package/corpus/templates/content/actions/materialize-builder-required-fields.ts +7 -0
- package/corpus/templates/content/actions/remove-database-items.ts +183 -0
- package/corpus/templates/content/actions/set-document-property.ts +57 -39
- package/corpus/templates/content/actions/sync-local-folder-source.ts +7 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +5 -2
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +50 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +471 -329
- package/corpus/templates/content/app/components/editor/database/row-access.ts +45 -0
- package/corpus/templates/content/app/components/editor/database/shared.tsx +141 -38
- package/corpus/templates/content/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +2 -2
- package/corpus/templates/content/app/hooks/use-content-prefs.ts +55 -0
- package/corpus/templates/content/app/i18n-data.ts +170 -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-07-30-database-rows-can-now-be-removed-without-deleting-their-page.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/parity/eval-scenarios.ts +2 -2
- package/corpus/templates/content/parity/matrix.md +1 -1
- package/corpus/templates/content/parity/matrix.ts +4 -5
- package/corpus/templates/content/server/lib/comment-notifications.ts +146 -0
- 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 +4 -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/.generated/bridge/editor-chrome.generated.ts +26 -11
- package/corpus/templates/design/actions/take-design-screenshot.ts +7 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +11 -3
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +4 -1
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +54 -17
- package/corpus/templates/design/app/components/design/design-canvas/local-runtime.ts +126 -0
- package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +2 -0
- package/corpus/templates/design/app/pages/Index.tsx +3 -1
- package/corpus/templates/design/app/pages/Present.tsx +2 -1
- package/corpus/templates/design/app/routes/settings.tsx +14 -22
- package/corpus/templates/design/changelog/2026-07-30-a-broken-inline-script-in-a-generated-screen-is-now-caught-o.md +6 -0
- package/corpus/templates/design/changelog/2026-07-30-design-html-is-now-validated-with-a-spec-grade-html-parser-i.md +6 -0
- package/corpus/templates/design/changelog/2026-07-30-designs-now-load-their-tailwind-and-alpine-runtimes-from-the.md +6 -0
- package/corpus/templates/design/changelog/2026-07-30-designs-with-a-broken-alpine-expression-are-now-caught-on-sa.md +6 -0
- package/corpus/templates/design/changelog/2026-07-30-editing-a-design-no-longer-strips-its-styling-the-canvas-kep.md +6 -0
- 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/package.json +4 -0
- package/corpus/templates/design/shared/html-integrity.ts +802 -556
- 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/collab/struct-routes.d.ts +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 +2 -2
- package/dist/observability/routes.d.ts +1 -1
- 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/provider-api/actions/custom-provider-registration.d.ts +10 -10
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- 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/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/docs/content/template-content-developers.mdx +1 -1
- 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/index.ts +5 -0
- package/src/sharing/recipients.ts +67 -0
- package/src/templates/chat/app/routes/settings.tsx +14 -22
- package/src/templates/chat/vitest.config.ts +9 -0
- package/src/triggers/actions/list-automations.ts +27 -8
- package/src/triggers/actions/manage-automation.ts +17 -6
- package/src/triggers/actions.ts +16 -4
- package/src/triggers/dispatcher.ts +44 -30
- package/src/triggers/routes.ts +19 -6
- package/src/vitest-config.ts +68 -0
- package/corpus/templates/content/actions/delete-database-items.ts +0 -89
|
@@ -8,6 +8,7 @@ import { assertAccess } from "@agent-native/core/sharing";
|
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
|
|
10
10
|
import { getDb, schema } from "../server/db/index.js"; // ensure registerShareableResource runs
|
|
11
|
+
import { notifyDeckComment } from "../server/lib/comment-notifications.js";
|
|
11
12
|
|
|
12
13
|
function displayNameFromEmail(email: string): string {
|
|
13
14
|
const local = email.split("@")[0] || email;
|
|
@@ -56,6 +57,16 @@ export default defineAction({
|
|
|
56
57
|
authorName,
|
|
57
58
|
});
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
const notified = await notifyDeckComment({
|
|
61
|
+
deckId,
|
|
62
|
+
slideId,
|
|
63
|
+
threadId,
|
|
64
|
+
authorEmail,
|
|
65
|
+
authorName,
|
|
66
|
+
content,
|
|
67
|
+
isReply: Boolean(parentId ?? args.threadId),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return { id, threadId, notified };
|
|
60
71
|
},
|
|
61
72
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@agent-native/toolkit/ui/switch";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { agentNativePath } from "@agent-native/core/client/api-path";
|
|
2
|
+
import type { SlidesUserPrefs } from "@shared/slides-user-prefs";
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
|
|
5
|
+
const PREFS_PATH = "/_agent-native/slides/user-prefs";
|
|
6
|
+
|
|
7
|
+
export interface SlidesPrefsState {
|
|
8
|
+
prefs: SlidesUserPrefs;
|
|
9
|
+
loading: boolean;
|
|
10
|
+
/** Applies the patch optimistically and rolls back if the write fails. */
|
|
11
|
+
save: (patch: SlidesUserPrefs) => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function useSlidesPrefs(): SlidesPrefsState {
|
|
15
|
+
const [prefs, setPrefs] = useState<SlidesUserPrefs>({});
|
|
16
|
+
const [loading, setLoading] = useState(true);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
let cancelled = false;
|
|
20
|
+
void (async () => {
|
|
21
|
+
try {
|
|
22
|
+
const res = await fetch(agentNativePath(PREFS_PATH));
|
|
23
|
+
const json = res.ok ? await res.json() : null;
|
|
24
|
+
if (cancelled) return;
|
|
25
|
+
if (json && typeof json === "object" && !("error" in json)) {
|
|
26
|
+
setPrefs(json as SlidesUserPrefs);
|
|
27
|
+
}
|
|
28
|
+
} finally {
|
|
29
|
+
if (!cancelled) setLoading(false);
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
32
|
+
return () => {
|
|
33
|
+
cancelled = true;
|
|
34
|
+
};
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
const save = useCallback(
|
|
38
|
+
async (patch: SlidesUserPrefs) => {
|
|
39
|
+
const previous = prefs;
|
|
40
|
+
setPrefs((current) => ({ ...current, ...patch }));
|
|
41
|
+
const res = await fetch(agentNativePath(PREFS_PATH), {
|
|
42
|
+
method: "PUT",
|
|
43
|
+
headers: { "Content-Type": "application/json" },
|
|
44
|
+
body: JSON.stringify(patch),
|
|
45
|
+
});
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
setPrefs(previous);
|
|
48
|
+
throw new Error(`Save failed (${res.status})`);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
[prefs],
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return { prefs, loading, save };
|
|
55
|
+
}
|
|
@@ -28,6 +28,10 @@ const messages = {
|
|
|
28
28
|
settings: {
|
|
29
29
|
title: "Settings",
|
|
30
30
|
description: "Language and workspace preferences for this app.",
|
|
31
|
+
emailNotifications: "Email notifications",
|
|
32
|
+
emailNotificationsDescription:
|
|
33
|
+
"Get an email when someone comments on or replies in your deck.",
|
|
34
|
+
saveFailed: "Failed to save",
|
|
31
35
|
languageTitle: "Language",
|
|
32
36
|
languageDescription:
|
|
33
37
|
"Choose the interface language. This preference is saved for your account.",
|
|
@@ -3,6 +3,8 @@ import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
|
|
|
3
3
|
import { TeamPage } from "@agent-native/core/client/org";
|
|
4
4
|
import {
|
|
5
5
|
AccountSettingsCard,
|
|
6
|
+
SettingsGroup,
|
|
7
|
+
SettingsRow,
|
|
6
8
|
SettingsTabsPage,
|
|
7
9
|
useAgentSettingsTabs,
|
|
8
10
|
type SettingsSearchEntry,
|
|
@@ -10,15 +12,10 @@ import {
|
|
|
10
12
|
import { CreativeContextSettingsLink } from "@agent-native/creative-context/client";
|
|
11
13
|
import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
|
|
12
14
|
import { useMemo } from "react";
|
|
15
|
+
import { toast } from "sonner";
|
|
13
16
|
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
CardContent,
|
|
17
|
-
CardDescription,
|
|
18
|
-
CardHeader,
|
|
19
|
-
CardTitle,
|
|
20
|
-
} from "@/components/ui/card";
|
|
21
|
-
import { Label } from "@/components/ui/label";
|
|
17
|
+
import { Switch } from "@/components/ui/switch";
|
|
18
|
+
import { useSlidesPrefs } from "@/hooks/use-slides-prefs";
|
|
22
19
|
import messages from "@/i18n/en-US";
|
|
23
20
|
|
|
24
21
|
import changelog from "../../CHANGELOG.md?raw";
|
|
@@ -31,6 +28,7 @@ export default function SettingsRoute() {
|
|
|
31
28
|
const t = useT();
|
|
32
29
|
const agentSettingsTabs = useAgentSettingsTabs();
|
|
33
30
|
useSetPageTitle(t("settings.title"));
|
|
31
|
+
const { prefs, loading: prefsLoading, save: savePrefs } = useSlidesPrefs();
|
|
34
32
|
|
|
35
33
|
const generalSearchEntries = useMemo<SettingsSearchEntry[]>(
|
|
36
34
|
() => [
|
|
@@ -40,6 +38,12 @@ export default function SettingsRoute() {
|
|
|
40
38
|
keywords: "language locale translation i18n",
|
|
41
39
|
hash: "language",
|
|
42
40
|
},
|
|
41
|
+
{
|
|
42
|
+
id: "slides-notifications",
|
|
43
|
+
label: t("settings.emailNotifications"),
|
|
44
|
+
keywords: "email notifications comments replies alerts",
|
|
45
|
+
hash: "notifications",
|
|
46
|
+
},
|
|
43
47
|
],
|
|
44
48
|
[t],
|
|
45
49
|
);
|
|
@@ -58,20 +62,39 @@ export default function SettingsRoute() {
|
|
|
58
62
|
|
|
59
63
|
<CreativeContextSettingsLink />
|
|
60
64
|
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
<SettingsGroup>
|
|
66
|
+
<SettingsRow
|
|
67
|
+
id="language"
|
|
68
|
+
label={t("settings.languageTitle")}
|
|
69
|
+
description={t("settings.languageDescription")}
|
|
70
|
+
control={
|
|
71
|
+
<div className="w-56">
|
|
72
|
+
<LanguagePicker label={t("settings.languageLabel")} />
|
|
73
|
+
</div>
|
|
74
|
+
}
|
|
75
|
+
/>
|
|
76
|
+
<SettingsRow
|
|
77
|
+
id="notifications"
|
|
78
|
+
label={t("settings.emailNotifications")}
|
|
79
|
+
description={t("settings.emailNotificationsDescription")}
|
|
80
|
+
control={
|
|
81
|
+
<Switch
|
|
82
|
+
aria-label={t("settings.emailNotifications")}
|
|
83
|
+
checked={prefs.emailNotifications !== false}
|
|
84
|
+
disabled={prefsLoading}
|
|
85
|
+
onCheckedChange={(checked) => {
|
|
86
|
+
savePrefs({ emailNotifications: checked }).catch((err) => {
|
|
87
|
+
toast.error(
|
|
88
|
+
err instanceof Error
|
|
89
|
+
? err.message
|
|
90
|
+
: t("settings.saveFailed"),
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
}
|
|
96
|
+
/>
|
|
97
|
+
</SettingsGroup>
|
|
75
98
|
</div>
|
|
76
99
|
}
|
|
77
100
|
team={
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email notifications for deck comments and replies.
|
|
3
|
+
*
|
|
4
|
+
* Recipient resolution, preference filtering, and delivery reporting come from
|
|
5
|
+
* `@agent-native/core/server`; this module owns only the Slides rows and the
|
|
6
|
+
* email copy. Share invites are not routed through the `emailNotifications`
|
|
7
|
+
* preference — they have their own delivery path.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
emailStrong,
|
|
12
|
+
notifyActivity,
|
|
13
|
+
renderEmail,
|
|
14
|
+
runActivityNotification,
|
|
15
|
+
sendEmail,
|
|
16
|
+
type ActivityNotificationResult,
|
|
17
|
+
} from "@agent-native/core/server";
|
|
18
|
+
import { filterRecipientsByResourceAccess } from "@agent-native/core/sharing";
|
|
19
|
+
import { and, eq } from "drizzle-orm";
|
|
20
|
+
|
|
21
|
+
import { getDeckUrl } from "../../actions/_app-url.js";
|
|
22
|
+
import { SLIDES_USER_PREFS_KEY } from "../../shared/slides-user-prefs.js";
|
|
23
|
+
import { getDb, schema } from "../db/index.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `deck-missing` stays distinct from `no-recipients`: one means the deck could
|
|
27
|
+
* not be read, the other means nobody wanted the email.
|
|
28
|
+
*/
|
|
29
|
+
export type SlidesCommentNotificationResult =
|
|
30
|
+
| ActivityNotificationResult
|
|
31
|
+
| { status: "deck-missing"; sent: []; failed: [] };
|
|
32
|
+
|
|
33
|
+
const LOG_LABEL = "[slides] comment notification";
|
|
34
|
+
const EXCERPT_LIMIT = 240;
|
|
35
|
+
|
|
36
|
+
function excerpt(content: string): string {
|
|
37
|
+
const collapsed = content.replace(/\s+/g, " ").trim();
|
|
38
|
+
return collapsed.length > EXCERPT_LIMIT
|
|
39
|
+
? `${collapsed.slice(0, EXCERPT_LIMIT - 1)}…`
|
|
40
|
+
: collapsed;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The editor reads `?slide=` as a one-based ordinal, not a slide id — passing
|
|
45
|
+
* `slide_2` parses to NaN and silently lands on slide 1.
|
|
46
|
+
*/
|
|
47
|
+
function deckUrl(deckId: string, slideNumber: number | null): string {
|
|
48
|
+
const base = getDeckUrl(deckId);
|
|
49
|
+
return slideNumber ? `${base}?slide=${slideNumber}` : base;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function slideNumberIn(deckData: string, slideId: string): number | null {
|
|
53
|
+
let parsed: unknown;
|
|
54
|
+
try {
|
|
55
|
+
parsed = JSON.parse(deckData);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
// Unparsable deck JSON is a real anomaly, so say so — but the comment email
|
|
58
|
+
// still goes out with a deck-level link rather than being dropped.
|
|
59
|
+
console.error(
|
|
60
|
+
`${LOG_LABEL}: deck data could not be parsed for a slide link:`,
|
|
61
|
+
error instanceof Error ? error.message : String(error),
|
|
62
|
+
);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const slides = (parsed as { slides?: { id?: string }[] } | null)?.slides;
|
|
66
|
+
if (!Array.isArray(slides)) return null;
|
|
67
|
+
const index = slides.findIndex((slide) => slide?.id === slideId);
|
|
68
|
+
return index >= 0 ? index + 1 : null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function getDeck(deckId: string) {
|
|
72
|
+
const [row] = await getDb()
|
|
73
|
+
.select({
|
|
74
|
+
id: schema.decks.id,
|
|
75
|
+
title: schema.decks.title,
|
|
76
|
+
ownerEmail: schema.decks.ownerEmail,
|
|
77
|
+
orgId: schema.decks.orgId,
|
|
78
|
+
data: schema.decks.data,
|
|
79
|
+
})
|
|
80
|
+
.from(schema.decks)
|
|
81
|
+
.where(eq(schema.decks.id, deckId))
|
|
82
|
+
.limit(1);
|
|
83
|
+
return row ?? null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function threadParticipants(
|
|
87
|
+
deckId: string,
|
|
88
|
+
threadId: string,
|
|
89
|
+
): Promise<string[]> {
|
|
90
|
+
const rows = await getDb()
|
|
91
|
+
.select({ authorEmail: schema.slideComments.authorEmail })
|
|
92
|
+
.from(schema.slideComments)
|
|
93
|
+
.where(
|
|
94
|
+
and(
|
|
95
|
+
eq(schema.slideComments.deckId, deckId),
|
|
96
|
+
eq(schema.slideComments.threadId, threadId),
|
|
97
|
+
),
|
|
98
|
+
);
|
|
99
|
+
return rows.map((row) => row.authorEmail);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export async function notifyDeckComment(input: {
|
|
103
|
+
deckId: string;
|
|
104
|
+
slideId: string;
|
|
105
|
+
threadId: string;
|
|
106
|
+
authorEmail: string;
|
|
107
|
+
authorName?: string | null;
|
|
108
|
+
content: string;
|
|
109
|
+
isReply: boolean;
|
|
110
|
+
}): Promise<SlidesCommentNotificationResult> {
|
|
111
|
+
return runActivityNotification(LOG_LABEL, () =>
|
|
112
|
+
deliverDeckCommentEmails(input),
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function deliverDeckCommentEmails(input: {
|
|
117
|
+
deckId: string;
|
|
118
|
+
slideId: string;
|
|
119
|
+
threadId: string;
|
|
120
|
+
authorEmail: string;
|
|
121
|
+
authorName?: string | null;
|
|
122
|
+
content: string;
|
|
123
|
+
isReply: boolean;
|
|
124
|
+
}): Promise<SlidesCommentNotificationResult> {
|
|
125
|
+
const deck = await getDeck(input.deckId);
|
|
126
|
+
if (!deck) {
|
|
127
|
+
console.error(`${LOG_LABEL}: deck ${input.deckId} not found`);
|
|
128
|
+
return { status: "deck-missing", sent: [], failed: [] };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const candidates = [deck.ownerEmail];
|
|
132
|
+
if (input.isReply) {
|
|
133
|
+
candidates.push(
|
|
134
|
+
...(await threadParticipants(input.deckId, input.threadId)),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Thread rows are history, not an access grant: someone removed from the
|
|
139
|
+
// deck must stop receiving its comment bodies.
|
|
140
|
+
const allowed = await filterRecipientsByResourceAccess({
|
|
141
|
+
resourceType: "deck",
|
|
142
|
+
resourceId: deck.id,
|
|
143
|
+
emails: candidates,
|
|
144
|
+
orgId: deck.orgId,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const actor = input.authorName?.trim() || input.authorEmail;
|
|
148
|
+
const url = deckUrl(deck.id, slideNumberIn(deck.data, input.slideId));
|
|
149
|
+
|
|
150
|
+
return notifyActivity({
|
|
151
|
+
candidates: allowed,
|
|
152
|
+
actorEmail: input.authorEmail,
|
|
153
|
+
preferenceKey: SLIDES_USER_PREFS_KEY,
|
|
154
|
+
logLabel: LOG_LABEL,
|
|
155
|
+
send: async (to) => {
|
|
156
|
+
const { html, text } = renderEmail({
|
|
157
|
+
preheader: input.isReply
|
|
158
|
+
? `${actor} replied to a comment on ${deck.title}.`
|
|
159
|
+
: `${actor} commented on ${deck.title}.`,
|
|
160
|
+
heading: input.isReply ? "New reply on your deck" : "New comment",
|
|
161
|
+
paragraphs: [
|
|
162
|
+
input.isReply
|
|
163
|
+
? `${emailStrong(actor)} replied in a comment thread on ${emailStrong(deck.title)}.`
|
|
164
|
+
: `${emailStrong(actor)} commented on ${emailStrong(deck.title)}.`,
|
|
165
|
+
`"${excerpt(input.content)}"`,
|
|
166
|
+
],
|
|
167
|
+
cta: { label: "Open deck", url },
|
|
168
|
+
footer:
|
|
169
|
+
"You received this because you own or participated in this thread. Turn these off in Slides settings.",
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
await sendEmail({
|
|
173
|
+
to,
|
|
174
|
+
subject: input.isReply
|
|
175
|
+
? `${actor} replied to a comment on "${deck.title}"`
|
|
176
|
+
: `${actor} commented on "${deck.title}"`,
|
|
177
|
+
html,
|
|
178
|
+
text,
|
|
179
|
+
});
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getSession } from "@agent-native/core/server";
|
|
2
|
+
import { getUserSetting } from "@agent-native/core/settings";
|
|
3
|
+
import { defineEventHandler, setResponseStatus } from "h3";
|
|
4
|
+
|
|
5
|
+
import { SLIDES_USER_PREFS_KEY } from "../../../../shared/slides-user-prefs.js";
|
|
6
|
+
|
|
7
|
+
export default defineEventHandler(async (event) => {
|
|
8
|
+
const session = await getSession(event);
|
|
9
|
+
if (!session?.email) {
|
|
10
|
+
setResponseStatus(event, 401);
|
|
11
|
+
return { error: "unauthorized" };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// coercion-ok: no stored blob means no preferences set yet, which is a real state, not a read failure.
|
|
15
|
+
return (await getUserSetting(session.email, SLIDES_USER_PREFS_KEY)) ?? {};
|
|
16
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getSession } from "@agent-native/core/server";
|
|
2
|
+
import { getUserSetting, putUserSetting } from "@agent-native/core/settings";
|
|
3
|
+
import { defineEventHandler, getHeader, readBody, setResponseStatus } from "h3";
|
|
4
|
+
|
|
5
|
+
import { SLIDES_USER_PREFS_KEY } from "../../../../shared/slides-user-prefs.js";
|
|
6
|
+
|
|
7
|
+
export default defineEventHandler(async (event) => {
|
|
8
|
+
const session = await getSession(event);
|
|
9
|
+
if (!session?.email) {
|
|
10
|
+
setResponseStatus(event, 401);
|
|
11
|
+
return { error: "unauthorized" };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// coercion-ok: an unparsable body is rejected with 400 immediately below.
|
|
15
|
+
const body = await readBody(event).catch(() => null);
|
|
16
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
17
|
+
setResponseStatus(event, 400);
|
|
18
|
+
return { error: "Invalid settings payload" };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Merge so a partial save never wipes preferences written elsewhere.
|
|
22
|
+
const stored = await getUserSetting(session.email, SLIDES_USER_PREFS_KEY);
|
|
23
|
+
// coercion-ok: a null read means this user has no preferences yet, which is a real state.
|
|
24
|
+
const existing = stored ?? {};
|
|
25
|
+
const next = {
|
|
26
|
+
...(typeof existing === "object" && existing && !Array.isArray(existing)
|
|
27
|
+
? existing
|
|
28
|
+
: {}),
|
|
29
|
+
...(body as Record<string, unknown>),
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
await putUserSetting(session.email, SLIDES_USER_PREFS_KEY, next, {
|
|
33
|
+
requestSource: getHeader(event, "x-request-source") || undefined,
|
|
34
|
+
});
|
|
35
|
+
return next;
|
|
36
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-user Slides preferences, stored under one user-setting key so Settings
|
|
3
|
+
* and the notification senders read and write the same object.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const SLIDES_USER_PREFS_KEY = "slides-user-prefs";
|
|
7
|
+
|
|
8
|
+
export type SlidesUserPrefs = {
|
|
9
|
+
/** Comment and reply emails only — never share invites. */
|
|
10
|
+
emailNotifications?: boolean;
|
|
11
|
+
};
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
|
|
3
|
+
import baseConfig from "@agent-native/core/vitest-config";
|
|
3
4
|
import react from "@vitejs/plugin-react-swc";
|
|
4
|
-
import { defineConfig } from "vitest/config";
|
|
5
|
+
import { defineConfig, mergeConfig } from "vitest/config";
|
|
5
6
|
|
|
6
|
-
export default
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
export default mergeConfig(
|
|
8
|
+
baseConfig,
|
|
9
|
+
defineConfig({
|
|
10
|
+
plugins: [react()],
|
|
11
|
+
resolve: {
|
|
12
|
+
alias: {
|
|
13
|
+
"@": path.resolve(__dirname, "./app"),
|
|
14
|
+
"@shared": path.resolve(__dirname, "./shared"),
|
|
15
|
+
},
|
|
12
16
|
},
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
},
|
|
18
|
-
|
|
17
|
+
test: {
|
|
18
|
+
include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
|
|
19
|
+
exclude: ["**/node_modules/**", "**/.git/**", "**/dist/**"],
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
@@ -263,6 +263,8 @@ export function Sidebar({
|
|
|
263
263
|
>
|
|
264
264
|
<OrgSwitcher
|
|
265
265
|
reserveSpace
|
|
266
|
+
// Tasks does not mount /agent, so the default link would 404.
|
|
267
|
+
agentPath={null}
|
|
266
268
|
className={
|
|
267
269
|
collapsed
|
|
268
270
|
? "h-8 justify-center px-0 [&>span]:sr-only [&>svg:last-child]:hidden"
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
|
|
2
2
|
import {
|
|
3
|
+
SettingsGroup,
|
|
4
|
+
SettingsRow,
|
|
3
5
|
SettingsTabsPage,
|
|
4
6
|
useAgentSettingsTabs,
|
|
5
7
|
} from "@agent-native/core/client/settings";
|
|
6
8
|
import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
|
|
7
9
|
|
|
8
|
-
import {
|
|
9
|
-
Card,
|
|
10
|
-
CardContent,
|
|
11
|
-
CardDescription,
|
|
12
|
-
CardHeader,
|
|
13
|
-
CardTitle,
|
|
14
|
-
} from "@/components/ui/card";
|
|
15
|
-
import { Label } from "@/components/ui/label";
|
|
16
10
|
import { APP_TITLE } from "@/lib/app-config";
|
|
17
11
|
|
|
18
12
|
export function meta() {
|
|
@@ -33,20 +27,18 @@ export default function SettingsRoute() {
|
|
|
33
27
|
{t("header.pageSettings")}
|
|
34
28
|
</p>
|
|
35
29
|
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
</CardContent>
|
|
49
|
-
</Card>
|
|
30
|
+
<SettingsGroup>
|
|
31
|
+
<SettingsRow
|
|
32
|
+
id="language"
|
|
33
|
+
label={t("settings.languageTitle")}
|
|
34
|
+
description={t("settings.languageDescription")}
|
|
35
|
+
control={
|
|
36
|
+
<div className="w-56">
|
|
37
|
+
<LanguagePicker label={t("settings.languageLabel")} />
|
|
38
|
+
</div>
|
|
39
|
+
}
|
|
40
|
+
/>
|
|
41
|
+
</SettingsGroup>
|
|
50
42
|
</div>
|
|
51
43
|
}
|
|
52
44
|
/>
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import baseConfig from "@agent-native/core/vitest-config";
|
|
4
|
+
import { defineConfig, mergeConfig } from "vitest/config";
|
|
4
5
|
|
|
5
|
-
export default
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export default mergeConfig(
|
|
7
|
+
baseConfig,
|
|
8
|
+
defineConfig({
|
|
9
|
+
resolve: {
|
|
10
|
+
alias: {
|
|
11
|
+
"@": path.resolve(__dirname, "./app"),
|
|
12
|
+
"@shared": path.resolve(__dirname, "./shared"),
|
|
13
|
+
},
|
|
10
14
|
},
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
|
|
15
|
+
test: {
|
|
16
|
+
include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
|
|
17
|
+
exclude: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/e2e/**"],
|
|
18
|
+
environment: "node",
|
|
19
|
+
},
|
|
20
|
+
}),
|
|
21
|
+
);
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @agent-native/toolkit
|
|
2
2
|
|
|
3
|
+
## 0.12.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f499dff: Add `@agent-native/core/vitest-config`, a base vitest config that caps a suite's
|
|
8
|
+
worker pool so concurrent test runs no longer oversubscribe the CPU. Defaults to
|
|
9
|
+
25% of cores; override with `VITEST_CONCURRENCY`. Every template and package
|
|
10
|
+
config merges it in.
|
|
11
|
+
|
|
3
12
|
## 0.12.1
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
|
@@ -29,6 +29,7 @@ export interface DefineAutomationInput {
|
|
|
29
29
|
triggerType: "schedule" | "event";
|
|
30
30
|
body: string;
|
|
31
31
|
schedule?: string;
|
|
32
|
+
timezone?: string;
|
|
32
33
|
event?: string;
|
|
33
34
|
condition?: string;
|
|
34
35
|
domain?: string;
|
|
@@ -46,6 +47,7 @@ export interface UpdateAutomationInput {
|
|
|
46
47
|
condition?: string | null;
|
|
47
48
|
delegatedPolicyId?: string | null;
|
|
48
49
|
schedule?: string;
|
|
50
|
+
timezone?: string;
|
|
49
51
|
model?: string | null;
|
|
50
52
|
mcpTools?: unknown;
|
|
51
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/automations/service.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/automations/service.ts"],"names":[],"mappings":"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"}
|