@agent-native/core 0.90.11 → 0.91.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +34 -0
- package/corpus/core/docs/content/toolkit-settings.mdx +56 -3
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/agent/run-ownership.ts +29 -1
- package/corpus/core/src/changelog/parse.ts +78 -0
- package/corpus/core/src/chat-threads/schema.ts +43 -0
- package/corpus/core/src/chat-threads/store.ts +144 -12
- package/corpus/core/src/cli/design-connect.ts +53 -9
- package/corpus/core/src/cli/workspace-dev.ts +25 -5
- package/corpus/core/src/client/AgentPanel.tsx +79 -14
- package/corpus/core/src/client/AssistantChat.tsx +359 -425
- package/corpus/core/src/client/analytics-session.ts +70 -0
- package/corpus/core/src/client/analytics.ts +175 -49
- package/corpus/core/src/client/chat/message-components.tsx +22 -2
- package/corpus/core/src/client/components/ui/message-scroller.tsx +131 -0
- package/corpus/core/src/client/conversation/AgentConversation.tsx +63 -41
- package/corpus/core/src/client/error-capture.ts +616 -0
- package/corpus/core/src/client/index.ts +12 -0
- package/corpus/core/src/client/session-replay.ts +57 -7
- package/corpus/core/src/client/settings/SettingsPanel.tsx +123 -1
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +292 -45
- package/corpus/core/src/client/settings/index.ts +1 -0
- package/corpus/core/src/client/sharing/ShareButton.tsx +14 -11
- package/corpus/core/src/client/sharing/ShareDialog.tsx +13 -10
- package/corpus/core/src/mcp/builtin-tools.ts +29 -2
- package/corpus/core/src/server/agent-chat-plugin.ts +174 -79
- package/corpus/core/src/server/onboarding-html.ts +28 -16
- package/corpus/core/src/sharing/actions/list-resource-shares.ts +45 -1
- package/corpus/core/src/sharing/actions/share-resource.ts +9 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
- package/corpus/core/src/vite/client.ts +217 -35
- package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +8 -7
- package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +14 -10
- package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +15 -15
- package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +1 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +38 -22
- package/corpus/templates/analytics/.agents/skills/data-programs/SKILL.md +114 -61
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +1 -0
- package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +7 -7
- package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +1 -0
- package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +1 -1
- package/corpus/templates/analytics/.builder/skills/bigquery/SKILL.md +17 -17
- package/corpus/templates/analytics/.builder/skills/gcloud/SKILL.md +5 -5
- package/corpus/templates/analytics/.builder/skills/github/SKILL.md +7 -7
- package/corpus/templates/analytics/.builder/skills/gong/SKILL.md +12 -12
- package/corpus/templates/analytics/.builder/skills/grafana/SKILL.md +7 -7
- package/corpus/templates/analytics/.builder/skills/sentry/SKILL.md +7 -7
- package/corpus/templates/analytics/.builder/skills/slack/SKILL.md +6 -6
- package/corpus/templates/analytics/.builder/skills/stripe/SKILL.md +7 -7
- package/corpus/templates/analytics/AGENTS.md +47 -2
- package/corpus/templates/analytics/actions/add-status-page-monitor.ts +36 -0
- package/corpus/templates/analytics/actions/capture-test-error.ts +33 -0
- package/corpus/templates/analytics/actions/delete-monitor.ts +24 -0
- package/corpus/templates/analytics/actions/delete-status-page.ts +23 -0
- package/corpus/templates/analytics/actions/get-error-issue.ts +36 -0
- package/corpus/templates/analytics/actions/get-monitor-stats.ts +55 -0
- package/corpus/templates/analytics/actions/get-monitor.ts +27 -0
- package/corpus/templates/analytics/actions/get-public-status-page.ts +41 -0
- package/corpus/templates/analytics/actions/get-status-page.ts +29 -0
- package/corpus/templates/analytics/actions/list-error-issues.ts +40 -0
- package/corpus/templates/analytics/actions/list-monitors.ts +21 -0
- package/corpus/templates/analytics/actions/list-status-pages.ts +21 -0
- package/corpus/templates/analytics/actions/match-error-issues.ts +51 -0
- package/corpus/templates/analytics/actions/navigate.ts +58 -4
- package/corpus/templates/analytics/actions/remove-status-page-monitor.ts +22 -0
- package/corpus/templates/analytics/actions/reorder-status-page-monitors.ts +25 -0
- package/corpus/templates/analytics/actions/resolve-error-issue.ts +38 -0
- package/corpus/templates/analytics/actions/run-monitor-check.ts +23 -0
- package/corpus/templates/analytics/actions/save-analysis.ts +1 -0
- package/corpus/templates/analytics/actions/save-monitor.ts +145 -0
- package/corpus/templates/analytics/actions/save-status-page.ts +47 -0
- package/corpus/templates/analytics/actions/view-screen.ts +212 -0
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +10 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +134 -39
- package/corpus/templates/analytics/app/components/monitoring/PublicStatusView.tsx +351 -0
- package/corpus/templates/analytics/app/components/monitoring/ResponseTimeChart.tsx +174 -0
- package/corpus/templates/analytics/app/components/monitoring/UptimeStatCards.tsx +85 -0
- package/corpus/templates/analytics/app/components/monitoring/UptimeTimelineBars.tsx +106 -0
- package/corpus/templates/analytics/app/components/monitoring/chart-utils.ts +101 -0
- package/corpus/templates/analytics/app/components/monitoring/index.ts +28 -0
- package/corpus/templates/analytics/app/components/monitoring/types.ts +42 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +34 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +6 -0
- package/corpus/templates/analytics/app/i18n-data.ts +33 -0
- package/corpus/templates/analytics/app/pages/DataSources.tsx +28 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +77 -9
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +3 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +7 -0
- package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +205 -0
- package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +100 -0
- package/corpus/templates/analytics/app/pages/monitoring/UptimePanel.tsx +475 -0
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +372 -0
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +360 -0
- package/corpus/templates/analytics/app/pages/monitoring/errors/Sparkline.tsx +55 -0
- package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +106 -0
- package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +75 -0
- package/corpus/templates/analytics/app/pages/monitoring/errors/utils.ts +132 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorDetail.tsx +535 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +1026 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorList.tsx +311 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/i18n.ts +235 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPageEditor.tsx +661 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPagesView.tsx +355 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/i18n.ts +106 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/slug.ts +24 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/types.ts +20 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/status-summary.ts +87 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/types.ts +161 -0
- package/corpus/templates/analytics/app/pages/monitoring/uptime/utils.ts +210 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +76 -1
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +74 -9
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +197 -20
- package/corpus/templates/analytics/app/root.tsx +33 -1
- package/corpus/templates/analytics/app/routes/monitoring._index.tsx +10 -0
- package/corpus/templates/analytics/app/routes/status.$slug.tsx +118 -0
- package/corpus/templates/analytics/changelog/2026-07-08-add-uptime-monitors-that-ping-your-urls-and-alert-you-when-t.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-analytics-chats-keep-large-data-dictionaries-compact-so-prov.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-create-public-status-pages-that-share-the-live-health-of-cho.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-extension-panels-use-clearer-open-copy.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-error-capture.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-fixed-single-panel-dashboard-drags-so-they-no-longer-rewrite.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-jump-straight-from-an-error-in-a-session-recording-to-its-fu.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-monitor-detail-and-list-now-show-colorful-uptime-timelines-r.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-pinned-ask-chats-now-show-a-pin-icon-in-the-sidebar.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-publish-a-public-uptime-status-page-with-colorful-uptime-tim.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-sessions-now-hide-visitor-emails-in-demo-mode-and-show-clean.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-settings-are-cleaner-searchable-and-alerts-have-their-own-tab.md +5 -0
- package/corpus/templates/analytics/changelog/2026-07-08-sidebar-sections-stay-collapsed-until-opened.md +5 -0
- package/corpus/templates/analytics/changelog/2026-07-08-the-uptime-monitor-list-now-has-a-current-status-overview-wi.md +6 -0
- package/corpus/templates/analytics/docs/error-capture.md +172 -0
- package/corpus/templates/analytics/docs/uptime-monitoring.md +150 -0
- package/corpus/templates/analytics/server/db/schema-errors.ts +150 -0
- package/corpus/templates/analytics/server/db/schema-monitoring.ts +177 -0
- package/corpus/templates/analytics/server/db/schema.ts +6 -0
- package/corpus/templates/analytics/server/jobs/uptime-monitors.ts +123 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +41 -0
- package/corpus/templates/analytics/server/lib/data-dictionary-context.ts +55 -12
- package/corpus/templates/analytics/server/lib/error-capture.ts +1331 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +47 -1
- package/corpus/templates/analytics/server/lib/monitor-stats.ts +494 -0
- package/corpus/templates/analytics/server/lib/status-pages.ts +798 -0
- package/corpus/templates/analytics/server/lib/uptime-monitors.ts +1665 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -37
- package/corpus/templates/analytics/server/plugins/auth.ts +11 -1
- package/corpus/templates/analytics/server/plugins/db.ts +408 -0
- package/corpus/templates/analytics/server/plugins/uptime-monitor-jobs.ts +63 -0
- package/corpus/templates/assets/app/routes/_index.tsx +1 -1
- package/corpus/templates/assets/app/routes/settings.tsx +22 -1
- package/corpus/templates/assets/changelog/2026-07-08-recent-drafts-keep-comfortable-side-padding.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/brain/app/routes/settings.tsx +43 -5
- package/corpus/templates/brain/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/calendar/app/pages/Settings.tsx +44 -6
- package/corpus/templates/calendar/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/chat/app/routes/settings.tsx +16 -1
- package/corpus/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +79 -37
- package/corpus/templates/clips/app/components/player/player-controls.tsx +35 -0
- package/corpus/templates/clips/app/components/player/video-player.tsx +162 -18
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +63 -6
- package/corpus/templates/clips/app/routes/record.tsx +18 -1
- package/corpus/templates/clips/changelog/2026-07-07-shared-clips-start-playback-reliably-from-the-first-play-click.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-camera-and-microphone-menus-now-show-which-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-copies-new-clip-links-after-saving.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-recordings-now-continue-after-granting-came.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-mobile-shared-clips-now-have-loom-style-tap-and-skip-controls.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-recordings-and-uploads-copy-links-after-saving.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-settings-are-cleaner-searchable-and-collapse-s3-with-builder.md +5 -0
- package/corpus/templates/clips/changelog/2026-07-08-transcripts-are-more-reliable-for-longer-desktop-recordings-.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +162 -13
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +14 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +36 -0
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +99 -25
- package/corpus/templates/clips/chrome-extension/src/permission.ts +63 -14
- package/corpus/templates/clips/chrome-extension/src/popup.ts +123 -23
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +47 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +33 -4
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +214 -29
- package/corpus/templates/content/actions/attach-content-database-source.ts +3 -0
- package/corpus/templates/content/actions/change-content-database-source-role.ts +1 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +42 -32
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +352 -81
- package/corpus/templates/content/app/components/editor/database/settings.tsx +49 -24
- package/corpus/templates/content/app/routes/_app.settings.tsx +19 -1
- package/corpus/templates/content/changelog/2026-07-07-builder-source-tag-fields-now-import-as-multi-select.md +6 -0
- package/corpus/templates/content/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/content/shared/api.ts +3 -0
- package/corpus/templates/content/shared/properties.ts +42 -0
- package/corpus/templates/design/AGENTS.md +9 -0
- package/corpus/templates/design/actions/generate-design.ts +3 -0
- package/corpus/templates/design/actions/get-design-system.ts +147 -1
- package/corpus/templates/design/actions/request-localhost-write-consent.ts +141 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +13 -19
- package/corpus/templates/design/app/routes/settings.tsx +16 -1
- package/corpus/templates/design/changelog/2026-07-08-design-generation-now-follows-hydrated-builder-design-system.md +6 -0
- package/corpus/templates/design/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/design/server/lib/verify-write-grant.ts +4 -2
- package/corpus/templates/dispatch/app/routes/settings.tsx +23 -2
- package/corpus/templates/dispatch/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/forms/app/routes/_app.settings.tsx +16 -1
- package/corpus/templates/forms/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/macros/app/routes/settings.tsx +16 -1
- package/corpus/templates/macros/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/mail/app/components/settings/GmailFiltersSection.tsx +1 -1
- package/corpus/templates/mail/app/components/settings/SnippetsSection.tsx +1 -1
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +123 -105
- package/corpus/templates/mail/changelog/2026-07-08-settings-redesigned-with-a-consistent-searchable-layout.md +5 -0
- package/corpus/templates/plan/app/routes/settings.tsx +23 -2
- package/corpus/templates/plan/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/corpus/templates/slides/actions/add-slide.ts +1 -0
- package/corpus/templates/slides/actions/get-design-system.ts +147 -1
- package/corpus/templates/slides/app/pages/Index.tsx +46 -1
- package/corpus/templates/slides/app/routes/settings.tsx +16 -1
- package/corpus/templates/slides/changelog/2026-07-08-deck-generation-now-follows-hydrated-builder-design-system-g.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
- package/dist/agent/run-ownership.d.ts +6 -0
- package/dist/agent/run-ownership.d.ts.map +1 -1
- package/dist/agent/run-ownership.js +11 -1
- package/dist/agent/run-ownership.js.map +1 -1
- package/dist/changelog/parse.d.ts +7 -0
- package/dist/changelog/parse.d.ts.map +1 -1
- package/dist/changelog/parse.js +64 -0
- package/dist/changelog/parse.js.map +1 -1
- package/dist/chat-threads/schema.d.ts +445 -0
- package/dist/chat-threads/schema.d.ts.map +1 -0
- package/dist/chat-threads/schema.js +39 -0
- package/dist/chat-threads/schema.js.map +1 -0
- package/dist/chat-threads/store.d.ts +12 -0
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +99 -10
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +40 -10
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/workspace-dev.d.ts.map +1 -1
- package/dist/cli/workspace-dev.js +20 -5
- package/dist/cli/workspace-dev.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +35 -7
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +105 -183
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/analytics-session.d.ts +3 -0
- package/dist/client/analytics-session.d.ts.map +1 -0
- package/dist/client/analytics-session.js +66 -0
- package/dist/client/analytics-session.js.map +1 -0
- package/dist/client/analytics.d.ts +32 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +116 -46
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +2 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +16 -6
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/components/ui/message-scroller.d.ts +16 -0
- package/dist/client/components/ui/message-scroller.d.ts.map +1 -0
- package/dist/client/components/ui/message-scroller.js +25 -0
- package/dist/client/components/ui/message-scroller.js.map +1 -0
- package/dist/client/conversation/AgentConversation.d.ts +1 -1
- package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
- package/dist/client/conversation/AgentConversation.js +3 -8
- package/dist/client/conversation/AgentConversation.js.map +1 -1
- package/dist/client/error-capture.d.ts +99 -0
- package/dist/client/error-capture.d.ts.map +1 -0
- package/dist/client/error-capture.js +437 -0
- package/dist/client/error-capture.js.map +1 -0
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/session-replay.d.ts +22 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +45 -4
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +100 -5
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts +49 -1
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
- package/dist/client/settings/SettingsTabsPage.js +131 -19
- package/dist/client/settings/SettingsTabsPage.js.map +1 -1
- package/dist/client/settings/index.d.ts +1 -1
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +13 -8
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/client/sharing/ShareDialog.js +12 -7
- package/dist/client/sharing/ShareDialog.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +21 -2
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/org/schema.d.ts +15 -15
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +109 -73
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +28 -16
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/sharing/actions/list-resource-shares.js +30 -1
- package/dist/sharing/actions/list-resource-shares.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +6 -0
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
- package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +192 -30
- package/dist/vite/client.js.map +1 -1
- package/docs/content/toolkit-settings.mdx +56 -3
- package/package.json +2 -1
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
- package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPagesView.tsx
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status-pages config sub-view. Query-param driven, consistent with the monitor
|
|
3
|
+
* sub-views:
|
|
4
|
+
* - index: ?view=uptime&statuspage=list
|
|
5
|
+
* - create: ?view=uptime&statuspage=new
|
|
6
|
+
* - edit: ?view=uptime&statuspage=<id>
|
|
7
|
+
* The index lists existing pages (with copy-link / open / edit / delete); the
|
|
8
|
+
* editor (StatusPageEditor) handles create + edit with a live preview.
|
|
9
|
+
*/
|
|
10
|
+
import { useActionMutation, useActionQuery } from "@agent-native/core/client";
|
|
11
|
+
import {
|
|
12
|
+
IconArrowLeft,
|
|
13
|
+
IconCheck,
|
|
14
|
+
IconCopy,
|
|
15
|
+
IconExternalLink,
|
|
16
|
+
IconLink,
|
|
17
|
+
IconPencil,
|
|
18
|
+
IconPlus,
|
|
19
|
+
IconTrash,
|
|
20
|
+
} from "@tabler/icons-react";
|
|
21
|
+
import { useState } from "react";
|
|
22
|
+
import { useSearchParams } from "react-router";
|
|
23
|
+
import { toast } from "sonner";
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
AlertDialog,
|
|
27
|
+
AlertDialogAction,
|
|
28
|
+
AlertDialogCancel,
|
|
29
|
+
AlertDialogContent,
|
|
30
|
+
AlertDialogDescription,
|
|
31
|
+
AlertDialogFooter,
|
|
32
|
+
AlertDialogHeader,
|
|
33
|
+
AlertDialogTitle,
|
|
34
|
+
} from "@/components/ui/alert-dialog";
|
|
35
|
+
import { Badge } from "@/components/ui/badge";
|
|
36
|
+
import { Button } from "@/components/ui/button";
|
|
37
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
38
|
+
import {
|
|
39
|
+
Tooltip,
|
|
40
|
+
TooltipContent,
|
|
41
|
+
TooltipTrigger,
|
|
42
|
+
} from "@/components/ui/tooltip";
|
|
43
|
+
|
|
44
|
+
import { fmt, useStatusPagesT } from "./i18n";
|
|
45
|
+
import { StatusPageEditor } from "./StatusPageEditor";
|
|
46
|
+
import type { StatusPage } from "./types";
|
|
47
|
+
|
|
48
|
+
function statusPageOrigin(): string {
|
|
49
|
+
if (typeof window === "undefined") return "";
|
|
50
|
+
return window.location.origin;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function StatusPagesView() {
|
|
54
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
55
|
+
const param = searchParams.get("statuspage");
|
|
56
|
+
|
|
57
|
+
const updateParams = (
|
|
58
|
+
mutate: (params: URLSearchParams) => void,
|
|
59
|
+
options?: { replace?: boolean },
|
|
60
|
+
) => {
|
|
61
|
+
setSearchParams(
|
|
62
|
+
(prev) => {
|
|
63
|
+
const params = new URLSearchParams(prev);
|
|
64
|
+
mutate(params);
|
|
65
|
+
return params;
|
|
66
|
+
},
|
|
67
|
+
{ replace: options?.replace ?? false },
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const goToMonitors = () =>
|
|
72
|
+
updateParams((params) => {
|
|
73
|
+
params.delete("statuspage");
|
|
74
|
+
params.delete("monitor");
|
|
75
|
+
params.delete("edit");
|
|
76
|
+
});
|
|
77
|
+
const goToIndex = (options?: { replace?: boolean }) =>
|
|
78
|
+
updateParams((params) => params.set("statuspage", "list"), options);
|
|
79
|
+
const goToNew = () =>
|
|
80
|
+
updateParams((params) => params.set("statuspage", "new"));
|
|
81
|
+
const goToEdit = (id: string, options?: { replace?: boolean }) =>
|
|
82
|
+
updateParams((params) => params.set("statuspage", id), options);
|
|
83
|
+
|
|
84
|
+
if (param && param !== "list") {
|
|
85
|
+
return (
|
|
86
|
+
<StatusPageEditor
|
|
87
|
+
pageId={param === "new" ? null : param}
|
|
88
|
+
onBack={goToIndex}
|
|
89
|
+
onCreated={(id) => goToEdit(id, { replace: true })}
|
|
90
|
+
/>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<StatusPagesIndex onBack={goToMonitors} onNew={goToNew} onEdit={goToEdit} />
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function StatusPagesIndex({
|
|
100
|
+
onBack,
|
|
101
|
+
onNew,
|
|
102
|
+
onEdit,
|
|
103
|
+
}: {
|
|
104
|
+
onBack: () => void;
|
|
105
|
+
onNew: () => void;
|
|
106
|
+
onEdit: (id: string) => void;
|
|
107
|
+
}) {
|
|
108
|
+
const t = useStatusPagesT();
|
|
109
|
+
const { data, isLoading } = useActionQuery<StatusPage[]>(
|
|
110
|
+
"list-status-pages",
|
|
111
|
+
undefined,
|
|
112
|
+
{ staleTime: 15_000 },
|
|
113
|
+
);
|
|
114
|
+
const deletePage = useActionMutation<{ id: string }, { id: string }>(
|
|
115
|
+
"delete-status-page",
|
|
116
|
+
{ method: "DELETE" },
|
|
117
|
+
);
|
|
118
|
+
const [toDelete, setToDelete] = useState<StatusPage | null>(null);
|
|
119
|
+
const pages = Array.isArray(data) ? data : [];
|
|
120
|
+
|
|
121
|
+
const confirmDelete = async () => {
|
|
122
|
+
if (!toDelete) return;
|
|
123
|
+
const target = toDelete;
|
|
124
|
+
setToDelete(null);
|
|
125
|
+
try {
|
|
126
|
+
await deletePage.mutateAsync({ id: target.id });
|
|
127
|
+
toast.success(t.deletedToast);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
toast.error(
|
|
130
|
+
fmt(t.deleteFailed, {
|
|
131
|
+
message: err instanceof Error ? err.message : String(err),
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<div className="space-y-5">
|
|
139
|
+
<Button
|
|
140
|
+
variant="ghost"
|
|
141
|
+
size="sm"
|
|
142
|
+
className="-ms-2 w-fit text-muted-foreground"
|
|
143
|
+
onClick={onBack}
|
|
144
|
+
>
|
|
145
|
+
<IconArrowLeft className="size-3.5" />
|
|
146
|
+
{t.back}
|
|
147
|
+
</Button>
|
|
148
|
+
|
|
149
|
+
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
|
150
|
+
<div className="min-w-0">
|
|
151
|
+
<h2 className="text-lg font-semibold">{t.title}</h2>
|
|
152
|
+
<p className="max-w-xl text-sm text-muted-foreground">{t.subtitle}</p>
|
|
153
|
+
</div>
|
|
154
|
+
<Button size="sm" onClick={onNew} className="shrink-0">
|
|
155
|
+
<IconPlus className="size-3.5" />
|
|
156
|
+
{t.newPage}
|
|
157
|
+
</Button>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
{isLoading ? (
|
|
161
|
+
<div className="space-y-2">
|
|
162
|
+
{[0, 1].map((i) => (
|
|
163
|
+
<Skeleton key={i} className="h-16 w-full rounded-lg" />
|
|
164
|
+
))}
|
|
165
|
+
</div>
|
|
166
|
+
) : pages.length === 0 ? (
|
|
167
|
+
<div className="flex flex-col items-center justify-center rounded-lg border border-dashed px-6 py-16 text-center">
|
|
168
|
+
<div className="mb-4 flex size-14 items-center justify-center rounded-2xl bg-primary/10">
|
|
169
|
+
<IconLink className="size-7 text-primary" />
|
|
170
|
+
</div>
|
|
171
|
+
<h3 className="text-lg font-semibold">{t.emptyTitle}</h3>
|
|
172
|
+
<p className="mx-auto mt-1.5 max-w-md text-sm text-muted-foreground">
|
|
173
|
+
{t.emptyDescription}
|
|
174
|
+
</p>
|
|
175
|
+
<Button className="mt-5" size="sm" onClick={onNew}>
|
|
176
|
+
<IconPlus className="size-3.5" />
|
|
177
|
+
{t.emptyCta}
|
|
178
|
+
</Button>
|
|
179
|
+
</div>
|
|
180
|
+
) : (
|
|
181
|
+
<div className="space-y-2">
|
|
182
|
+
{pages.map((page) => (
|
|
183
|
+
<StatusPageRow
|
|
184
|
+
key={page.id}
|
|
185
|
+
page={page}
|
|
186
|
+
onEdit={() => onEdit(page.id)}
|
|
187
|
+
onDelete={() => setToDelete(page)}
|
|
188
|
+
/>
|
|
189
|
+
))}
|
|
190
|
+
</div>
|
|
191
|
+
)}
|
|
192
|
+
|
|
193
|
+
<AlertDialog
|
|
194
|
+
open={!!toDelete}
|
|
195
|
+
onOpenChange={(open) => !open && setToDelete(null)}
|
|
196
|
+
>
|
|
197
|
+
<AlertDialogContent>
|
|
198
|
+
<AlertDialogHeader>
|
|
199
|
+
<AlertDialogTitle>{t.deleteTitle}</AlertDialogTitle>
|
|
200
|
+
<AlertDialogDescription>
|
|
201
|
+
{fmt(t.deleteDescription, {
|
|
202
|
+
title: toDelete?.title ?? "",
|
|
203
|
+
slug: toDelete?.slug ?? "",
|
|
204
|
+
})}
|
|
205
|
+
</AlertDialogDescription>
|
|
206
|
+
</AlertDialogHeader>
|
|
207
|
+
<AlertDialogFooter>
|
|
208
|
+
<AlertDialogCancel>{t.cancel}</AlertDialogCancel>
|
|
209
|
+
<AlertDialogAction
|
|
210
|
+
onClick={confirmDelete}
|
|
211
|
+
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
212
|
+
>
|
|
213
|
+
{t.deleteConfirm}
|
|
214
|
+
</AlertDialogAction>
|
|
215
|
+
</AlertDialogFooter>
|
|
216
|
+
</AlertDialogContent>
|
|
217
|
+
</AlertDialog>
|
|
218
|
+
</div>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function StatusPageRow({
|
|
223
|
+
page,
|
|
224
|
+
onEdit,
|
|
225
|
+
onDelete,
|
|
226
|
+
}: {
|
|
227
|
+
page: StatusPage;
|
|
228
|
+
onEdit: () => void;
|
|
229
|
+
onDelete: () => void;
|
|
230
|
+
}) {
|
|
231
|
+
const t = useStatusPagesT();
|
|
232
|
+
const [copied, setCopied] = useState(false);
|
|
233
|
+
const publicUrl = `${statusPageOrigin()}/status/${page.slug}`;
|
|
234
|
+
const count = page.monitors.length;
|
|
235
|
+
|
|
236
|
+
const copyLink = async () => {
|
|
237
|
+
try {
|
|
238
|
+
await navigator.clipboard.writeText(publicUrl);
|
|
239
|
+
setCopied(true);
|
|
240
|
+
window.setTimeout(() => setCopied(false), 1500);
|
|
241
|
+
} catch {
|
|
242
|
+
toast.error(t.copyFailed);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
return (
|
|
247
|
+
<div
|
|
248
|
+
role="button"
|
|
249
|
+
tabIndex={0}
|
|
250
|
+
onClick={onEdit}
|
|
251
|
+
onKeyDown={(e) => {
|
|
252
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
253
|
+
e.preventDefault();
|
|
254
|
+
onEdit();
|
|
255
|
+
}
|
|
256
|
+
}}
|
|
257
|
+
className="group flex cursor-pointer items-center gap-4 rounded-lg border border-border/50 bg-card px-4 py-3 transition-colors hover:border-border hover:bg-muted/30"
|
|
258
|
+
>
|
|
259
|
+
<div className="min-w-0 flex-1">
|
|
260
|
+
<div className="flex items-center gap-2">
|
|
261
|
+
<span className="truncate text-sm font-medium">{page.title}</span>
|
|
262
|
+
<Badge
|
|
263
|
+
variant={page.published ? "default" : "secondary"}
|
|
264
|
+
className="shrink-0 text-[10px]"
|
|
265
|
+
>
|
|
266
|
+
{page.published ? t.publishedBadge : t.draftBadge}
|
|
267
|
+
</Badge>
|
|
268
|
+
</div>
|
|
269
|
+
<div className="truncate text-xs text-muted-foreground">
|
|
270
|
+
/status/{page.slug}
|
|
271
|
+
<span className="text-muted-foreground/70">
|
|
272
|
+
{" · "}
|
|
273
|
+
{count === 0
|
|
274
|
+
? t.noMonitorsOnPage
|
|
275
|
+
: fmt(count === 1 ? t.oneMonitor : t.monitorsCount, { count })}
|
|
276
|
+
</span>
|
|
277
|
+
</div>
|
|
278
|
+
</div>
|
|
279
|
+
|
|
280
|
+
<div
|
|
281
|
+
className="flex shrink-0 items-center gap-1"
|
|
282
|
+
onClick={(e) => e.stopPropagation()}
|
|
283
|
+
>
|
|
284
|
+
<Tooltip>
|
|
285
|
+
<TooltipTrigger asChild>
|
|
286
|
+
<Button
|
|
287
|
+
variant="ghost"
|
|
288
|
+
size="icon"
|
|
289
|
+
className="size-8 text-muted-foreground"
|
|
290
|
+
onClick={copyLink}
|
|
291
|
+
aria-label={t.copyLink}
|
|
292
|
+
>
|
|
293
|
+
{copied ? (
|
|
294
|
+
<IconCheck className="size-3.5" />
|
|
295
|
+
) : (
|
|
296
|
+
<IconCopy className="size-3.5" />
|
|
297
|
+
)}
|
|
298
|
+
</Button>
|
|
299
|
+
</TooltipTrigger>
|
|
300
|
+
<TooltipContent>{copied ? t.copied : t.copyLink}</TooltipContent>
|
|
301
|
+
</Tooltip>
|
|
302
|
+
{page.published ? (
|
|
303
|
+
<Tooltip>
|
|
304
|
+
<TooltipTrigger asChild>
|
|
305
|
+
<Button
|
|
306
|
+
variant="ghost"
|
|
307
|
+
size="icon"
|
|
308
|
+
className="size-8 text-muted-foreground"
|
|
309
|
+
asChild
|
|
310
|
+
>
|
|
311
|
+
<a
|
|
312
|
+
href={publicUrl}
|
|
313
|
+
target="_blank"
|
|
314
|
+
rel="noreferrer noopener"
|
|
315
|
+
aria-label={t.openPage}
|
|
316
|
+
>
|
|
317
|
+
<IconExternalLink className="size-3.5" />
|
|
318
|
+
</a>
|
|
319
|
+
</Button>
|
|
320
|
+
</TooltipTrigger>
|
|
321
|
+
<TooltipContent>{t.openPage}</TooltipContent>
|
|
322
|
+
</Tooltip>
|
|
323
|
+
) : null}
|
|
324
|
+
<Tooltip>
|
|
325
|
+
<TooltipTrigger asChild>
|
|
326
|
+
<Button
|
|
327
|
+
variant="ghost"
|
|
328
|
+
size="icon"
|
|
329
|
+
className="size-8 text-muted-foreground"
|
|
330
|
+
onClick={onEdit}
|
|
331
|
+
aria-label={t.edit}
|
|
332
|
+
>
|
|
333
|
+
<IconPencil className="size-3.5" />
|
|
334
|
+
</Button>
|
|
335
|
+
</TooltipTrigger>
|
|
336
|
+
<TooltipContent>{t.edit}</TooltipContent>
|
|
337
|
+
</Tooltip>
|
|
338
|
+
<Tooltip>
|
|
339
|
+
<TooltipTrigger asChild>
|
|
340
|
+
<Button
|
|
341
|
+
variant="ghost"
|
|
342
|
+
size="icon"
|
|
343
|
+
className="size-8 text-muted-foreground hover:text-destructive"
|
|
344
|
+
onClick={onDelete}
|
|
345
|
+
aria-label={t.delete}
|
|
346
|
+
>
|
|
347
|
+
<IconTrash className="size-3.5" />
|
|
348
|
+
</Button>
|
|
349
|
+
</TooltipTrigger>
|
|
350
|
+
<TooltipContent>{t.delete}</TooltipContent>
|
|
351
|
+
</Tooltip>
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-contained i18n for the status-pages config sub-view. English is the
|
|
3
|
+
* source of truth; other locales fall back per key. Reuses the uptime feature's
|
|
4
|
+
* `fmt` interpolation helper.
|
|
5
|
+
*/
|
|
6
|
+
import { useLocale } from "@agent-native/core/client";
|
|
7
|
+
|
|
8
|
+
export { fmt } from "../i18n";
|
|
9
|
+
|
|
10
|
+
const MESSAGES = {
|
|
11
|
+
"en-US": {
|
|
12
|
+
// Entry / index
|
|
13
|
+
title: "Status pages", // i18n-ignore feature-local i18n source
|
|
14
|
+
subtitle: // i18n-ignore feature-local i18n source
|
|
15
|
+
"Publish a public page that shows the live health of the monitors you choose.",
|
|
16
|
+
back: "Back to monitors",
|
|
17
|
+
backToPages: "Back to status pages",
|
|
18
|
+
newPage: "New status page",
|
|
19
|
+
emptyTitle: "No status pages yet", // i18n-ignore feature-local i18n source
|
|
20
|
+
emptyDescription: // i18n-ignore feature-local i18n source
|
|
21
|
+
"Create a public status page to share the live health of your monitors with customers or teammates.",
|
|
22
|
+
emptyCta: "Create a status page",
|
|
23
|
+
monitorsCount: "{count} monitors",
|
|
24
|
+
oneMonitor: "1 monitor",
|
|
25
|
+
noMonitorsOnPage: "No monitors yet",
|
|
26
|
+
publishedBadge: "Published",
|
|
27
|
+
draftBadge: "Draft",
|
|
28
|
+
copyLink: "Copy link",
|
|
29
|
+
copied: "Copied",
|
|
30
|
+
openPage: "Open",
|
|
31
|
+
edit: "Edit",
|
|
32
|
+
delete: "Delete",
|
|
33
|
+
// Delete dialog
|
|
34
|
+
deleteTitle: "Delete status page?",
|
|
35
|
+
deleteDescription:
|
|
36
|
+
"This permanently deletes “{title}” and its public link at /status/{slug}.",
|
|
37
|
+
deleteConfirm: "Delete",
|
|
38
|
+
cancel: "Cancel",
|
|
39
|
+
// Editor
|
|
40
|
+
createTitle: "New status page",
|
|
41
|
+
editTitle: "Edit status page",
|
|
42
|
+
createSubtitle:
|
|
43
|
+
"Give it a title and choose which monitors to show. Publish when you're ready to share.",
|
|
44
|
+
editSubtitle: "Update what this page shows and who can see it.",
|
|
45
|
+
save: "Save status page",
|
|
46
|
+
saving: "Saving…",
|
|
47
|
+
sectionBasics: "Basics",
|
|
48
|
+
fieldTitle: "Title",
|
|
49
|
+
fieldTitlePlaceholder: "Acme Status",
|
|
50
|
+
fieldSlug: "Public URL",
|
|
51
|
+
fieldSlugHint: "Lowercase letters, numbers, and dashes.",
|
|
52
|
+
fieldDescription: "Description",
|
|
53
|
+
fieldDescriptionPlaceholder: "Live status of Acme's services.",
|
|
54
|
+
fieldPublished: "Published",
|
|
55
|
+
fieldPublishedHint: "When on, anyone with the link can view this page.",
|
|
56
|
+
linkLiveHint: "Live at {url} once published.",
|
|
57
|
+
linkLive: "Live at {url}",
|
|
58
|
+
sectionLayout: "Layout",
|
|
59
|
+
fieldShowUptimeBars: "Uptime bars",
|
|
60
|
+
fieldShowOverallUptime: "Overall uptime",
|
|
61
|
+
fieldShowResponseTime: "Response time",
|
|
62
|
+
fieldDensity: "Density",
|
|
63
|
+
densityComfortable: "Comfortable",
|
|
64
|
+
densityCompact: "Compact",
|
|
65
|
+
fieldAlignment: "Alignment",
|
|
66
|
+
alignmentLeft: "Left",
|
|
67
|
+
alignmentCenter: "Center",
|
|
68
|
+
sectionMonitors: "Monitors",
|
|
69
|
+
sectionMonitorsHint: "Choose which monitors appear and in what order.",
|
|
70
|
+
addMonitor: "Add a monitor",
|
|
71
|
+
addMonitorPlaceholder: "Add a monitor…", // i18n-ignore feature-local i18n source
|
|
72
|
+
noMonitorsSelected: "No monitors added yet.",
|
|
73
|
+
noMonitorsAvailable: "All your monitors are already on this page.",
|
|
74
|
+
createMonitorsFirst: "Create a monitor first, then add it here.",
|
|
75
|
+
displayNamePlaceholder: "Display name (optional)",
|
|
76
|
+
showUrl: "Show URL",
|
|
77
|
+
moveUp: "Move up",
|
|
78
|
+
moveDown: "Move down",
|
|
79
|
+
remove: "Remove",
|
|
80
|
+
// Preview
|
|
81
|
+
sectionPreview: "Live preview",
|
|
82
|
+
previewHint: "Reflects your last save.",
|
|
83
|
+
previewSaveFirst: "Save the page to see a live preview.",
|
|
84
|
+
previewDraftNote:
|
|
85
|
+
"This page is a draft — publish it to make the link live.",
|
|
86
|
+
// Validation / toasts
|
|
87
|
+
titleRequired: "Give the page a title.",
|
|
88
|
+
slugInvalid: "Use lowercase letters, numbers, and dashes.",
|
|
89
|
+
savedToast: "Status page saved.",
|
|
90
|
+
saveFailed: "Could not save status page: {message}",
|
|
91
|
+
deletedToast: "Status page deleted.",
|
|
92
|
+
deleteFailed: "Could not delete status page: {message}",
|
|
93
|
+
copyFailed: "Could not copy the link.",
|
|
94
|
+
},
|
|
95
|
+
} as const;
|
|
96
|
+
|
|
97
|
+
type StatusPagesMessages = (typeof MESSAGES)["en-US"];
|
|
98
|
+
|
|
99
|
+
export function useStatusPagesT(): StatusPagesMessages {
|
|
100
|
+
const { locale } = useLocale();
|
|
101
|
+
return {
|
|
102
|
+
...MESSAGES["en-US"],
|
|
103
|
+
...((MESSAGES as Record<string, Partial<StatusPagesMessages>>)[locale] ??
|
|
104
|
+
{}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side slug helpers for status pages. Mirror the server `normalizeSlug`
|
|
3
|
+
* (server/lib/status-pages.ts) so the in-app editor derives + validates the
|
|
4
|
+
* public `/status/<slug>` value the same way the server will store it. Pure so
|
|
5
|
+
* they are trivially unit-tested.
|
|
6
|
+
*/
|
|
7
|
+
export const MAX_SLUG_LENGTH = 64;
|
|
8
|
+
|
|
9
|
+
/** Lowercase, `[a-z0-9-]`, collapsed/trimmed dashes, capped at 64 chars. */
|
|
10
|
+
export function slugify(raw: string): string {
|
|
11
|
+
return String(raw ?? "")
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.trim()
|
|
14
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
15
|
+
.replace(/^-+|-+$/g, "")
|
|
16
|
+
.slice(0, MAX_SLUG_LENGTH)
|
|
17
|
+
.replace(/^-+|-+$/g, "");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** A slug is valid when it is non-empty, `[a-z0-9-]`, no leading/trailing/double dashes. */
|
|
21
|
+
export function isValidSlug(slug: string): boolean {
|
|
22
|
+
if (!slug || slug.length > MAX_SLUG_LENGTH) return false;
|
|
23
|
+
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug);
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-facing status-page contract. We re-export the server library's
|
|
3
|
+
* type-only shapes (erased at build time) from a single place so the editor and
|
|
4
|
+
* list components share one source of truth with the actions they call.
|
|
5
|
+
*/
|
|
6
|
+
export type {
|
|
7
|
+
PublicStatusPage,
|
|
8
|
+
StatusPage,
|
|
9
|
+
StatusPageAlignment,
|
|
10
|
+
StatusPageDensity,
|
|
11
|
+
StatusPageInput,
|
|
12
|
+
StatusPageMonitorInput,
|
|
13
|
+
StatusPageMonitorRef,
|
|
14
|
+
} from "../../../../../server/lib/status-pages";
|
|
15
|
+
|
|
16
|
+
/** Response shape of the `get-status-page` action: config + live preview view. */
|
|
17
|
+
export interface StatusPagePreview {
|
|
18
|
+
page: import("../../../../../server/lib/status-pages").StatusPage;
|
|
19
|
+
view: import("../../../../../server/lib/status-pages").PublicStatusPage;
|
|
20
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure aggregate math for the monitor list "current status" overview. Kept free
|
|
3
|
+
* of React / i18n imports so it can be unit-tested in isolation and reused by
|
|
4
|
+
* the list summary without pulling in the whole panel.
|
|
5
|
+
*/
|
|
6
|
+
import type { MonitorStatus } from "./types";
|
|
7
|
+
|
|
8
|
+
export type MonitorHealthTone = "up" | "down" | "degraded" | "neutral";
|
|
9
|
+
|
|
10
|
+
/** Coarse tone for a monitor's current status (mirrors utils.statusTone). */
|
|
11
|
+
export function statusToneOf(status: MonitorStatus | null): MonitorHealthTone {
|
|
12
|
+
switch (status) {
|
|
13
|
+
case "up":
|
|
14
|
+
return "up";
|
|
15
|
+
case "down":
|
|
16
|
+
case "error":
|
|
17
|
+
return "down";
|
|
18
|
+
case "degraded":
|
|
19
|
+
return "degraded";
|
|
20
|
+
default:
|
|
21
|
+
return "neutral";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface MonitorStatusSummary {
|
|
26
|
+
total: number;
|
|
27
|
+
up: number;
|
|
28
|
+
down: number;
|
|
29
|
+
degraded: number;
|
|
30
|
+
/** Monitors with no conclusive status yet (pending / running / unknown). */
|
|
31
|
+
pending: number;
|
|
32
|
+
/** Mean of available 24h uptime across monitors, or null when none report. */
|
|
33
|
+
overallUptimePct: number | null;
|
|
34
|
+
/** Monitors currently failing — each has an open incident by the incident model. */
|
|
35
|
+
openIncidents: number;
|
|
36
|
+
/** Worst tone across the set, for the headline badge. */
|
|
37
|
+
overall: MonitorHealthTone;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface MonitorLike {
|
|
41
|
+
id: string;
|
|
42
|
+
lastStatus: MonitorStatus | null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface StatsLike {
|
|
46
|
+
windows: { uptime24h: number | null };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Roll a set of monitors (plus their optional stats) into the "current status"
|
|
51
|
+
* summary shown atop the list: counts by health, an overall uptime average, and
|
|
52
|
+
* the open-incident count (monitors currently down or degraded).
|
|
53
|
+
*/
|
|
54
|
+
export function summarizeMonitors(
|
|
55
|
+
monitors: MonitorLike[],
|
|
56
|
+
statsById?: Map<string, StatsLike>,
|
|
57
|
+
): MonitorStatusSummary {
|
|
58
|
+
let up = 0;
|
|
59
|
+
let down = 0;
|
|
60
|
+
let degraded = 0;
|
|
61
|
+
let pending = 0;
|
|
62
|
+
const pcts: number[] = [];
|
|
63
|
+
for (const monitor of monitors) {
|
|
64
|
+
const tone = statusToneOf(monitor.lastStatus);
|
|
65
|
+
if (tone === "up") up++;
|
|
66
|
+
else if (tone === "down") down++;
|
|
67
|
+
else if (tone === "degraded") degraded++;
|
|
68
|
+
else pending++;
|
|
69
|
+
const pct = statsById?.get(monitor.id)?.windows.uptime24h;
|
|
70
|
+
if (pct != null && Number.isFinite(pct)) pcts.push(pct);
|
|
71
|
+
}
|
|
72
|
+
const overallUptimePct = pcts.length
|
|
73
|
+
? pcts.reduce((sum, value) => sum + value, 0) / pcts.length
|
|
74
|
+
: null;
|
|
75
|
+
const overall: MonitorHealthTone =
|
|
76
|
+
down > 0 ? "down" : degraded > 0 ? "degraded" : up > 0 ? "up" : "neutral";
|
|
77
|
+
return {
|
|
78
|
+
total: monitors.length,
|
|
79
|
+
up,
|
|
80
|
+
down,
|
|
81
|
+
degraded,
|
|
82
|
+
pending,
|
|
83
|
+
overallUptimePct,
|
|
84
|
+
openIncidents: down + degraded,
|
|
85
|
+
overall,
|
|
86
|
+
};
|
|
87
|
+
}
|