@agent-native/core 0.69.0 → 0.70.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/README.md +15 -15
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +109 -0
- package/corpus/core/docs/design/durable-agent-runs.md +217 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/action.ts +89 -0
- package/corpus/core/src/agent/model-config.ts +0 -2
- package/corpus/core/src/agent/run-loop-with-resume.ts +48 -0
- package/corpus/core/src/changelog/parse.ts +245 -0
- package/corpus/core/src/cli/changelog.ts +199 -0
- package/corpus/core/src/cli/index.ts +19 -0
- package/corpus/core/src/cli/recap.ts +24 -1
- package/corpus/core/src/cli/skills.ts +74 -47
- package/corpus/core/src/client/AgentPanel.tsx +5 -3
- package/corpus/core/src/client/AssistantChat.tsx +8 -0
- package/corpus/core/src/client/CommandMenu.tsx +183 -75
- package/corpus/core/src/client/agent-chat-adapter.ts +44 -7
- package/corpus/core/src/client/analytics.ts +181 -0
- package/corpus/core/src/client/changelog/Changelog.tsx +321 -0
- package/corpus/core/src/client/client-surface.ts +41 -0
- package/corpus/core/src/client/composer/TiptapComposer.tsx +123 -12
- package/corpus/core/src/client/feedback-context.ts +4 -0
- package/corpus/core/src/client/index.ts +12 -0
- package/corpus/core/src/client/mcp-apps/McpAppRenderer.tsx +54 -0
- package/corpus/core/src/client/settings/useBuilderStatus.ts +82 -20
- package/corpus/core/src/client/sse-event-processor.ts +7 -1
- package/corpus/core/src/mcp/build-server.ts +57 -1
- package/corpus/core/src/mcp/embed-app.ts +197 -7
- package/corpus/core/src/mcp/oauth-route.ts +109 -13
- package/corpus/core/src/server/attribution.ts +211 -0
- package/corpus/core/src/server/auth.ts +6 -0
- package/corpus/core/src/server/better-auth-instance.ts +49 -5
- package/corpus/core/src/server/builder-browser.ts +27 -1
- package/corpus/core/src/server/core-routes-plugin.ts +136 -0
- package/corpus/core/src/server/google-oauth.ts +19 -6
- package/corpus/core/src/server/onboarding-html.ts +35 -0
- package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
- package/corpus/core/src/styles/agent-conversation.css +21 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/reliable-mutations/SKILL.md +72 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +22 -0
- package/corpus/templates/analytics/AGENTS.md +8 -1
- package/corpus/templates/analytics/CHANGELOG.md +10 -0
- package/corpus/templates/analytics/actions/install-dashboard-template.ts +99 -4
- package/corpus/templates/analytics/actions/open-traffic-dashboard.ts +1 -1
- package/corpus/templates/analytics/actions/update-dashboard.ts +39 -8
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +30 -3
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +180 -144
- package/corpus/templates/analytics/app/components/layout/Header.tsx +2 -3
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -5
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +221 -215
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +6 -6
- package/corpus/templates/analytics/app/lib/demo-dashboard-path.ts +1 -1
- package/corpus/templates/analytics/app/lib/last-opened.ts +2 -1
- package/corpus/templates/analytics/app/pages/Settings.tsx +4 -0
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +2 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +32 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +101 -99
- package/corpus/templates/analytics/app/pages/overview/OverviewPage.tsx +1 -1
- package/corpus/templates/analytics/app/routes/adhoc.$id.tsx +18 -5
- package/corpus/templates/analytics/app/routes/catalog.tsx +1 -1
- package/corpus/templates/analytics/app/routes/dashboards.$id.tsx +9 -0
- package/corpus/templates/analytics/app/routes/traffic.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-06-23-long-dashboard-and-analysis-names-in-the-sidebar-now-truncat.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-23-open-any-dashboard-chart-full-screen-in-a-modal-from-the-pan.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-23-the-dashboards-and-analyses-sidebar-settings-buttons-now-sta.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +145 -0
- package/corpus/templates/analytics/server/db/index.ts +1 -1
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +9 -2
- package/corpus/templates/analytics/server/lib/demo-dashboards.ts +1 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +2 -2
- package/corpus/templates/analytics/server/plugins/core-routes.ts +6 -6
- package/corpus/templates/assets/CHANGELOG.md +10 -0
- package/corpus/templates/assets/actions/generate-image.ts +24 -0
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/assets/app/global.css +17 -1
- package/corpus/templates/assets/app/root.tsx +7 -1
- package/corpus/templates/assets/app/routes/_index.tsx +94 -14
- package/corpus/templates/assets/app/routes/settings.tsx +6 -0
- package/corpus/templates/assets/changelog/2026-06-23-chat-dates-in-the-sidebar-no-longer-wrap-onto-two-lines.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-23-clicking-image-video-or-refine-on-the-start-screen-now-drops.md +6 -0
- package/corpus/templates/assets/changelog/2026-06-23-pick-your-image-generation-model-right-from-the-chat-model-m.md +6 -0
- package/corpus/templates/brain/CHANGELOG.md +10 -0
- package/corpus/templates/brain/app/root.tsx +7 -1
- package/corpus/templates/brain/app/routes/settings.tsx +8 -1
- package/corpus/templates/calendar/CHANGELOG.md +10 -0
- package/corpus/templates/calendar/app/pages/Settings.tsx +4 -0
- package/corpus/templates/calendar/app/root.tsx +7 -1
- package/corpus/templates/chat/CHANGELOG.md +10 -0
- package/corpus/templates/chat/app/root.tsx +7 -1
- package/corpus/templates/clips/CHANGELOG.md +10 -0
- package/corpus/templates/clips/app/components/library/library-grid.tsx +1 -20
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +33 -7
- package/corpus/templates/clips/app/components/player/sign-in-prompt-dialog.tsx +8 -0
- package/corpus/templates/clips/app/components/player/video-player.tsx +150 -20
- package/corpus/templates/clips/app/components/recorder/countdown-overlay.tsx +72 -48
- package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +7 -11
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +31 -0
- package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +71 -0
- package/corpus/templates/clips/app/lib/countdown-audio-cue.ts +35 -17
- package/corpus/templates/clips/app/root.tsx +7 -1
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +15 -1
- package/corpus/templates/clips/app/routes/record.tsx +78 -5
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +86 -5
- package/corpus/templates/clips/changelog/2026-06-23-clips-shared-in-slack-no-longer-show-a-could-not-start-playb.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-made-the-play-button-on-shared-and-embedded-clips-scale-with.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-public-clip-share-links-now-show-whether-they-ll-play-inline.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-removed-select-button-from-library-hover-a-clip-to-select-it.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-screen-camera-recordings-now-keep-the-presenter-s-face-in-th.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-shared-video-links-now-play-for-anyone-without-signing-in.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-skip-or-cancel-the-recording-countdown-with-buttons-beside-t.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-the-desktop-camera-bubble-now-looks-sharp-the-instant-it-ope.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-the-desktop-recording-widget-now-grows-downward-only-when-yo.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-23-the-recording-start-sound-is-now-a-softer-more-modern-chime.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +17 -8
- package/corpus/templates/clips/chrome-extension/src/background.ts +769 -180
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +177 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +466 -329
- package/corpus/templates/clips/chrome-extension/src/overlay.css +377 -0
- package/corpus/templates/clips/chrome-extension/src/overlay.html +12 -0
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +330 -0
- package/corpus/templates/clips/chrome-extension/src/permission.html +227 -0
- package/corpus/templates/clips/chrome-extension/src/permission.ts +105 -0
- package/corpus/templates/clips/chrome-extension/src/popup.html +3 -0
- package/corpus/templates/clips/chrome-extension/src/popup.ts +50 -2
- package/corpus/templates/clips/chrome-extension/src/styles.css +50 -0
- package/corpus/templates/clips/chrome-extension/vite.config.ts +3 -0
- package/corpus/templates/clips/desktop/src/lib/audio-cue.ts +41 -24
- package/corpus/templates/clips/desktop/src/lib/bubble-webrtc.ts +119 -2
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +20 -0
- package/corpus/templates/clips/desktop/src/main.tsx +3 -0
- package/corpus/templates/clips/desktop/src/overlays/countdown.tsx +21 -2
- package/corpus/templates/clips/desktop/src/overlays/region-record-border.tsx +76 -0
- package/corpus/templates/clips/desktop/src/styles.css +119 -2
- package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +2 -1
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +140 -1
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +4 -1
- package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +85 -6
- package/corpus/templates/clips/shared/share-attribution.ts +79 -0
- package/corpus/templates/content/AGENTS.md +20 -3
- package/corpus/templates/content/CHANGELOG.md +10 -0
- package/corpus/templates/content/actions/_database-utils.ts +15 -0
- package/corpus/templates/content/actions/_property-utils.ts +371 -4
- package/corpus/templates/content/actions/configure-document-property.ts +35 -1
- package/corpus/templates/content/actions/create-content-database.ts +5 -1
- package/corpus/templates/content/actions/delete-document-property.ts +52 -2
- package/corpus/templates/content/actions/duplicate-document-property.ts +34 -17
- package/corpus/templates/content/actions/reorder-document-property.ts +79 -0
- package/corpus/templates/content/actions/set-document-property.ts +39 -0
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +806 -0
- package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +226 -68
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +59 -30
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +25 -1
- package/corpus/templates/content/app/components/editor/blockFieldSaveController.ts +180 -0
- package/corpus/templates/content/app/components/editor/blockFieldSaveRegistry.ts +179 -0
- package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +244 -0
- package/corpus/templates/content/app/components/editor/previewDocumentSaveRegistry.ts +132 -0
- package/corpus/templates/content/app/global.css +9 -0
- package/corpus/templates/content/app/hooks/use-document-properties.ts +21 -0
- package/corpus/templates/content/app/root.tsx +7 -1
- package/corpus/templates/content/server/db/schema.ts +30 -0
- package/corpus/templates/content/server/plugins/db.ts +87 -0
- package/corpus/templates/content/shared/api.ts +7 -0
- package/corpus/templates/content/shared/properties.ts +109 -0
- package/corpus/templates/design/CHANGELOG.md +10 -0
- package/corpus/templates/design/actions/generate-design.ts +4 -0
- package/corpus/templates/design/app/root.tsx +7 -1
- package/corpus/templates/design/app/routes/settings.tsx +10 -2
- package/corpus/templates/dispatch/CHANGELOG.md +10 -0
- package/corpus/templates/dispatch/app/root.tsx +7 -1
- package/corpus/templates/forms/.agents/skills/form-responses/SKILL.md +10 -0
- package/corpus/templates/forms/CHANGELOG.md +10 -0
- package/corpus/templates/forms/actions/export-responses.ts +6 -0
- package/corpus/templates/forms/actions/list-responses.ts +2 -0
- package/corpus/templates/forms/actions/response-insights.ts +2 -0
- package/corpus/templates/forms/app/pages/ResponsesPage.tsx +138 -1
- package/corpus/templates/forms/app/root.tsx +7 -1
- package/corpus/templates/forms/changelog/2026-06-23-response-tables-now-show-the-page-each-submission-came-from-.md +6 -0
- package/corpus/templates/forms/changelog/2026-06-23-response-tables-now-show-whether-feedback-came-from-the-web-.md +6 -0
- package/corpus/templates/forms/server/db/schema.ts +7 -0
- package/corpus/templates/forms/server/handlers/submissions.ts +19 -2
- package/corpus/templates/forms/server/lib/integrations.ts +76 -2
- package/corpus/templates/forms/server/plugins/db.ts +20 -0
- package/corpus/templates/forms/shared/types.ts +12 -0
- package/corpus/templates/macros/CHANGELOG.md +10 -0
- package/corpus/templates/macros/app/root.tsx +7 -1
- package/corpus/templates/mail/CHANGELOG.md +10 -0
- package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +3 -0
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +27 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +31 -17
- package/corpus/templates/plan/.agents/skills/visual-plan/references/wireframe.md +7 -4
- package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +34 -24
- package/corpus/templates/plan/.agents/skills/visual-recap/references/wireframe.md +7 -4
- package/corpus/templates/plan/AGENTS.md +4 -0
- package/corpus/templates/plan/CHANGELOG.md +10 -0
- package/corpus/templates/plan/actions/view-screen.ts +5 -0
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +98 -1
- package/corpus/templates/plan/app/components/plan/wireframe/html-artboard.css +3 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +107 -7
- package/corpus/templates/plan/app/root.tsx +7 -1
- package/corpus/templates/plan/changelog/2026-06-23-large-diagrams-in-a-plan-now-scroll-within-their-block-inste.md +6 -0
- package/corpus/templates/plan/shared/share-attribution.ts +72 -0
- package/corpus/templates/slides/CHANGELOG.md +10 -0
- package/corpus/templates/slides/app/root.tsx +7 -1
- package/corpus/templates/videos/CHANGELOG.md +4 -151
- package/corpus/templates/videos/app/root.tsx +7 -1
- package/dist/action.js +87 -0
- package/dist/action.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/model-config.d.ts +2 -2
- package/dist/agent/model-config.d.ts.map +1 -1
- package/dist/agent/model-config.js +0 -2
- package/dist/agent/model-config.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts +13 -0
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +44 -0
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/changelog/parse.d.ts +70 -0
- package/dist/changelog/parse.d.ts.map +1 -0
- package/dist/changelog/parse.js +200 -0
- package/dist/changelog/parse.js.map +1 -0
- package/dist/cli/changelog.d.ts +4 -0
- package/dist/cli/changelog.d.ts.map +1 -0
- package/dist/cli/changelog.js +166 -0
- package/dist/cli/changelog.js.map +1 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +22 -1
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +3 -3
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +74 -47
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +5 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +6 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +2 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/CommandMenu.d.ts +17 -1
- package/dist/client/CommandMenu.d.ts.map +1 -1
- package/dist/client/CommandMenu.js +49 -13
- package/dist/client/CommandMenu.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +43 -6
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/analytics.d.ts +18 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +177 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/changelog/Changelog.d.ts +47 -0
- package/dist/client/changelog/Changelog.d.ts.map +1 -0
- package/dist/client/changelog/Changelog.js +138 -0
- package/dist/client/changelog/Changelog.js.map +1 -0
- package/dist/client/client-surface.d.ts +17 -0
- package/dist/client/client-surface.d.ts.map +1 -0
- package/dist/client/client-surface.js +24 -0
- package/dist/client/client-surface.js.map +1 -0
- package/dist/client/composer/TiptapComposer.d.ts +26 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +27 -5
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/feedback-context.d.ts +3 -0
- package/dist/client/feedback-context.d.ts.map +1 -1
- package/dist/client/feedback-context.js +2 -0
- package/dist/client/feedback-context.js.map +1 -1
- package/dist/client/index.d.ts +3 -1
- 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/mcp-apps/McpAppRenderer.d.ts +1 -0
- package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.js +42 -1
- package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +2 -0
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +58 -10
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +7 -1
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/mcp/build-server.d.ts +21 -0
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +43 -1
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/embed-app.d.ts.map +1 -1
- package/dist/mcp/embed-app.js +197 -7
- package/dist/mcp/embed-app.js.map +1 -1
- package/dist/mcp/oauth-route.d.ts.map +1 -1
- package/dist/mcp/oauth-route.js +95 -12
- package/dist/mcp/oauth-route.js.map +1 -1
- package/dist/server/attribution.d.ts +83 -0
- package/dist/server/attribution.d.ts.map +1 -0
- package/dist/server/attribution.js +178 -0
- package/dist/server/attribution.js.map +1 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +7 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts +9 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +32 -2
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/builder-browser.d.ts +4 -0
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +20 -1
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +25 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +101 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +16 -2
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +35 -0
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/shared/mcp-embed-headers.js +1 -1
- package/dist/shared/mcp-embed-headers.js.map +1 -1
- package/dist/styles/agent-conversation.css +21 -0
- package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
- package/dist/templates/workspace-core/.agents/skills/reliable-mutations/SKILL.md +72 -0
- package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
- package/docs/design/durable-agent-runs.md +217 -0
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
- package/src/templates/workspace-core/.agents/skills/reliable-mutations/SKILL.md +72 -0
- package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
- package/corpus/templates/analytics/app/pages/About.tsx +0 -108
- package/corpus/templates/analytics/app/routes/about.tsx +0 -9
- /package/corpus/templates/analytics/app/routes/{dashboards.tsx → dashboards._index.tsx} +0 -0
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
IconArrowsMaximize,
|
|
6
6
|
IconArrowsMinimize,
|
|
7
7
|
IconDotsVertical,
|
|
8
|
+
IconMaximize,
|
|
8
9
|
IconPencil,
|
|
9
10
|
IconTrash,
|
|
10
11
|
IconCode,
|
|
@@ -32,9 +33,15 @@ import {
|
|
|
32
33
|
AlertDialogHeader,
|
|
33
34
|
AlertDialogTitle,
|
|
34
35
|
} from "@/components/ui/alert-dialog";
|
|
36
|
+
import {
|
|
37
|
+
Dialog,
|
|
38
|
+
DialogContent,
|
|
39
|
+
DialogHeader,
|
|
40
|
+
DialogTitle,
|
|
41
|
+
} from "@/components/ui/dialog";
|
|
35
42
|
import { useSortable } from "@dnd-kit/sortable";
|
|
36
43
|
import { CSS } from "@dnd-kit/utilities";
|
|
37
|
-
import { SqlChart } from "@/components/dashboard/SqlChart";
|
|
44
|
+
import { ChartFillHeight, SqlChart } from "@/components/dashboard/SqlChart";
|
|
38
45
|
import { ViewSqlPopover } from "./ViewSqlPopover";
|
|
39
46
|
import type { SqlPanel } from "./types";
|
|
40
47
|
|
|
@@ -76,6 +83,7 @@ export function SqlChartCard({
|
|
|
76
83
|
} = useSortable({ id: panel.id, disabled: !editable });
|
|
77
84
|
|
|
78
85
|
const [confirmOpen, setConfirmOpen] = useState(false);
|
|
86
|
+
const [expanded, setExpanded] = useState(false);
|
|
79
87
|
const [exportCsv, setExportCsv] = useState<(() => void) | null>(null);
|
|
80
88
|
const [shouldLoadData, setShouldLoadData] = useState(
|
|
81
89
|
panel.chartType === "section",
|
|
@@ -229,7 +237,9 @@ export function SqlChartCard({
|
|
|
229
237
|
);
|
|
230
238
|
}
|
|
231
239
|
|
|
232
|
-
|
|
240
|
+
// Every non-section panel exposes at least the Full screen view action, so the
|
|
241
|
+
// options menu always renders — including on read-only / shared dashboards.
|
|
242
|
+
const showPanelMenu = true;
|
|
233
243
|
|
|
234
244
|
return (
|
|
235
245
|
<div
|
|
@@ -259,6 +269,13 @@ export function SqlChartCard({
|
|
|
259
269
|
<TooltipContent>Panel options</TooltipContent>
|
|
260
270
|
</Tooltip>
|
|
261
271
|
<DropdownMenuContent align="end" className="w-44">
|
|
272
|
+
<DropdownMenuItem onSelect={() => setExpanded(true)}>
|
|
273
|
+
<IconMaximize className="h-4 w-4 mr-2" />
|
|
274
|
+
Full screen
|
|
275
|
+
</DropdownMenuItem>
|
|
276
|
+
{editable || panel.chartType === "table" ? (
|
|
277
|
+
<DropdownMenuSeparator />
|
|
278
|
+
) : null}
|
|
262
279
|
{panel.chartType === "table" && (
|
|
263
280
|
<DropdownMenuItem
|
|
264
281
|
disabled={!exportCsv}
|
|
@@ -346,6 +363,19 @@ export function SqlChartCard({
|
|
|
346
363
|
</CardContent>
|
|
347
364
|
</Card>
|
|
348
365
|
|
|
366
|
+
<Dialog open={expanded} onOpenChange={setExpanded}>
|
|
367
|
+
<DialogContent className="flex h-[90vh] w-[95vw] max-w-[1400px] flex-col gap-4">
|
|
368
|
+
<DialogHeader className="shrink-0 pr-8 text-left">
|
|
369
|
+
<DialogTitle className="truncate">{panel.title}</DialogTitle>
|
|
370
|
+
</DialogHeader>
|
|
371
|
+
<div className="flex min-h-0 flex-1 flex-col overflow-auto">
|
|
372
|
+
<ChartFillHeight>
|
|
373
|
+
<SqlChart panel={panel} resolvedSql={resolvedSql} loadData />
|
|
374
|
+
</ChartFillHeight>
|
|
375
|
+
</div>
|
|
376
|
+
</DialogContent>
|
|
377
|
+
</Dialog>
|
|
378
|
+
|
|
349
379
|
{editable ? (
|
|
350
380
|
<AlertDialog open={confirmOpen} onOpenChange={setConfirmOpen}>
|
|
351
381
|
<AlertDialogContent>
|
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
DropdownMenu,
|
|
49
49
|
DropdownMenuContent,
|
|
50
50
|
DropdownMenuItem,
|
|
51
|
+
DropdownMenuLabel,
|
|
51
52
|
DropdownMenuSeparator,
|
|
52
53
|
DropdownMenuTrigger,
|
|
53
54
|
} from "@/components/ui/dropdown-menu";
|
|
@@ -995,53 +996,107 @@ export default function SqlDashboardPage() {
|
|
|
995
996
|
</Button>
|
|
996
997
|
</AddPanelPopover>
|
|
997
998
|
) : null}
|
|
998
|
-
|
|
999
|
-
<
|
|
1000
|
-
<
|
|
1001
|
-
<
|
|
1002
|
-
<
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
aria-label="Dashboard actions"
|
|
1008
|
-
>
|
|
1009
|
-
<IconDots className="h-4 w-4" />
|
|
1010
|
-
</Button>
|
|
1011
|
-
</DropdownMenuTrigger>
|
|
1012
|
-
</TooltipTrigger>
|
|
1013
|
-
<TooltipContent>More actions</TooltipContent>
|
|
1014
|
-
</Tooltip>
|
|
1015
|
-
<DropdownMenuContent align="end" className="w-44">
|
|
1016
|
-
{canEdit && !archivedAt ? (
|
|
1017
|
-
<DropdownMenuItem
|
|
1018
|
-
onSelect={(event) => {
|
|
1019
|
-
event.preventDefault();
|
|
1020
|
-
void handleArchive();
|
|
1021
|
-
}}
|
|
1022
|
-
>
|
|
1023
|
-
<IconArchive className="mr-2 h-3.5 w-3.5" />
|
|
1024
|
-
Archive
|
|
1025
|
-
</DropdownMenuItem>
|
|
1026
|
-
) : null}
|
|
1027
|
-
{canEdit && !archivedAt && canManage ? (
|
|
1028
|
-
<DropdownMenuSeparator />
|
|
1029
|
-
) : null}
|
|
1030
|
-
{canManage ? (
|
|
1031
|
-
<DropdownMenuItem
|
|
1032
|
-
onSelect={(event) => {
|
|
1033
|
-
event.preventDefault();
|
|
1034
|
-
setConfirmDeleteOpen(true);
|
|
1035
|
-
}}
|
|
1036
|
-
className="text-destructive focus:text-destructive"
|
|
999
|
+
<DropdownMenu>
|
|
1000
|
+
<Tooltip>
|
|
1001
|
+
<TooltipTrigger asChild>
|
|
1002
|
+
<DropdownMenuTrigger asChild>
|
|
1003
|
+
<Button
|
|
1004
|
+
size="sm"
|
|
1005
|
+
variant="ghost"
|
|
1006
|
+
className="text-muted-foreground hover:text-foreground"
|
|
1007
|
+
aria-label="Dashboard details and actions"
|
|
1037
1008
|
>
|
|
1038
|
-
<
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
</
|
|
1043
|
-
</
|
|
1044
|
-
|
|
1009
|
+
<IconDots className="h-4 w-4" />
|
|
1010
|
+
</Button>
|
|
1011
|
+
</DropdownMenuTrigger>
|
|
1012
|
+
</TooltipTrigger>
|
|
1013
|
+
<TooltipContent>Details</TooltipContent>
|
|
1014
|
+
</Tooltip>
|
|
1015
|
+
<DropdownMenuContent align="end" className="w-56">
|
|
1016
|
+
<DropdownMenuLabel className="font-normal">
|
|
1017
|
+
<div className="flex flex-col gap-1.5 text-xs text-muted-foreground">
|
|
1018
|
+
{dashboardUpdatedAt && (
|
|
1019
|
+
<span className="flex items-center gap-1.5">
|
|
1020
|
+
<IconClock className="h-3 w-3" />
|
|
1021
|
+
Updated{" "}
|
|
1022
|
+
{new Date(dashboardUpdatedAt).toLocaleDateString("en-US", {
|
|
1023
|
+
year: "numeric",
|
|
1024
|
+
month: "short",
|
|
1025
|
+
day: "numeric",
|
|
1026
|
+
})}
|
|
1027
|
+
</span>
|
|
1028
|
+
)}
|
|
1029
|
+
{dashboardOwner && (
|
|
1030
|
+
<span className="flex items-center gap-1.5">
|
|
1031
|
+
<IconUser className="h-3 w-3" />
|
|
1032
|
+
{dashboardOwner.split("@")[0]}
|
|
1033
|
+
</span>
|
|
1034
|
+
)}
|
|
1035
|
+
{dashboardVisibility ? (
|
|
1036
|
+
<span
|
|
1037
|
+
className={`flex items-center gap-1.5 font-medium ${
|
|
1038
|
+
dashboardVisibility === "public"
|
|
1039
|
+
? "text-green-600"
|
|
1040
|
+
: dashboardVisibility === "org"
|
|
1041
|
+
? "text-blue-600"
|
|
1042
|
+
: "text-yellow-600"
|
|
1043
|
+
}`}
|
|
1044
|
+
>
|
|
1045
|
+
<span
|
|
1046
|
+
className={`h-1.5 w-1.5 rounded-full ${
|
|
1047
|
+
dashboardVisibility === "public"
|
|
1048
|
+
? "bg-green-500"
|
|
1049
|
+
: dashboardVisibility === "org"
|
|
1050
|
+
? "bg-blue-500"
|
|
1051
|
+
: "bg-yellow-500"
|
|
1052
|
+
}`}
|
|
1053
|
+
/>
|
|
1054
|
+
{dashboardVisibility === "public"
|
|
1055
|
+
? "Public"
|
|
1056
|
+
: dashboardVisibility === "org"
|
|
1057
|
+
? "Shared with org"
|
|
1058
|
+
: "Private"}
|
|
1059
|
+
</span>
|
|
1060
|
+
) : null}
|
|
1061
|
+
{hiddenAt && (
|
|
1062
|
+
<span className="flex items-center gap-1.5 font-medium text-amber-600 dark:text-amber-400">
|
|
1063
|
+
<IconEyeOff className="h-3 w-3" />
|
|
1064
|
+
Hidden
|
|
1065
|
+
</span>
|
|
1066
|
+
)}
|
|
1067
|
+
</div>
|
|
1068
|
+
</DropdownMenuLabel>
|
|
1069
|
+
{(canEdit && !archivedAt) || canManage ? (
|
|
1070
|
+
<DropdownMenuSeparator />
|
|
1071
|
+
) : null}
|
|
1072
|
+
{canEdit && !archivedAt ? (
|
|
1073
|
+
<DropdownMenuItem
|
|
1074
|
+
onSelect={(event) => {
|
|
1075
|
+
event.preventDefault();
|
|
1076
|
+
void handleArchive();
|
|
1077
|
+
}}
|
|
1078
|
+
>
|
|
1079
|
+
<IconArchive className="mr-2 h-3.5 w-3.5" />
|
|
1080
|
+
Archive
|
|
1081
|
+
</DropdownMenuItem>
|
|
1082
|
+
) : null}
|
|
1083
|
+
{canEdit && !archivedAt && canManage ? (
|
|
1084
|
+
<DropdownMenuSeparator />
|
|
1085
|
+
) : null}
|
|
1086
|
+
{canManage ? (
|
|
1087
|
+
<DropdownMenuItem
|
|
1088
|
+
onSelect={(event) => {
|
|
1089
|
+
event.preventDefault();
|
|
1090
|
+
setConfirmDeleteOpen(true);
|
|
1091
|
+
}}
|
|
1092
|
+
className="text-destructive focus:text-destructive"
|
|
1093
|
+
>
|
|
1094
|
+
<IconTrash className="mr-2 h-3.5 w-3.5" />
|
|
1095
|
+
Delete permanently
|
|
1096
|
+
</DropdownMenuItem>
|
|
1097
|
+
) : null}
|
|
1098
|
+
</DropdownMenuContent>
|
|
1099
|
+
</DropdownMenu>
|
|
1045
1100
|
{canManage ? (
|
|
1046
1101
|
<AlertDialog
|
|
1047
1102
|
open={confirmDeleteOpen}
|
|
@@ -1152,59 +1207,6 @@ export default function SqlDashboardPage() {
|
|
|
1152
1207
|
</Button>
|
|
1153
1208
|
</Alert>
|
|
1154
1209
|
) : null}
|
|
1155
|
-
{/* Author, last updated, and visibility metadata */}
|
|
1156
|
-
<div className="flex flex-wrap items-center gap-3 text-xs text-muted-foreground">
|
|
1157
|
-
{hiddenAt && (
|
|
1158
|
-
<span className="flex items-center gap-1.5 font-medium text-amber-600 dark:text-amber-400">
|
|
1159
|
-
<IconEyeOff className="h-3 w-3" />
|
|
1160
|
-
Hidden
|
|
1161
|
-
</span>
|
|
1162
|
-
)}
|
|
1163
|
-
{dashboardUpdatedAt && (
|
|
1164
|
-
<span className="flex items-center gap-1">
|
|
1165
|
-
<IconClock className="h-3 w-3" />
|
|
1166
|
-
Updated{" "}
|
|
1167
|
-
{new Date(dashboardUpdatedAt).toLocaleDateString("en-US", {
|
|
1168
|
-
year: "numeric",
|
|
1169
|
-
month: "short",
|
|
1170
|
-
day: "numeric",
|
|
1171
|
-
})}
|
|
1172
|
-
</span>
|
|
1173
|
-
)}
|
|
1174
|
-
{dashboardOwner && (
|
|
1175
|
-
<span className="flex items-center gap-1">
|
|
1176
|
-
<IconUser className="h-3 w-3" />
|
|
1177
|
-
{dashboardOwner.split("@")[0]}
|
|
1178
|
-
</span>
|
|
1179
|
-
)}
|
|
1180
|
-
{dashboardVisibility ? (
|
|
1181
|
-
<span
|
|
1182
|
-
className={`flex items-center gap-1.5 font-medium ${
|
|
1183
|
-
dashboardVisibility === "public"
|
|
1184
|
-
? "text-green-600"
|
|
1185
|
-
: dashboardVisibility === "org"
|
|
1186
|
-
? "text-blue-600"
|
|
1187
|
-
: "text-yellow-600"
|
|
1188
|
-
}`}
|
|
1189
|
-
>
|
|
1190
|
-
<span
|
|
1191
|
-
className={`h-1.5 w-1.5 rounded-full ${
|
|
1192
|
-
dashboardVisibility === "public"
|
|
1193
|
-
? "bg-green-500"
|
|
1194
|
-
: dashboardVisibility === "org"
|
|
1195
|
-
? "bg-blue-500"
|
|
1196
|
-
: "bg-yellow-500"
|
|
1197
|
-
}`}
|
|
1198
|
-
/>
|
|
1199
|
-
{dashboardVisibility === "public"
|
|
1200
|
-
? "Public"
|
|
1201
|
-
: dashboardVisibility === "org"
|
|
1202
|
-
? "Shared with org"
|
|
1203
|
-
: "Private"}
|
|
1204
|
-
</span>
|
|
1205
|
-
) : null}
|
|
1206
|
-
</div>
|
|
1207
|
-
|
|
1208
1210
|
{/* Description (click to edit) */}
|
|
1209
1211
|
{editingDescription && canEdit ? (
|
|
1210
1212
|
<Textarea
|
|
@@ -1,9 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { redirect, type LoaderFunctionArgs } from "react-router";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
// `/adhoc/:id` is the legacy dashboard URL. The canonical, user-facing URL is
|
|
4
|
+
// now `/dashboards/:id`. Forward old links (bookmarks, deep links, query
|
|
5
|
+
// params like `?id=` and `?config=`) to the canonical path so nothing breaks.
|
|
6
|
+
function target({ request, params }: LoaderFunctionArgs): string {
|
|
7
|
+
const url = new URL(request.url);
|
|
8
|
+
const id = params.id ?? "";
|
|
9
|
+
return `/dashboards/${encodeURIComponent(id)}${url.search}${url.hash}`;
|
|
5
10
|
}
|
|
6
11
|
|
|
7
|
-
export
|
|
8
|
-
|
|
12
|
+
export function loader(args: LoaderFunctionArgs) {
|
|
13
|
+
throw redirect(target(args));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function clientLoader(args: LoaderFunctionArgs) {
|
|
17
|
+
throw redirect(target(args));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function AdhocRedirectRoute() {
|
|
21
|
+
return null;
|
|
9
22
|
}
|
|
@@ -76,7 +76,7 @@ function dashboardPathForTemplate(
|
|
|
76
76
|
if (template.id === "demo-node-exporter") {
|
|
77
77
|
return demoNodeExporterDashboardPath(dashboardId, options);
|
|
78
78
|
}
|
|
79
|
-
return `/
|
|
79
|
+
return `/dashboards/${dashboardId}`;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
function sourceLabel(source: string): string {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { redirect, type LoaderFunctionArgs } from "react-router";
|
|
2
2
|
|
|
3
|
-
const TRAFFIC_DASHBOARD_PATH = "/
|
|
3
|
+
const TRAFFIC_DASHBOARD_PATH = "/dashboards/agent-native-templates-first-party";
|
|
4
4
|
|
|
5
5
|
function target(request: Request): string {
|
|
6
6
|
const url = new URL(request.url);
|
|
@@ -187,6 +187,151 @@
|
|
|
187
187
|
"yKey": "count",
|
|
188
188
|
"color": "#10b981"
|
|
189
189
|
}
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "virality-referrals-section",
|
|
193
|
+
"title": "Virality & Referrals",
|
|
194
|
+
"chartType": "section",
|
|
195
|
+
"width": 1,
|
|
196
|
+
"columns": 3,
|
|
197
|
+
"config": {
|
|
198
|
+
"description": "Signups attributed to shared clips and plans, who is driving referrals, and the share view to click to signup funnel. referral_* and utm_* fields are read from the signup event's properties JSON; share_view and share_cta_click track shared-surface engagement."
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"id": "referred-signups-30d",
|
|
203
|
+
"title": "Referred Signups (30d)",
|
|
204
|
+
"chartType": "metric",
|
|
205
|
+
"source": "first-party",
|
|
206
|
+
"width": 1,
|
|
207
|
+
"sql": "SELECT COUNT(*) AS count FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '30 days' AND properties::jsonb ->> 'referral_source' IS NOT NULL AND properties::jsonb ->> 'referral_source' <> '' AND properties::jsonb ->> 'referral_source' <> 'direct'",
|
|
208
|
+
"config": {
|
|
209
|
+
"yKey": "count",
|
|
210
|
+
"yFormatter": "number",
|
|
211
|
+
"description": "Signups in the last 30 days with a non-direct referral_source (clip_share, plan_share, external)."
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"id": "viral-signup-share-30d",
|
|
216
|
+
"title": "Viral Signup Share (30d)",
|
|
217
|
+
"chartType": "metric",
|
|
218
|
+
"source": "first-party",
|
|
219
|
+
"width": 1,
|
|
220
|
+
"sql": "SELECT CASE WHEN COUNT(*) = 0 THEN 0 ELSE 1.0 * COUNT(*) FILTER (WHERE properties::jsonb ->> 'referral_source' IS NOT NULL AND properties::jsonb ->> 'referral_source' <> '' AND properties::jsonb ->> 'referral_source' <> 'direct') / COUNT(*) END AS rate FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '30 days'",
|
|
221
|
+
"config": {
|
|
222
|
+
"yKey": "rate",
|
|
223
|
+
"yFormatter": "percent",
|
|
224
|
+
"description": "Headline virality number: referred signups divided by all signups over the last 30 days."
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"id": "clip-share-signups-30d",
|
|
229
|
+
"title": "Clip-Share Signups (30d)",
|
|
230
|
+
"chartType": "metric",
|
|
231
|
+
"source": "first-party",
|
|
232
|
+
"width": 1,
|
|
233
|
+
"sql": "SELECT COUNT(*) AS count FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '30 days' AND properties::jsonb ->> 'referral_source' = 'clip_share'",
|
|
234
|
+
"config": {
|
|
235
|
+
"yKey": "count",
|
|
236
|
+
"yFormatter": "number",
|
|
237
|
+
"description": "Signups in the last 30 days attributed to a shared clip."
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"id": "signups-by-referral-source",
|
|
242
|
+
"title": "Signups by Referral Source (90d)",
|
|
243
|
+
"chartType": "bar",
|
|
244
|
+
"source": "first-party",
|
|
245
|
+
"width": 1,
|
|
246
|
+
"sql": "SELECT COALESCE(NULLIF(properties::jsonb ->> 'referral_source', ''), 'direct') AS referral_source, COUNT(*) AS count FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '90 days' GROUP BY COALESCE(NULLIF(properties::jsonb ->> 'referral_source', ''), 'direct') ORDER BY count DESC LIMIT 20",
|
|
247
|
+
"config": {
|
|
248
|
+
"xKey": "referral_source",
|
|
249
|
+
"yKey": "count",
|
|
250
|
+
"color": "var(--brand-purple)",
|
|
251
|
+
"description": "Signups grouped by referral_source over the last 90 days. Null/empty sources are bucketed as direct."
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"id": "referred-signups-over-time",
|
|
256
|
+
"title": "Referred Signups Over Time (90d)",
|
|
257
|
+
"chartType": "area",
|
|
258
|
+
"source": "first-party",
|
|
259
|
+
"width": 2,
|
|
260
|
+
"sql": "SELECT substr(timestamp, 1, 10) AS date, COUNT(*) AS count FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '90 days' AND properties::jsonb ->> 'referral_source' IS NOT NULL AND properties::jsonb ->> 'referral_source' <> '' AND properties::jsonb ->> 'referral_source' <> 'direct' GROUP BY substr(timestamp, 1, 10) ORDER BY date",
|
|
261
|
+
"config": {
|
|
262
|
+
"xKey": "date",
|
|
263
|
+
"yKey": "count",
|
|
264
|
+
"color": "var(--brand-purple)",
|
|
265
|
+
"description": "Daily referred (non-direct) signups over the last 90 days."
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
"id": "top-referrers",
|
|
270
|
+
"title": "Top Referrers (90d)",
|
|
271
|
+
"chartType": "table",
|
|
272
|
+
"source": "first-party",
|
|
273
|
+
"width": 1,
|
|
274
|
+
"sql": "SELECT properties::jsonb ->> 'referrer_user' AS referrer_user, COUNT(*) AS signups FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '90 days' AND properties::jsonb ->> 'referrer_user' IS NOT NULL AND properties::jsonb ->> 'referrer_user' <> '' GROUP BY properties::jsonb ->> 'referrer_user' ORDER BY signups DESC LIMIT 20",
|
|
275
|
+
"config": {
|
|
276
|
+
"description": "Users (by id) driving the most referred signups over the last 90 days.",
|
|
277
|
+
"columns": [
|
|
278
|
+
{ "key": "referrer_user", "label": "Referrer (user id)" },
|
|
279
|
+
{ "key": "signups", "label": "Signups", "format": "number" }
|
|
280
|
+
]
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"id": "share-funnel-30d",
|
|
285
|
+
"title": "Share Funnel (30d)",
|
|
286
|
+
"chartType": "bar",
|
|
287
|
+
"source": "first-party",
|
|
288
|
+
"width": 2,
|
|
289
|
+
"sql": "SELECT 'Share views' AS stage, COUNT(*) AS count FROM analytics_events WHERE event_name = 'share_view' AND timestamp::timestamptz >= now() - interval '30 days' UNION ALL SELECT 'CTA clicks' AS stage, COUNT(*) AS count FROM analytics_events WHERE event_name = 'share_cta_click' AND timestamp::timestamptz >= now() - interval '30 days' UNION ALL SELECT 'Clip-share signups' AS stage, COUNT(*) AS count FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '30 days' AND properties::jsonb ->> 'referral_source' = 'clip_share'",
|
|
290
|
+
"config": {
|
|
291
|
+
"xKey": "stage",
|
|
292
|
+
"yKey": "count",
|
|
293
|
+
"color": "var(--brand-teal)",
|
|
294
|
+
"description": "View to click to signup funnel for shared surfaces over the last 30 days: share_view, share_cta_click, then clip_share signups."
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"id": "viral-participation-rate-90d",
|
|
299
|
+
"title": "Viral Participation Rate (90d)",
|
|
300
|
+
"chartType": "metric",
|
|
301
|
+
"source": "first-party",
|
|
302
|
+
"width": 1,
|
|
303
|
+
"sql": "SELECT COALESCE(COUNT(*) FILTER (WHERE recent.auth_user_id IN (SELECT properties::jsonb ->> 'referrer_user' FROM analytics_events WHERE event_name = 'signup' AND properties::jsonb ->> 'referrer_user' IS NOT NULL AND properties::jsonb ->> 'referrer_user' <> ''))::float / NULLIF(COUNT(*), 0), 0) AS rate FROM (SELECT DISTINCT properties::jsonb ->> 'auth_user_id' AS auth_user_id FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '90 days' AND properties::jsonb ->> 'auth_user_id' IS NOT NULL AND properties::jsonb ->> 'auth_user_id' <> '') AS recent",
|
|
304
|
+
"config": {
|
|
305
|
+
"yKey": "rate",
|
|
306
|
+
"yFormatter": "percent",
|
|
307
|
+
"description": "Share of users who signed up in the last 90d who have since referred at least one new signup (referrers counted across all time). New cohorts under-count: recent signups haven't had time to refer yet. Matches auth_user_id to referrer_user (both better-auth ids)."
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"id": "viral-coefficient-90d",
|
|
312
|
+
"title": "Viral Coefficient K (90d)",
|
|
313
|
+
"chartType": "metric",
|
|
314
|
+
"source": "first-party",
|
|
315
|
+
"width": 1,
|
|
316
|
+
"sql": "SELECT COALESCE(COUNT(*) FILTER (WHERE properties::jsonb ->> 'referrer_user' IS NOT NULL AND properties::jsonb ->> 'referrer_user' <> '')::float / NULLIF(COUNT(DISTINCT properties::jsonb ->> 'auth_user_id'), 0), 0) AS k FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '90 days'",
|
|
317
|
+
"config": {
|
|
318
|
+
"yKey": "k",
|
|
319
|
+
"yFormatter": "number",
|
|
320
|
+
"description": "Viral coefficient (K): referred signups divided by new users over the last 90d. K >= 1 means each user brings on at least one more, i.e. self-sustaining growth."
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"id": "activated-referrers-90d",
|
|
325
|
+
"title": "Activated Referrers (90d)",
|
|
326
|
+
"chartType": "metric",
|
|
327
|
+
"source": "first-party",
|
|
328
|
+
"width": 1,
|
|
329
|
+
"sql": "SELECT COUNT(DISTINCT properties::jsonb ->> 'referrer_user') AS count FROM analytics_events WHERE event_name = 'signup' AND timestamp::timestamptz >= now() - interval '90 days' AND properties::jsonb ->> 'referrer_user' IS NOT NULL AND properties::jsonb ->> 'referrer_user' <> ''",
|
|
330
|
+
"config": {
|
|
331
|
+
"yKey": "count",
|
|
332
|
+
"yFormatter": "number",
|
|
333
|
+
"description": "Distinct users who drove at least one referred signup in the last 90d (distinct referrer_user on signups in the window)."
|
|
334
|
+
}
|
|
190
335
|
}
|
|
191
336
|
]
|
|
192
337
|
}
|
|
@@ -11,7 +11,7 @@ registerShareableResource({
|
|
|
11
11
|
sharesTable: schema.dashboardShares,
|
|
12
12
|
displayName: "Dashboard",
|
|
13
13
|
titleColumn: "title",
|
|
14
|
-
getResourcePath: (dashboard) => `/
|
|
14
|
+
getResourcePath: (dashboard) => `/dashboards/${dashboard.id}`,
|
|
15
15
|
getDb,
|
|
16
16
|
});
|
|
17
17
|
|
|
@@ -924,8 +924,15 @@ export const dashboardCatalogEntries: DashboardCatalogEntry[] = [
|
|
|
924
924
|
category: "Product",
|
|
925
925
|
defaultDashboardId: "agent-native-templates-first-party",
|
|
926
926
|
dataSources: ["first-party"],
|
|
927
|
-
tags: [
|
|
928
|
-
|
|
927
|
+
tags: [
|
|
928
|
+
"templates",
|
|
929
|
+
"traffic",
|
|
930
|
+
"signups",
|
|
931
|
+
"sessions",
|
|
932
|
+
"referrals",
|
|
933
|
+
"virality",
|
|
934
|
+
],
|
|
935
|
+
panelCount: 25,
|
|
929
936
|
version: CATALOG_VERSION,
|
|
930
937
|
recommended: true,
|
|
931
938
|
buildConfig: () => seedConfig("agent-native-templates-first-party"),
|
|
@@ -60,7 +60,7 @@ function demoDashboardPath(dashboardId: string): string {
|
|
|
60
60
|
const params = new URLSearchParams({
|
|
61
61
|
tab: DEMO_NODE_EXPORTER_DEFAULT_TAB,
|
|
62
62
|
});
|
|
63
|
-
return `/
|
|
63
|
+
return `/dashboards/${dashboardId}?${params.toString()}`;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
function nowIso(): string {
|
|
@@ -240,11 +240,11 @@ export default createAgentChatPlugin({
|
|
|
240
240
|
return filtered.slice(0, 20).map((d) => ({
|
|
241
241
|
id: `dashboard:${d.id}`,
|
|
242
242
|
label: d.name || "Untitled dashboard",
|
|
243
|
-
description: `/
|
|
243
|
+
description: `/dashboards/${d.id}`,
|
|
244
244
|
icon: "deck",
|
|
245
245
|
refType: "dashboard",
|
|
246
246
|
refId: d.id,
|
|
247
|
-
refPath: `/
|
|
247
|
+
refPath: `/dashboards/${d.id}`,
|
|
248
248
|
}));
|
|
249
249
|
} catch (err) {
|
|
250
250
|
console.error("[analytics] Dashboard mention provider failed:", err);
|
|
@@ -3,17 +3,17 @@ import { createCoreRoutesPlugin } from "@agent-native/core/server";
|
|
|
3
3
|
// Land external-agent deep links straight on the real SPA route. Without
|
|
4
4
|
// this, `/_agent-native/open?app=analytics&view=adhoc&dashboardId=…` falls
|
|
5
5
|
// back to `/<view>` = `/adhoc`, which has no matching route (the dashboard
|
|
6
|
-
// route is `
|
|
7
|
-
// Analytics" link produced by `update-dashboard` / `save-analysis` for a
|
|
6
|
+
// route is `dashboards.$id.tsx` → `/dashboards/:id`) and 404s — so an "Open
|
|
7
|
+
// in Analytics" link produced by `update-dashboard` / `save-analysis` for a
|
|
8
8
|
// connected Claude Code / Codex / Cowork never opened the record.
|
|
9
9
|
export default createCoreRoutesPlugin({
|
|
10
10
|
resolveOpenPath: ({ view, params }) => {
|
|
11
|
-
if (params.dashboardId) return `/
|
|
11
|
+
if (params.dashboardId) return `/dashboards/${params.dashboardId}`;
|
|
12
12
|
if (params.analysisId) return `/analyses/${params.analysisId}`;
|
|
13
13
|
if (view === "analyses") return "/analyses";
|
|
14
|
-
// `adhoc`/unknown with no id: there is no bare `/
|
|
15
|
-
// the app root rather than 404 (the polled `navigate` command
|
|
16
|
-
// applies any record focus once the SPA is loaded).
|
|
14
|
+
// `adhoc`/unknown with no id: there is no bare `/dashboards` record route —
|
|
15
|
+
// send to the app root rather than 404 (the polled `navigate` command
|
|
16
|
+
// still applies any record focus once the SPA is loaded).
|
|
17
17
|
if (view === "adhoc") return "/";
|
|
18
18
|
return null;
|
|
19
19
|
},
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable user-facing changes to Assets are documented here. Open it any
|
|
4
|
+
time from the command menu (Cmd+K → "What's new") or from Settings.
|
|
5
|
+
|
|
6
|
+
## 2026-06-23
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- See what's new right inside Assets — a changelog now lives in the command menu (Cmd+K) and in Settings.
|