@agent-native/core 0.92.0 → 0.92.2
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 +1 -1
- package/corpus/core/CHANGELOG.md +20 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/application-state/store.ts +12 -1
- package/corpus/core/src/cli/sync-builder-starter-manifest.ts +29 -1
- package/corpus/core/src/client/AssistantChat.tsx +27 -14
- package/corpus/core/src/client/PoweredByBadge.tsx +1 -8
- package/corpus/core/src/client/agent-chat-adapter.ts +37 -10
- package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +52 -1
- package/corpus/core/src/client/db-admin/TableEditor.tsx +49 -0
- package/corpus/core/src/client/db-admin/export-utils.ts +13 -4
- package/corpus/core/src/client/db-admin/useAgentSync.ts +72 -0
- package/corpus/core/src/client/error-capture.ts +69 -7
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +5 -1
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +53 -8
- package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +5 -1
- package/corpus/core/src/client/extensions/portable-extension.ts +1 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +12 -9
- package/corpus/core/src/client/org/TeamPage.tsx +77 -71
- package/corpus/core/src/client/settings/SettingsPanel.tsx +205 -52
- package/corpus/core/src/client/settings/SettingsSection.tsx +8 -1
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +25 -9
- package/corpus/core/src/db-admin/agent-tools.ts +8 -2
- package/corpus/core/src/db-admin/operations.ts +116 -4
- package/corpus/core/src/db-admin/routes.ts +1 -0
- package/corpus/core/src/db-admin/types.ts +4 -0
- package/corpus/core/src/extensions/html-shell.ts +5 -4
- package/corpus/core/src/extensions/routes.ts +10 -0
- package/corpus/core/src/navigation/index.ts +1 -1
- package/corpus/core/src/notifications/channels.ts +1 -22
- package/corpus/core/src/resources/handlers.ts +10 -8
- package/corpus/core/src/server/poll.ts +293 -8
- package/corpus/core/src/styles/agent-native.css +27 -0
- package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +7 -0
- package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/core/src/templates/default/AGENTS.md +4 -2
- package/corpus/core/src/templates/headless/AGENTS.md +4 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/core/src/templates/workspace-core/AGENTS.md +7 -1
- package/corpus/core/src/templates/workspace-root/AGENTS.md +7 -1
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
- package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/analytics/AGENTS.md +33 -14
- package/corpus/templates/analytics/actions/capture-test-error.ts +4 -0
- package/corpus/templates/analytics/actions/get-analytics-alert-rule-defaults.ts +23 -0
- package/corpus/templates/analytics/actions/get-error-issue.ts +1 -1
- package/corpus/templates/analytics/actions/list-analysis-revisions.ts +40 -0
- package/corpus/templates/analytics/actions/list-dashboard-revisions.ts +40 -0
- package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +299 -0
- package/corpus/templates/analytics/actions/navigate.ts +4 -2
- package/corpus/templates/analytics/actions/restore-analysis-revision.ts +43 -0
- package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +68 -0
- package/corpus/templates/analytics/actions/save-analytics-alert-rule.ts +14 -0
- package/corpus/templates/analytics/actions/save-monitor.ts +1 -1
- package/corpus/templates/analytics/actions/view-screen.ts +24 -0
- package/corpus/templates/analytics/app/components/analysis/AnalysisHistoryPanel.tsx +181 -0
- package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +184 -0
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +22 -16
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +27 -21
- package/corpus/templates/analytics/app/hooks/use-analysis-revisions.ts +43 -0
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +110 -0
- package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +43 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +8 -3
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +64 -2
- package/corpus/templates/analytics/app/i18n-data.ts +783 -3
- package/corpus/templates/analytics/app/pages/Agents.tsx +359 -19
- package/corpus/templates/analytics/app/pages/Settings.tsx +3 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +34 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +28 -0
- package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +18 -1
- package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +7 -10
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +479 -23
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +0 -9
- package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +11 -0
- package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +9 -1
- package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +6 -3
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +26 -30
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -99
- package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +262 -104
- package/corpus/templates/analytics/app/routes/team.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-07-08-admins-can-audit-dashboard-usage-ownership-and-cleanup-signa.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-agent-monitoring-stays-available-to-non-admins.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-alert-emails-now-show-the-message-without-raw-metadata-json.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-alert-rules-are-easier-to-scan-expand-and-edit-from-settings.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-forms-remember-last-email-recipients.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-rules-can-now-use-per-rule-slack-and-webhook.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +5 -0
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-usage-now-counts-explorer-dashboard-traffic.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-demo-mode-session-emails-are-filtered-and-anonymized.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-adds-stack-traces-and-frequency-bars.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-now-shows-the-latest-occurrence-message-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-monitoring-errors-only-show-test-action-when-empty.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-production-session-replay-now-requires-private-blob-storage-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-shared-extension-links-now-show-a-clear-message-when-you-do-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-team-settings-show-access-controls-next-to-member-lists.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-uptime-checks-no-longer-count-ssrf-setup-time-against-the-re.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-uptime-checks-reuse-one-keep-alive-connection-so-recorded-la.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-uptime-monitors-now-confirm-transient-timeout-failures-befor.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-uptime-monitors-now-use-a-10-second-request-timeout-by-defau.md +6 -0
- package/corpus/templates/analytics/docs/uptime-monitoring.md +30 -18
- package/corpus/templates/analytics/server/db/schema-monitoring.ts +1 -1
- package/corpus/templates/analytics/server/db/schema.ts +56 -0
- package/corpus/templates/analytics/server/lib/analytics-alerts.ts +92 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +334 -5
- package/corpus/templates/analytics/server/lib/error-capture.ts +231 -36
- package/corpus/templates/analytics/server/lib/session-replay.ts +114 -8
- package/corpus/templates/analytics/server/lib/uptime-monitors.ts +244 -33
- package/corpus/templates/analytics/server/plugins/db.ts +112 -2
- package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +1 -0
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/assets/AGENTS.md +4 -0
- package/corpus/templates/assets/app/routes/settings.tsx +1 -1
- package/corpus/templates/assets/app/routes/team.tsx +1 -1
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/brain/AGENTS.md +4 -0
- package/corpus/templates/brain/app/routes/team.tsx +1 -1
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/calendar/AGENTS.md +4 -0
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +11 -2
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +21 -8
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +7 -1
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -2
- package/corpus/templates/calendar/app/lib/popover-click-guard.ts +48 -4
- package/corpus/templates/calendar/app/pages/Settings.tsx +1 -1
- package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/calendar/changelog/2026-07-08-clicking-empty-calendar-space-closes-an-open-event-popover-b.md +6 -0
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/chat/AGENTS.md +4 -0
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/chat/app/routes/settings.tsx +2 -2
- package/corpus/templates/chat/app/routes/team.tsx +1 -1
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +9 -3
- package/corpus/templates/clips/actions/set-thumbnail.ts +11 -2
- package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +1 -7
- package/corpus/templates/clips/app/components/player/player-controls.tsx +21 -13
- package/corpus/templates/clips/app/components/player/video-player.tsx +30 -75
- package/corpus/templates/clips/app/i18n/ar-SA.ts +6 -5
- package/corpus/templates/clips/app/i18n/de-DE.ts +6 -6
- package/corpus/templates/clips/app/i18n/en-US.ts +6 -5
- package/corpus/templates/clips/app/i18n/es-ES.ts +6 -5
- package/corpus/templates/clips/app/i18n/fr-FR.ts +6 -6
- package/corpus/templates/clips/app/i18n/hi-IN.ts +6 -5
- package/corpus/templates/clips/app/i18n/ja-JP.ts +6 -5
- package/corpus/templates/clips/app/i18n/ko-KR.ts +6 -5
- package/corpus/templates/clips/app/i18n/pt-BR.ts +6 -5
- package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -5
- package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -5
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +51 -118
- package/corpus/templates/clips/changelog/2026-07-08-hosted-clip-uploads-now-clear-failed-buffered-chunks.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-hosted-recording-uploads-now-avoid-sql-chunk-storage.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-meeting-recaps-now-keep-summaries-action-items-and-transcrip.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-video-playback-controls-now-match-loom-style-5-second-skips-.md +6 -0
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +63 -0
- package/corpus/templates/clips/server/lib/video-storage.ts +4 -0
- package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +19 -13
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +40 -1
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/content/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/content/AGENTS.md +4 -0
- package/corpus/templates/content/app/routes/_app.settings.tsx +2 -2
- package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/design/AGENTS.md +4 -0
- package/corpus/templates/design/actions/take-design-screenshot.ts +12 -9
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -13
- package/corpus/templates/design/app/routes/team.tsx +1 -1
- package/corpus/templates/design/changelog/2026-07-08-local-images-added-to-designs-now-upload-to-file-storage-ins.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/dispatch/AGENTS.md +4 -0
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/dispatch/app/routes/settings.tsx +2 -2
- package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/forms/AGENTS.md +4 -0
- package/corpus/templates/forms/app/routes/_app.settings.tsx +2 -2
- package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/forms/shared/navigation.ts +1 -1
- package/corpus/templates/macros/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/macros/AGENTS.md +4 -0
- package/corpus/templates/macros/app/routes/settings.tsx +2 -2
- package/corpus/templates/macros/app/routes/team.tsx +1 -1
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/mail/.agents/skills/email-drafts/SKILL.md +1 -1
- package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/mail/AGENTS.md +4 -0
- package/corpus/templates/mail/changelog/2026-07-08-mail-attachments-in-hosted-environments-now-require-file-sto.md +6 -0
- package/corpus/templates/mail/server/handlers/media.ts +26 -1
- package/corpus/templates/mail/server/lib/outgoing-email.ts +24 -1
- package/corpus/templates/mail/server/lib/upload-store.ts +2 -1
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/plan/AGENTS.md +4 -0
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/plan/app/routes/settings.tsx +2 -2
- package/corpus/templates/plan/app/routes/team.tsx +1 -1
- package/corpus/templates/plan/changelog/2026-07-08-hosted-plan-images-now-require-connected-storage.md +6 -0
- package/corpus/templates/plan/server/lib/plan-assets.ts +33 -4
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/slides/AGENTS.md +4 -0
- package/corpus/templates/slides/actions/generate-image-api.ts +15 -3
- package/corpus/templates/slides/app/routes/settings.tsx +2 -2
- package/corpus/templates/slides/app/routes/team.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-07-08-generated-slide-images-now-return-hosted-file-storage-urls-i.md +6 -0
- package/corpus/templates/slides/shared/api.ts +1 -1
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +8 -2
- package/dist/application-state/store.js.map +1 -1
- package/dist/cli/sync-builder-starter-manifest.d.ts.map +1 -1
- package/dist/cli/sync-builder-starter-manifest.js +24 -1
- package/dist/cli/sync-builder-starter-manifest.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +24 -13
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/PoweredByBadge.d.ts +1 -1
- package/dist/client/PoweredByBadge.d.ts.map +1 -1
- package/dist/client/PoweredByBadge.js +3 -9
- package/dist/client/PoweredByBadge.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +28 -9
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
- package/dist/client/chat/widgets/DataTableWidget.js +19 -2
- package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
- package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
- package/dist/client/db-admin/TableEditor.js +19 -2
- package/dist/client/db-admin/TableEditor.js.map +1 -1
- package/dist/client/db-admin/export-utils.d.ts +2 -0
- package/dist/client/db-admin/export-utils.d.ts.map +1 -1
- package/dist/client/db-admin/export-utils.js +11 -3
- package/dist/client/db-admin/export-utils.js.map +1 -1
- package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
- package/dist/client/db-admin/useAgentSync.js +63 -0
- package/dist/client/db-admin/useAgentSync.js.map +1 -1
- package/dist/client/error-capture.d.ts.map +1 -1
- package/dist/client/error-capture.js +41 -7
- package/dist/client/error-capture.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +3 -1
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +32 -5
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.js +3 -1
- package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
- package/dist/client/extensions/portable-extension.d.ts.map +1 -1
- package/dist/client/extensions/portable-extension.js +1 -0
- package/dist/client/extensions/portable-extension.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +11 -6
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +5 -5
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +37 -14
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsSection.js +1 -1
- package/dist/client/settings/SettingsSection.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
- package/dist/client/settings/SettingsTabsPage.js +21 -10
- package/dist/client/settings/SettingsTabsPage.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db-admin/agent-tools.d.ts.map +1 -1
- package/dist/db-admin/agent-tools.js +7 -2
- package/dist/db-admin/agent-tools.js.map +1 -1
- package/dist/db-admin/operations.d.ts.map +1 -1
- package/dist/db-admin/operations.js +90 -4
- package/dist/db-admin/operations.js.map +1 -1
- package/dist/db-admin/routes.d.ts.map +1 -1
- package/dist/db-admin/routes.js +1 -0
- package/dist/db-admin/routes.js.map +1 -1
- package/dist/db-admin/types.d.ts +4 -0
- package/dist/db-admin/types.d.ts.map +1 -1
- package/dist/db-admin/types.js.map +1 -1
- package/dist/extensions/html-shell.d.ts +5 -4
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +8 -0
- package/dist/extensions/routes.js.map +1 -1
- package/dist/navigation/index.d.ts +1 -1
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +1 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/notifications/channels.js +1 -17
- package/dist/notifications/channels.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +5 -0
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +9 -8
- package/dist/resources/handlers.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/poll.d.ts +12 -4
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +236 -9
- package/dist/server/poll.js.map +1 -1
- package/dist/styles/agent-native.css +27 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/default/.agents/skills/security/SKILL.md +7 -0
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
- package/dist/templates/default/AGENTS.md +4 -2
- package/dist/templates/headless/AGENTS.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
- package/dist/templates/workspace-core/AGENTS.md +7 -1
- package/dist/templates/workspace-root/AGENTS.md +7 -1
- package/package.json +1 -1
- package/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/security/SKILL.md +7 -0
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
- package/src/templates/default/AGENTS.md +4 -2
- package/src/templates/headless/AGENTS.md +4 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
- package/src/templates/workspace-core/AGENTS.md +7 -1
- package/src/templates/workspace-root/AGENTS.md +7 -1
|
@@ -19,12 +19,19 @@ are shareable and the agent can deep-link a monitor.
|
|
|
19
19
|
|
|
20
20
|
Each check runs on the server (`server/lib/uptime-monitors.ts`):
|
|
21
21
|
|
|
22
|
-
1.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
1. Run SSRF setup (dispatcher + DNS private-address check) **outside** the
|
|
23
|
+
request timeout budget. The connect-time dispatcher is built once and reused
|
|
24
|
+
across checks (HTTP keep-alive), so latency reflects the real request round
|
|
25
|
+
trip instead of a fresh DNS + TCP + TLS handshake on every probe.
|
|
26
|
+
2. Fetch the monitor's `url` with the configured `method`, headers, and body,
|
|
27
|
+
through that SSRF-safe path, with an `AbortController` timeout that covers
|
|
28
|
+
only the HTTP request (headers / redirect chain).
|
|
29
|
+
3. Measure latency from the HTTP response headers. If a body assertion is
|
|
30
|
+
configured, read up to **512 KB** of the response body (skipped for `HEAD`)
|
|
31
|
+
with a bounded body-read timer after clearing the request abort timer, so a
|
|
32
|
+
slow body cannot be mislabeled as a request timeout or hang indefinitely.
|
|
33
|
+
4. Evaluate the **status matcher** and every **assertion**.
|
|
34
|
+
5. Classify the result:
|
|
28
35
|
- `up` — status matches and all assertions pass.
|
|
29
36
|
- `degraded` — status matches but only a `max_latency_ms` assertion fails
|
|
30
37
|
(the endpoint responded, just too slowly). Alerts at `warning` severity.
|
|
@@ -58,14 +65,18 @@ Each check runs on the server (`server/lib/uptime-monitors.ts`):
|
|
|
58
65
|
|
|
59
66
|
`evaluateAndNotifyMonitor` manages incidents like the analytics alert engine:
|
|
60
67
|
|
|
61
|
-
- On a transition **into failure**, it opens a `monitor_incidents` row
|
|
62
|
-
continuous failure streak) and calls `notifyWithDelivery` with a
|
|
63
|
-
and body plus safe inbox metadata
|
|
68
|
+
- On a transition **into confirmed failure**, it opens a `monitor_incidents` row
|
|
69
|
+
(one per continuous failure streak) and calls `notifyWithDelivery` with a
|
|
70
|
+
clear title and body plus safe inbox metadata
|
|
64
71
|
`{ kind: "uptime_monitor", monitorId, url, statusCode, latencyMs, failedAssertions, emailRecipients }`.
|
|
65
72
|
The `inbox` channel is the in-app bell; `email` uses the monitor's
|
|
66
73
|
`emailRecipients`; `slack` / `webhook` use the monitor's optional
|
|
67
74
|
delivery-only `slackWebhookUrl` / `webhookUrl` (falling back to workspace
|
|
68
75
|
`NOTIFICATIONS_SLACK_WEBHOOK_URL` / `NOTIFICATIONS_WEBHOOK_URL` when unset).
|
|
76
|
+
- Transient no-response failures, such as network errors or timeouts, must fail
|
|
77
|
+
twice in a row before opening an incident or alerting. Set
|
|
78
|
+
`UPTIME_MONITOR_TRANSIENT_FAILURE_CONFIRMATION_CHECKS=1` to alert on the first
|
|
79
|
+
transient failure, or a higher value (max 10) for stricter confirmation.
|
|
69
80
|
- While an incident is open it will not re-alert. After an incident resolves,
|
|
70
81
|
`cooldownMinutes` suppresses a fresh "down" alert for that window to prevent
|
|
71
82
|
flapping.
|
|
@@ -101,15 +112,16 @@ incidents, and prunes old check results.
|
|
|
101
112
|
|
|
102
113
|
Environment flags (mirrors the analytics alert job):
|
|
103
114
|
|
|
104
|
-
| flag
|
|
105
|
-
|
|
|
106
|
-
| `UPTIME_MONITOR_JOBS`
|
|
107
|
-
| `RUN_BACKGROUND_JOBS`
|
|
108
|
-
| (production)
|
|
109
|
-
| `UPTIME_MONITOR_INTERVAL_MS`
|
|
110
|
-
| `UPTIME_MONITOR_SWEEP_LIMIT`
|
|
111
|
-
| `UPTIME_MONITOR_RESULT_RETENTION_DAYS`
|
|
112
|
-
| `UPTIME_MONITOR_ALLOW_PRIVATE_HOSTS`
|
|
115
|
+
| flag | effect |
|
|
116
|
+
| ------------------------------------------------------ | ---------------------------------------------------------------------------------- |
|
|
117
|
+
| `UPTIME_MONITOR_JOBS` | `1` enables the in-process cron; `0` disables it. |
|
|
118
|
+
| `RUN_BACKGROUND_JOBS` | fallback flag when `UPTIME_MONITOR_JOBS` is unset. |
|
|
119
|
+
| (production) | on by default unless a flag is `0` or a platform scheduler owns it. |
|
|
120
|
+
| `UPTIME_MONITOR_INTERVAL_MS` | wake interval for the sweep (default 30s, min 10s). |
|
|
121
|
+
| `UPTIME_MONITOR_SWEEP_LIMIT` | max monitors processed per sweep (default 100). |
|
|
122
|
+
| `UPTIME_MONITOR_RESULT_RETENTION_DAYS` | how long check results are kept (default 30). |
|
|
123
|
+
| `UPTIME_MONITOR_ALLOW_PRIVATE_HOSTS` | allow probing private/internal hosts. |
|
|
124
|
+
| `UPTIME_MONITOR_TRANSIENT_FAILURE_CONFIRMATION_CHECKS` | consecutive timeout/network failures required before alerting (default 2, max 10). |
|
|
113
125
|
|
|
114
126
|
The monitor tables (`monitors`, `monitor_check_results`, `monitor_incidents`)
|
|
115
127
|
are created by the app migration list in `server/plugins/db.ts`, which runs at
|
|
@@ -42,7 +42,7 @@ export const monitors = table("monitors", {
|
|
|
42
42
|
/** Optional request body (POST/PUT/PATCH). */
|
|
43
43
|
requestBody: text("request_body"),
|
|
44
44
|
intervalSeconds: integer("interval_seconds").notNull().default(300),
|
|
45
|
-
timeoutMs: integer("timeout_ms").notNull().default(
|
|
45
|
+
timeoutMs: integer("timeout_ms").notNull().default(10000),
|
|
46
46
|
/**
|
|
47
47
|
* Status matcher as JSON. One of:
|
|
48
48
|
* { "mode": "class", "classes": ["2xx","3xx"] }
|
|
@@ -38,11 +38,38 @@ export const dashboards = table("dashboards", {
|
|
|
38
38
|
/** Hidden dashboards are omitted from default navigation but remain openable. */
|
|
39
39
|
hiddenAt: text("hidden_at"),
|
|
40
40
|
hiddenBy: text("hidden_by"),
|
|
41
|
+
/** Last authenticated user who changed dashboard metadata/config, if tracked. */
|
|
42
|
+
updatedBy: text("updated_by"),
|
|
41
43
|
...ownableColumns(),
|
|
42
44
|
});
|
|
43
45
|
|
|
44
46
|
export const dashboardShares = createSharesTable("dashboard_shares");
|
|
45
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Bounded dashboard history. Each row snapshots the previous dashboard config
|
|
50
|
+
* before a meaningful save so users and agents can restore known-good states.
|
|
51
|
+
*/
|
|
52
|
+
export const dashboardRevisions = table(
|
|
53
|
+
"dashboard_revisions",
|
|
54
|
+
{
|
|
55
|
+
id: text("id").primaryKey(),
|
|
56
|
+
dashboardId: text("dashboard_id").notNull(),
|
|
57
|
+
kind: text("kind", { enum: ["explorer", "sql"] }).notNull(),
|
|
58
|
+
title: text("title").notNull(),
|
|
59
|
+
config: text("config").notNull(),
|
|
60
|
+
createdAt: text("created_at").notNull().default(now()),
|
|
61
|
+
createdBy: text("created_by"),
|
|
62
|
+
ownerEmail: text("owner_email").notNull().default("local@localhost"),
|
|
63
|
+
orgId: text("org_id"),
|
|
64
|
+
},
|
|
65
|
+
(t) => ({
|
|
66
|
+
dashboardCreatedIdx: index("dashboard_revisions_dashboard_created_idx").on(
|
|
67
|
+
t.dashboardId,
|
|
68
|
+
t.createdAt,
|
|
69
|
+
),
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
|
|
46
73
|
/**
|
|
47
74
|
* Saved filter views per dashboard. Lives alongside the parent and is
|
|
48
75
|
* governed by the parent's sharing (no separate share rows).
|
|
@@ -117,6 +144,31 @@ export const analyses = table("analyses", {
|
|
|
117
144
|
...ownableColumns(),
|
|
118
145
|
});
|
|
119
146
|
|
|
147
|
+
export const analysisRevisions = table(
|
|
148
|
+
"analysis_revisions",
|
|
149
|
+
{
|
|
150
|
+
id: text("id").primaryKey(),
|
|
151
|
+
analysisId: text("analysis_id").notNull(),
|
|
152
|
+
name: text("name").notNull(),
|
|
153
|
+
description: text("description").notNull().default(""),
|
|
154
|
+
question: text("question").notNull().default(""),
|
|
155
|
+
instructions: text("instructions").notNull().default(""),
|
|
156
|
+
dataSources: text("data_sources").notNull().default("[]"),
|
|
157
|
+
resultMarkdown: text("result_markdown").notNull().default(""),
|
|
158
|
+
resultData: text("result_data"),
|
|
159
|
+
createdAt: text("created_at").notNull().default(now()),
|
|
160
|
+
createdBy: text("created_by"),
|
|
161
|
+
ownerEmail: text("owner_email").notNull().default("local@localhost"),
|
|
162
|
+
orgId: text("org_id"),
|
|
163
|
+
},
|
|
164
|
+
(t) => ({
|
|
165
|
+
analysisCreatedIdx: index("analysis_revisions_analysis_created_idx").on(
|
|
166
|
+
t.analysisId,
|
|
167
|
+
t.createdAt,
|
|
168
|
+
),
|
|
169
|
+
}),
|
|
170
|
+
);
|
|
171
|
+
|
|
120
172
|
export const analysisShares = createSharesTable("analysis_shares");
|
|
121
173
|
|
|
122
174
|
/**
|
|
@@ -209,6 +261,10 @@ export const analyticsAlertRules = table("analytics_alert_rules", {
|
|
|
209
261
|
.default("warning"),
|
|
210
262
|
channels: text("channels").notNull().default('["inbox"]'),
|
|
211
263
|
emailRecipients: text("email_recipients").notNull().default("[]"),
|
|
264
|
+
/** Optional per-rule Slack incoming webhook URL (overrides workspace env). */
|
|
265
|
+
slackWebhookUrl: text("slack_webhook_url"),
|
|
266
|
+
/** Optional per-rule generic webhook URL (overrides workspace env). */
|
|
267
|
+
webhookUrl: text("webhook_url"),
|
|
212
268
|
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
|
|
213
269
|
lastEvaluatedAt: text("last_evaluated_at"),
|
|
214
270
|
lastTriggeredAt: text("last_triggered_at"),
|
|
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
|
|
3
3
|
import { notifyWithDelivery } from "@agent-native/core/notifications";
|
|
4
4
|
import { recordChange } from "@agent-native/core/server";
|
|
5
|
+
import { getUserSetting, putUserSetting } from "@agent-native/core/settings";
|
|
5
6
|
import {
|
|
6
7
|
and,
|
|
7
8
|
asc,
|
|
@@ -53,9 +54,15 @@ export interface AnalyticsAlertRuleInput {
|
|
|
53
54
|
severity?: AnalyticsAlertSeverity;
|
|
54
55
|
channels?: string[];
|
|
55
56
|
emailRecipients?: string[];
|
|
57
|
+
slackWebhookUrl?: string | null;
|
|
58
|
+
webhookUrl?: string | null;
|
|
56
59
|
enabled?: boolean;
|
|
57
60
|
}
|
|
58
61
|
|
|
62
|
+
export interface AnalyticsAlertRuleDefaults {
|
|
63
|
+
emailRecipients: string[];
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
export interface AnalyticsAlertRule {
|
|
60
67
|
id: string;
|
|
61
68
|
name: string;
|
|
@@ -70,6 +77,8 @@ export interface AnalyticsAlertRule {
|
|
|
70
77
|
severity: AnalyticsAlertSeverity;
|
|
71
78
|
channels: string[];
|
|
72
79
|
emailRecipients: string[];
|
|
80
|
+
slackWebhookUrl: string | null;
|
|
81
|
+
webhookUrl: string | null;
|
|
73
82
|
enabled: boolean;
|
|
74
83
|
lastEvaluatedAt: string | null;
|
|
75
84
|
lastTriggeredAt: string | null;
|
|
@@ -126,6 +135,7 @@ function nowIso(): string {
|
|
|
126
135
|
|
|
127
136
|
const ALERT_RULE_RUNNING_STALE_MS = 15 * 60 * 1000;
|
|
128
137
|
const DEFAULT_HTTP_5XX_ALERT_ID_PREFIX = "default-http-5xx-spike";
|
|
138
|
+
const ALERT_RULE_DEFAULTS_KEY = "analytics-alert-rule-defaults";
|
|
129
139
|
|
|
130
140
|
function safeJsonParse<T>(raw: unknown, fallback: T): T {
|
|
131
141
|
if (typeof raw !== "string" || !raw.trim()) return fallback;
|
|
@@ -143,6 +153,10 @@ function normalizeName(name: string): string {
|
|
|
143
153
|
return normalized.slice(0, 120);
|
|
144
154
|
}
|
|
145
155
|
|
|
156
|
+
function badRequest(message: string): Error {
|
|
157
|
+
return Object.assign(new Error(message), { statusCode: 400 });
|
|
158
|
+
}
|
|
159
|
+
|
|
146
160
|
function normalizeNullableText(
|
|
147
161
|
value: string | null | undefined,
|
|
148
162
|
): string | null {
|
|
@@ -203,6 +217,61 @@ function normalizeEmailRecipients(recipients: string[] | undefined): string[] {
|
|
|
203
217
|
return normalized;
|
|
204
218
|
}
|
|
205
219
|
|
|
220
|
+
function alertRuleDefaultsKey(ctx: AccessCtx): string {
|
|
221
|
+
return `${ALERT_RULE_DEFAULTS_KEY}:${ctx.orgId ?? "personal"}`;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function settingStringArray(value: unknown): string[] {
|
|
225
|
+
return Array.isArray(value)
|
|
226
|
+
? value.filter((item): item is string => typeof item === "string")
|
|
227
|
+
: [];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export async function getAnalyticsAlertRuleDefaults(
|
|
231
|
+
ctx: AccessCtx,
|
|
232
|
+
): Promise<AnalyticsAlertRuleDefaults> {
|
|
233
|
+
const stored = await getUserSetting(ctx.email, alertRuleDefaultsKey(ctx));
|
|
234
|
+
return {
|
|
235
|
+
emailRecipients: normalizeEmailRecipients(
|
|
236
|
+
settingStringArray(stored?.emailRecipients),
|
|
237
|
+
),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export async function rememberAnalyticsAlertRuleDefaults(
|
|
242
|
+
input: Pick<AnalyticsAlertRuleInput, "emailRecipients">,
|
|
243
|
+
ctx: AccessCtx,
|
|
244
|
+
): Promise<void> {
|
|
245
|
+
const emailRecipients = normalizeEmailRecipients(input.emailRecipients);
|
|
246
|
+
if (emailRecipients.length === 0) return;
|
|
247
|
+
try {
|
|
248
|
+
await putUserSetting(ctx.email, alertRuleDefaultsKey(ctx), {
|
|
249
|
+
emailRecipients,
|
|
250
|
+
updatedAt: nowIso(),
|
|
251
|
+
});
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.warn("Failed to persist analytics alert rule defaults", error);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function normalizeOptionalHttpUrl(
|
|
258
|
+
value: string | null | undefined,
|
|
259
|
+
label: string,
|
|
260
|
+
): string | null {
|
|
261
|
+
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
262
|
+
if (!trimmed) return null;
|
|
263
|
+
let parsed: URL;
|
|
264
|
+
try {
|
|
265
|
+
parsed = new URL(trimmed);
|
|
266
|
+
} catch {
|
|
267
|
+
throw badRequest(`${label} must be an absolute http(s) URL`);
|
|
268
|
+
}
|
|
269
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
270
|
+
throw badRequest(`${label} must be an absolute http(s) URL`);
|
|
271
|
+
}
|
|
272
|
+
return trimmed;
|
|
273
|
+
}
|
|
274
|
+
|
|
206
275
|
function boolEnv(name: string): boolean | null {
|
|
207
276
|
const raw = process.env[name]?.trim().toLowerCase();
|
|
208
277
|
if (!raw) return null;
|
|
@@ -292,6 +361,8 @@ function rowToRule(row: any): AnalyticsAlertRule {
|
|
|
292
361
|
severity: row.severity === "critical" ? "critical" : "warning",
|
|
293
362
|
channels: safeJsonParse<string[]>(row.channels, ["inbox"]),
|
|
294
363
|
emailRecipients: safeJsonParse<string[]>(row.emailRecipients, []),
|
|
364
|
+
slackWebhookUrl: row.slackWebhookUrl?.trim() || null,
|
|
365
|
+
webhookUrl: row.webhookUrl?.trim() || null,
|
|
295
366
|
enabled: row.enabled === true || row.enabled === 1,
|
|
296
367
|
lastEvaluatedAt: row.lastEvaluatedAt ?? null,
|
|
297
368
|
lastTriggeredAt: row.lastTriggeredAt ?? null,
|
|
@@ -360,6 +431,11 @@ export async function saveAnalyticsAlertRule(
|
|
|
360
431
|
const severity = input.severity === "critical" ? "critical" : "warning";
|
|
361
432
|
const emailRecipients = normalizeEmailRecipients(input.emailRecipients);
|
|
362
433
|
const channels = normalizeChannels(input.channels, emailRecipients);
|
|
434
|
+
const slackWebhookUrl = normalizeOptionalHttpUrl(
|
|
435
|
+
input.slackWebhookUrl,
|
|
436
|
+
"Slack webhook URL",
|
|
437
|
+
);
|
|
438
|
+
const webhookUrl = normalizeOptionalHttpUrl(input.webhookUrl, "Webhook URL");
|
|
363
439
|
const enabled = input.enabled ?? true;
|
|
364
440
|
const db = getDb() as any;
|
|
365
441
|
|
|
@@ -385,6 +461,8 @@ export async function saveAnalyticsAlertRule(
|
|
|
385
461
|
severity,
|
|
386
462
|
channels: JSON.stringify(channels),
|
|
387
463
|
emailRecipients: JSON.stringify(emailRecipients),
|
|
464
|
+
slackWebhookUrl,
|
|
465
|
+
webhookUrl,
|
|
388
466
|
enabled,
|
|
389
467
|
updatedAt,
|
|
390
468
|
lastError: null,
|
|
@@ -405,6 +483,8 @@ export async function saveAnalyticsAlertRule(
|
|
|
405
483
|
severity,
|
|
406
484
|
channels: JSON.stringify(channels),
|
|
407
485
|
emailRecipients: JSON.stringify(emailRecipients),
|
|
486
|
+
slackWebhookUrl,
|
|
487
|
+
webhookUrl,
|
|
408
488
|
enabled,
|
|
409
489
|
createdAt: updatedAt,
|
|
410
490
|
updatedAt,
|
|
@@ -415,6 +495,7 @@ export async function saveAnalyticsAlertRule(
|
|
|
415
495
|
|
|
416
496
|
const saved = await getAnalyticsAlertRule(id, ctx);
|
|
417
497
|
if (!saved) throw new Error("Failed to save analytics alert rule");
|
|
498
|
+
await rememberAnalyticsAlertRuleDefaults({ emailRecipients }, ctx);
|
|
418
499
|
recordChange({
|
|
419
500
|
source: "analytics-alert-rules",
|
|
420
501
|
type: "change",
|
|
@@ -657,6 +738,7 @@ export async function evaluateAndNotifyAnalyticsAlertRule(
|
|
|
657
738
|
|
|
658
739
|
const body = alertBody(rule, evaluation);
|
|
659
740
|
const channels = ensureInboxNotificationChannel(rule.channels);
|
|
741
|
+
const deliveryMetadata = alertNotifyDeliveryMetadata(rule);
|
|
660
742
|
const delivery = await notifyWithDelivery(
|
|
661
743
|
{
|
|
662
744
|
severity: rule.severity,
|
|
@@ -680,6 +762,7 @@ export async function evaluateAndNotifyAnalyticsAlertRule(
|
|
|
680
762
|
sampleEvents: evaluation.sampleEvents,
|
|
681
763
|
emailRecipients: rule.emailRecipients,
|
|
682
764
|
requestedChannels: rule.channels,
|
|
765
|
+
...(deliveryMetadata ? { delivery: deliveryMetadata } : {}),
|
|
683
766
|
},
|
|
684
767
|
},
|
|
685
768
|
{ owner: rule.ownerEmail },
|
|
@@ -719,6 +802,15 @@ function ensureInboxNotificationChannel(channels: string[]): string[] {
|
|
|
719
802
|
return normalized.includes("inbox") ? normalized : ["inbox", ...normalized];
|
|
720
803
|
}
|
|
721
804
|
|
|
805
|
+
function alertNotifyDeliveryMetadata(
|
|
806
|
+
rule: AnalyticsAlertRule,
|
|
807
|
+
): Record<string, string> | undefined {
|
|
808
|
+
const delivery: Record<string, string> = {};
|
|
809
|
+
if (rule.slackWebhookUrl) delivery.slackWebhookUrl = rule.slackWebhookUrl;
|
|
810
|
+
if (rule.webhookUrl) delivery.webhookUrl = rule.webhookUrl;
|
|
811
|
+
return Object.keys(delivery).length > 0 ? delivery : undefined;
|
|
812
|
+
}
|
|
813
|
+
|
|
722
814
|
export async function markAnalyticsAlertRuleError(
|
|
723
815
|
id: string,
|
|
724
816
|
error: unknown,
|