@agent-native/core 0.141.6 → 0.141.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +3 -14
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +11 -6
- package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +5 -5
- package/corpus/templates/analytics/AGENTS.md +2 -2
- package/corpus/templates/analytics/actions/compose-dashboard.ts +1 -1
- package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +135 -0
- package/corpus/templates/analytics/actions/navigate.ts +1 -1
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +2 -2
- package/corpus/templates/analytics/actions/update-dashboard.ts +0 -1
- package/corpus/templates/analytics/actions/view-screen.ts +0 -20
- package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +5 -5
- package/corpus/templates/analytics/app/i18n-data.ts +2 -90
- package/corpus/templates/analytics/app/pages/Agents.tsx +0 -3
- package/corpus/templates/analytics/app/pages/Settings.tsx +22 -43
- package/corpus/templates/analytics/app/pages/settings/settings-search.ts +23 -20
- package/corpus/templates/analytics/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/analytics/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/analytics/app/routes/team.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-08-05-settings-no-longer-includes-an-unnecessary-about-section.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +1 -1
- package/corpus/templates/analytics/scripts/first-party-analytics-bigquery.sql +104 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -2
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +1058 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +34 -15
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +57 -4
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +1 -3
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +2 -4
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +8 -6
- package/corpus/templates/assets/.agents/skills/library-management/SKILL.md +16 -1
- package/corpus/templates/assets/AGENTS.md +1 -0
- package/corpus/templates/assets/actions/_helpers.ts +12 -0
- package/corpus/templates/assets/actions/generate-image.ts +9 -3
- package/corpus/templates/assets/actions/import-style-from-url.ts +115 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +3 -1
- package/corpus/templates/assets/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/assets/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/assets/app/routes/settings.tsx +5 -0
- package/corpus/templates/assets/app/routes/team.tsx +1 -1
- package/corpus/templates/assets/changelog/2026-08-05-brand-kits-can-import-a-website-s-hydrated-visual-language-a.md +6 -0
- package/corpus/templates/assets/changelog/2026-08-05-generated-images-now-hand-off-embeddable-previews-to-other-w.md +6 -0
- package/corpus/templates/assets/server/lib/generation.ts +58 -0
- package/corpus/templates/assets/shared/api.ts +12 -0
- package/corpus/templates/brain/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/brain/app/routes/team.tsx +1 -1
- package/corpus/templates/brain/app/routes.ts +1 -1
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +3 -1
- package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/calendar/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/chat/app/root.tsx +1 -1
- package/corpus/templates/chat/app/routes/agent.tsx +7 -7
- package/corpus/templates/chat/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/chat/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/chat/app/routes/team.tsx +1 -1
- package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/content/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/content/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/content/e2e/global-setup.ts +1 -1
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -1
- package/corpus/templates/design/actions/analyze-brand-assets.ts +7 -7
- package/corpus/templates/design/actions/import-from-url.ts +6 -5
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +2 -2
- package/corpus/templates/design/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/design/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/design/app/routes/team.tsx +1 -1
- package/corpus/templates/design/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-de.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +1 -1
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/dispatch/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/factory/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/factory/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/factory/app/routes/team.tsx +1 -1
- package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +1 -1
- package/corpus/templates/forms/app/routes/_app.settings.$.tsx +1 -0
- package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/forms/shared/navigation.ts +1 -1
- package/corpus/templates/macros/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/macros/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/macros/app/routes/team.tsx +1 -1
- package/corpus/templates/mail/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/mail/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/plan/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/plan/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/plan/app/routes/team.tsx +1 -1
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +3 -1
- package/corpus/templates/slides/actions/analyze-brand-assets.ts +7 -7
- package/corpus/templates/slides/actions/import-from-url.ts +6 -6
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +3 -0
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +9 -3
- package/corpus/templates/slides/app/context/DeckContext.tsx +71 -20
- package/corpus/templates/slides/app/global.css +6 -0
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +9 -5
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -0
- package/corpus/templates/slides/app/pages/Index.tsx +16 -5
- package/corpus/templates/slides/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/slides/app/routes/settings.$.tsx +1 -0
- package/corpus/templates/slides/app/routes/team.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-08-05-failed-deck-creation-and-reference-uploads-now-recover-clean.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-slides-recover-completed-generation-results-after-a-sync-hic.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-st.md +6 -0
- package/corpus/templates/tasks/app/components/layout/Header.tsx +3 -1
- package/corpus/templates/tasks/app/routes/extensions._index.tsx +1 -1
- package/corpus/templates/tasks/app/routes/settings.$.tsx +1 -0
- package/dist/agent/engine/ai-sdk-engine.js +49 -3
- package/dist/agent/production-agent.d.ts +1 -0
- package/dist/agent/production-agent.js +8 -0
- package/dist/agent/types.d.ts +7 -0
- package/dist/client/agent-chat-adapter.d.ts +1 -1
- package/dist/client/agent-chat-adapter.js +30 -3
- package/dist/client/agent-page/AgentWorkspaceContent.d.ts +1 -1
- package/dist/client/agent-page/AgentWorkspaceContent.js +13 -13
- package/dist/client/chat/run-recovery.js +5 -1
- package/dist/client/embed-auth.js +6 -2
- package/dist/client/error-format.js +12 -0
- package/dist/client/integrations/IntegrationsPanel.js +40 -6
- package/dist/client/org/OrgSwitcher.js +2 -2
- package/dist/client/org/TeamPage.js +92 -72
- package/dist/client/require-session.d.ts +1 -1
- package/dist/client/require-session.js +3 -3
- package/dist/client/resources/use-mcp-servers.d.ts +5 -0
- package/dist/client/resources/use-mcp-servers.js +36 -0
- package/dist/client/settings/AccountSettingsCard.js +40 -35
- package/dist/client/settings/AutomationsSection.js +1 -1
- package/dist/client/settings/DemoModeSection.d.ts +3 -1
- package/dist/client/settings/DemoModeSection.js +4 -1
- package/dist/client/settings/ExtensionsSettingsContent.js +1 -1
- package/dist/client/settings/SchedulingTimezoneField.d.ts +3 -1
- package/dist/client/settings/SchedulingTimezoneField.js +9 -5
- package/dist/client/settings/SettingsPanel.d.ts +4 -1
- package/dist/client/settings/SettingsPanel.js +21 -21
- package/dist/client/settings/SettingsTabsPage.d.ts +2 -2
- package/dist/client/settings/SettingsTabsPage.js +98 -45
- package/dist/client/settings/VoiceTranscriptionSection.js +6 -1
- package/dist/client/settings/useSettingsPanelController.js +47 -8
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/ingestion/website.d.ts +30 -0
- package/dist/localization/default-messages.d.ts +5 -0
- package/dist/localization/default-messages.js +5 -0
- package/dist/mcp-client/oauth-routes.js +1 -1
- package/dist/mcp-client/routes.d.ts +1 -0
- package/dist/mcp-client/routes.js +49 -0
- package/dist/navigation/index.js +16 -5
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/call-agent.js +11 -0
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/auth.js +9 -7
- package/dist/server/identity-sso.js +2 -1
- package/dist/server/onboarding-html.js +57 -34
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.js +1 -1
- package/dist/setup-connections/onboarding.js +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/sign-in-journey.d.ts +5 -2
- package/dist/shared/sign-in-journey.js +10 -4
- package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/dist/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/dist/templates/chat/app/root.tsx +1 -1
- package/dist/templates/chat/app/routes/agent.tsx +7 -7
- package/dist/templates/chat/app/routes/extensions._index.tsx +1 -1
- package/dist/templates/chat/app/routes/settings.$.tsx +1 -0
- package/dist/templates/chat/app/routes/team.tsx +1 -1
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
- package/docs/content/authentication.mdx +4 -5
- package/docs/content/template-analytics-developers.mdx +1 -1
- package/docs/content/template-calendar-developers.mdx +1 -1
- package/docs/content/template-chat-developers.mdx +2 -2
- package/docs/content/template-content-developers.mdx +1 -1
- package/docs/content/template-mail-developers.mdx +1 -1
- package/docs/content/template-plan-developers.mdx +1 -1
- package/docs/content/toolkit-command-navigation.mdx +6 -6
- package/docs/content/toolkit-org-team.mdx +1 -1
- package/docs/content/toolkit-settings.mdx +8 -8
- package/docs/content/toolkit-setup-connections.mdx +1 -1
- package/package.json +1 -1
- package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/src/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/src/templates/chat/app/root.tsx +1 -1
- package/src/templates/chat/app/routes/agent.tsx +7 -7
- package/src/templates/chat/app/routes/extensions._index.tsx +1 -1
- package/src/templates/chat/app/routes/settings.$.tsx +1 -0
- package/src/templates/chat/app/routes/team.tsx +1 -1
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
- package/corpus/templates/analytics/.agents/skills/dashboard-management/references/template-catalog-and-demo.md +0 -62
- package/corpus/templates/analytics/actions/install-dashboard-template.ts +0 -369
- package/corpus/templates/analytics/actions/list-dashboard-templates.ts +0 -47
- package/corpus/templates/analytics/actions/list-native-v2-dashboard-templates.ts +0 -34
- package/corpus/templates/analytics/app/routes/catalog.tsx +0 -240
- package/src/templates/default/actions/navigate.spec.ts +0 -53
package/corpus/README.md
CHANGED
|
@@ -715,15 +715,9 @@ state or tracker context, but docs traffic is not app usage and should not appea
|
|
|
715
715
|
as an app/template series. Use a minimum cohort-size threshold for retention
|
|
716
716
|
rates so one or two identities cannot create misleading 100% or 0% spikes.
|
|
717
717
|
|
|
718
|
-
##
|
|
718
|
+
## Demo Dashboards
|
|
719
719
|
|
|
720
|
-
`
|
|
721
|
-
dashboard templates (Node Exporter, the canonical Agent Native observability
|
|
722
|
-
dashboard, etc.), and `ensure-demo-dashboards` auto-installs a per-user demo
|
|
723
|
-
on first app open. See
|
|
724
|
-
`references/template-catalog-and-demo.md` for the canonical-dashboard panel
|
|
725
|
-
rule, Node Exporter template specifics, and the full demo-dashboard lifecycle
|
|
726
|
-
(source routing, env var overrides, tombstoning, reset).
|
|
720
|
+
`ensure-demo-dashboards` auto-installs a per-user demo on first app open.
|
|
727
721
|
|
|
728
722
|
## Building Large First-Party Dashboards (compose-dashboard)
|
|
729
723
|
|
|
@@ -758,21 +752,16 @@ Hosted agent runs have a **~40s budget**. Many sequential `update-dashboard` cal
|
|
|
758
752
|
- To make nested config edits, use
|
|
759
753
|
`setConfigPath("yAxis.format", "percent")` instead of resending/clobbering
|
|
760
754
|
the whole nested object.
|
|
761
|
-
- **To add a shipped template's panels, prefer `install-dashboard-template` with `mergePanels: true`** and the existing `dashboardId`. It appends only the template panels whose id is not already present (preserving existing panels and order) in one atomic save — you don't author each panel yourself.
|
|
762
755
|
- **Always verify the returned proof-of-done and report it.**
|
|
763
756
|
`mutate-dashboard` returns `panelCount`, `appliedOps`, `panelOrder`,
|
|
764
757
|
`firstPanelIds`, `changedPanelIds`, `commandLog`, and a `summary` string.
|
|
765
|
-
|
|
766
|
-
`skippedExistingIds`, and `panelCount`. Tell the user the resulting panel
|
|
767
|
-
count instead of assuming success.
|
|
758
|
+
Tell the user the resulting panel count instead of assuming success.
|
|
768
759
|
|
|
769
760
|
```bash
|
|
770
761
|
# Add or edit several panels in ONE atomic call (never one call per panel)
|
|
771
762
|
pnpm action mutate-dashboard --dashboardId weekly-metrics \
|
|
772
763
|
--code 'dashboard.panelsMatching({"source":"first-party"}).setWidth(2);'
|
|
773
764
|
|
|
774
|
-
# Append a template's panels to an existing dashboard in one call
|
|
775
|
-
pnpm action install-dashboard-template --templateId skills-cli-funnel --dashboardId weekly-metrics --mergePanels true
|
|
776
765
|
```
|
|
777
766
|
|
|
778
767
|
## Archiving vs deleting
|
|
@@ -22,8 +22,10 @@ For events recorded by the analytics template itself via its `/track` endpoint,
|
|
|
22
22
|
|
|
23
23
|
For first-party counts, active-user, and retention questions, prefer the compact
|
|
24
24
|
tenant-scoped daily event and user-day rollups. Use `analytics_events` only for a
|
|
25
|
-
bounded recent drill-down with an explicit date/time range
|
|
26
|
-
|
|
25
|
+
bounded recent drill-down with an explicit date/time range. For the Builder.io
|
|
26
|
+
production organization after the BigQuery cutover, these logical tables are
|
|
27
|
+
served by partitioned BigQuery data and views; the source still does not require
|
|
28
|
+
an end user's separate warehouse connection.
|
|
27
29
|
|
|
28
30
|
Before a large or historical first-party query, call
|
|
29
31
|
`get-first-party-analytics-health`. Keep Neon as the default while its status is
|
|
@@ -37,10 +39,13 @@ a requirement to use BigQuery. The health result lists the supported options:
|
|
|
37
39
|
|
|
38
40
|
If a suitable backend is not configured, use its returned setup link or
|
|
39
41
|
`data-source-status --key <provider>` to guide the user through the existing
|
|
40
|
-
Data Sources walkthrough.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
Data Sources walkthrough. Connecting a query backend alone does not move the
|
|
43
|
+
collector or copy existing Neon events. For the Builder.io production
|
|
44
|
+
organization, the hidden `migrate-first-party-analytics-to-bigquery` action is
|
|
45
|
+
the explicit state machine: prepare dual-write, backfill with its cursor, then
|
|
46
|
+
cut over with confirmation. After cutover, `/track` writes and event queries
|
|
47
|
+
use BigQuery; public-key metadata, derived exception issues, and session-replay
|
|
48
|
+
data remain in SQL.
|
|
44
49
|
|
|
45
50
|
Example pageviews query for a local calendar day:
|
|
46
51
|
|
|
@@ -59,12 +59,10 @@ When a query fans out into many series, the `series` column will hold a `metric_
|
|
|
59
59
|
|
|
60
60
|
## Node Exporter dashboards
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
Use `list-sql-dashboards` to find an existing Node Exporter dashboard, then use
|
|
63
|
+
`update-dashboard` to create or repair one from the supported panel definitions:
|
|
63
64
|
|
|
64
65
|
```bash
|
|
65
|
-
pnpm action list-dashboard-templates
|
|
66
|
-
pnpm action install-dashboard-template --templateId=node-exporter-macos
|
|
67
|
-
pnpm action install-dashboard-template --templateId=node-exporter-full
|
|
68
66
|
```
|
|
69
67
|
|
|
70
68
|
`node-exporter-macos` is the comprehensive Darwin/Homebrew dashboard for macOS scrapes; it covers CPU, load, macOS memory fields, swap, APFS filesystems, disk IO, network devices, battery/power, scrape health, exporter process stats, Go runtime stats, and a metric-family coverage table. `node-exporter-full` is converted from Grafana dashboard 1860 revision 45 and lives at `seeds/dashboards/node-exporter-full.json`; it contains 124 Prometheus query panels, 16 section dividers, and native tabs for Overview, CPU & Memory, System, Storage, Network, and Exporter. The Full dashboard is Linux-focused because Grafana 1860 expects Linux collectors such as `node_memory_MemAvailable_bytes`, pressure stall information, `node_sockstat_*`, `node_netstat_*`, `node_timex_*`, `node_systemd_*`, and `node_hwmon_*`; Homebrew/macOS node_exporter omits many of those, so empty panels on macOS are expected. The templates use `job`, `instance`, and `range` filters; set `instance` to the Prometheus `instance` label from `node_uname_info`.
|
|
@@ -92,7 +90,9 @@ scrape_configs:
|
|
|
92
90
|
brew services restart prometheus # Prometheus UI at http://localhost:9090
|
|
93
91
|
```
|
|
94
92
|
|
|
95
|
-
Paste `http://localhost:9090` as the Prometheus URL in Data Sources, then
|
|
93
|
+
Paste `http://localhost:9090` as the Prometheus URL in Data Sources, then use
|
|
94
|
+
`list-sql-dashboards` and `update-dashboard` to manage the desired Node Exporter
|
|
95
|
+
dashboard.
|
|
96
96
|
|
|
97
97
|
## Incident Investigation Pattern
|
|
98
98
|
|
|
@@ -81,7 +81,7 @@ ladder.
|
|
|
81
81
|
## Application State
|
|
82
82
|
|
|
83
83
|
- `navigation` exposes the current dashboard, analysis, source, chart, and
|
|
84
|
-
selection. `navigate` moves the user
|
|
84
|
+
selection. `navigate` moves the user between supported Analytics surfaces,
|
|
85
85
|
`"sessions"`, `"monitoring"`, and `"agents"`. Use `view-screen` when the
|
|
86
86
|
active context is unclear.
|
|
87
87
|
- Clicking a panel stages it as a chat context chip and writes `selected-object`
|
|
@@ -97,7 +97,7 @@ Read the relevant skill before deeper work:
|
|
|
97
97
|
- `cross-source-analysis` for questions spanning sources (identity stitching,
|
|
98
98
|
de-duplication).
|
|
99
99
|
- `dashboard-management` for dashboard/panel storage, layout, extensions,
|
|
100
|
-
mutation
|
|
100
|
+
mutation and sharing.
|
|
101
101
|
- `adhoc-analysis` and `analysis-workspace` for one-off answers and large
|
|
102
102
|
multi-source work.
|
|
103
103
|
- `provider-api` and `data-programs` for the escape hatch and durable,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Push the saved config through the collab layer so open dashboard editors get
|
|
32
|
-
* the change in real time (mirrors update-dashboard
|
|
32
|
+
* the change in real time (mirrors update-dashboard).
|
|
33
33
|
*/
|
|
34
34
|
async function syncToCollab(
|
|
35
35
|
dashboardId: string,
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import {
|
|
3
|
+
getRequestOrgId,
|
|
4
|
+
getRequestUserEmail,
|
|
5
|
+
} from "@agent-native/core/server";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
8
|
+
import { requireAnalyticsAdminContext } from "../server/lib/db-admin-connections.js";
|
|
9
|
+
import {
|
|
10
|
+
assertFirstPartyAnalyticsBigQueryReady,
|
|
11
|
+
backfillFirstPartyAnalyticsBatch,
|
|
12
|
+
getFirstPartyAnalyticsBackend,
|
|
13
|
+
saveFirstPartyAnalyticsBackend,
|
|
14
|
+
} from "../server/lib/first-party-analytics-backend.js";
|
|
15
|
+
|
|
16
|
+
async function resolveScope() {
|
|
17
|
+
const userEmail = getRequestUserEmail();
|
|
18
|
+
if (!userEmail) throw new Error("no authenticated user");
|
|
19
|
+
const orgId = getRequestOrgId();
|
|
20
|
+
if (!orgId) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
"An active organization is required for the first-party Analytics migration.",
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
const admin = await requireAnalyticsAdminContext({ userEmail, orgId });
|
|
26
|
+
return { userEmail: admin.userEmail, orgId: admin.orgId };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const migrationSchema = z.object({
|
|
30
|
+
mode: z.enum(["status", "prepare", "backfill", "cutover"]),
|
|
31
|
+
table: z
|
|
32
|
+
.string()
|
|
33
|
+
.trim()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe(
|
|
36
|
+
"Optional BigQuery table reference as dataset.table or project.dataset.table. The default is <BIGQUERY_PROJECT_ID>.analytics.first_party_analytics_events_raw.",
|
|
37
|
+
),
|
|
38
|
+
cursor: z.string().trim().optional(),
|
|
39
|
+
limit: z.number().int().min(1).max(500).optional(),
|
|
40
|
+
confirm: z.boolean().optional(),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export default defineAction({
|
|
44
|
+
description:
|
|
45
|
+
"UI-only production migration for the current Analytics organization. Run prepare to validate the configured BigQuery table and enter dual-write mode, call backfill repeatedly with the returned cursor until complete, then call cutover with confirm=true. New /track events stay in Postgres during dual-write, so a BigQuery outage does not silently lose live data. Cutover is the only step that stops analytics event and rollup writes to Postgres; public-key metadata, derived exception issues, and session-replay data remain in the SQL store.",
|
|
46
|
+
schema: migrationSchema,
|
|
47
|
+
agentTool: false,
|
|
48
|
+
needsApproval: ({ mode }) => mode === "cutover",
|
|
49
|
+
run: async ({ mode, table, cursor, limit, confirm }) => {
|
|
50
|
+
const scope = await resolveScope();
|
|
51
|
+
const current = await getFirstPartyAnalyticsBackend(scope);
|
|
52
|
+
const configuredTable = table ?? current.table;
|
|
53
|
+
|
|
54
|
+
if (mode === "status") {
|
|
55
|
+
const ready =
|
|
56
|
+
current.sink === "postgres"
|
|
57
|
+
? null
|
|
58
|
+
: await assertFirstPartyAnalyticsBigQueryReady(current.table);
|
|
59
|
+
return {
|
|
60
|
+
...current,
|
|
61
|
+
ready: Boolean(ready),
|
|
62
|
+
rowCount: ready?.rowCount ?? null,
|
|
63
|
+
table: ready?.table.fullyQualified ?? current.table,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (mode === "prepare") {
|
|
68
|
+
const ready =
|
|
69
|
+
await assertFirstPartyAnalyticsBigQueryReady(configuredTable);
|
|
70
|
+
await saveFirstPartyAnalyticsBackend(scope, {
|
|
71
|
+
sink: "dual",
|
|
72
|
+
table: ready.table.fullyQualified,
|
|
73
|
+
backfillCursor: null,
|
|
74
|
+
backfillCompleted: false,
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
sink: "dual" as const,
|
|
78
|
+
table: ready.table.fullyQualified,
|
|
79
|
+
existingBigQueryRows: ready.rowCount,
|
|
80
|
+
next: "backfill",
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (mode === "backfill") {
|
|
85
|
+
if (current.sink !== "dual") {
|
|
86
|
+
throw new Error(
|
|
87
|
+
"Prepare the organization for dual-write before starting the BigQuery backfill.",
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
const result = await backfillFirstPartyAnalyticsBatch(
|
|
91
|
+
scope,
|
|
92
|
+
cursor ?? current.backfillCursor ?? null,
|
|
93
|
+
limit ?? 500,
|
|
94
|
+
current.table,
|
|
95
|
+
);
|
|
96
|
+
await saveFirstPartyAnalyticsBackend(scope, {
|
|
97
|
+
sink: "dual",
|
|
98
|
+
table: current.table,
|
|
99
|
+
backfillCursor: result.nextCursor,
|
|
100
|
+
backfillCompleted: result.complete,
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
...result,
|
|
104
|
+
sink: "dual" as const,
|
|
105
|
+
table: current.table,
|
|
106
|
+
next: result.complete ? "cutover" : "backfill",
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!confirm) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
"Cutover requires confirm=true because it stops first-party event and rollup writes to Postgres for this organization.",
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
if (current.sink !== "dual" || current.backfillCompleted !== true) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
"Complete the dual-write backfill before cutting over to BigQuery.",
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
const ready = await assertFirstPartyAnalyticsBigQueryReady(current.table);
|
|
121
|
+
await saveFirstPartyAnalyticsBackend(scope, {
|
|
122
|
+
sink: "bigquery",
|
|
123
|
+
table: ready.table.fullyQualified,
|
|
124
|
+
backfillCursor: current.backfillCursor,
|
|
125
|
+
backfillCompleted: true,
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
sink: "bigquery" as const,
|
|
129
|
+
table: ready.table.fullyQualified,
|
|
130
|
+
existingBigQueryRows: ready.rowCount,
|
|
131
|
+
postgresEventWrites: "stopped",
|
|
132
|
+
next: "verify dashboards",
|
|
133
|
+
};
|
|
134
|
+
},
|
|
135
|
+
});
|
|
@@ -50,7 +50,7 @@ export default defineAction({
|
|
|
50
50
|
.string()
|
|
51
51
|
.optional()
|
|
52
52
|
.describe(
|
|
53
|
-
"View to navigate to (ask, adhoc, analyses, extensions, sessions, monitoring, agents,
|
|
53
|
+
"View to navigate to (ask, adhoc, analyses, extensions, sessions, monitoring, agents, data-dictionary, data-sources, settings)",
|
|
54
54
|
),
|
|
55
55
|
dashboardId: z
|
|
56
56
|
.string()
|
|
@@ -15,12 +15,12 @@ function resolveScope() {
|
|
|
15
15
|
|
|
16
16
|
export default defineAction({
|
|
17
17
|
description:
|
|
18
|
-
"Query the built-in first-party Analytics source: events recorded through this app's analytics collector endpoint (/track), compact daily rollups, identifiable user-day rollups, and session replay summaries recorded through /api/analytics/replay. This source does not require an external provider connection. Use it for questions about app/site traffic, product events, template/app usage, conversions, session recordings, LLM/agent observability, model cost, token volume, latency, and other first-party data collected by this analytics app. Use source-specific actions such as BigQuery, GA4, Mixpanel, PostHog, or Amplitude when the user asks for those sources or the relevant data lives there. SQL may read analytics_events, analytics_event_daily_rollups, analytics_user_days, and session_recordings; session_replay_chunks is intentionally unavailable, and reads are automatically scoped to the current user/org. Prefer analytics_event_daily_rollups for event counts and analytics_user_days for active-user or retention questions.
|
|
18
|
+
"Query the built-in first-party Analytics source: events recorded through this app's analytics collector endpoint (/track), compact daily rollups updated transactionally with new ingest, identifiable user-day rollups, and session replay summaries recorded through /api/analytics/replay. This source does not require an external provider connection. Use it for questions about app/site traffic, product events, template/app usage, conversions, session recordings, LLM/agent observability, model cost, token volume, latency, and other first-party data collected by this analytics app. Use source-specific actions such as BigQuery, GA4, Mixpanel, PostHog, or Amplitude when the user asks for those sources or the relevant data lives there. SQL may read analytics_events, analytics_event_daily_rollups, analytics_user_days, and session_recordings; session_replay_chunks is intentionally unavailable, and reads are automatically scoped to the current user/org. Prefer analytics_event_daily_rollups for event counts and analytics_user_days for active-user or retention questions. On the Builder.io production organization after the explicit BigQuery cutover, event and rollup reads use partitioned BigQuery tables/views while session_recordings remains in the SQL store; cross-backend joins are not supported. Before a large or historical query, call get-first-party-analytics-health and use a configured external backend when it recommends one: BigQuery supports warehouse SQL and historical analysis, while Amplitude supports product analytics, funnels, and retention. Connecting a backend does not automatically reroute /track events or copy existing Neon events; the migration action performs that explicit prepare, backfill, and cutover sequence. Aggregate, project only needed columns, use bounded recent drill-downs, and add a LIMIT for raw or high-cardinality reads; do not issue an unbounded raw-event scan or paginate a large cohort. An explicit all-time or lifetime request remains all-time, so do not invent a default lower time bound. Safe scoped results are cached for up to five minutes for this agent action. analytics_events columns include event_name, timestamp, event_date, user_id, anonymous_id, user_key, session_id, app, template, signed_in, url, path, hostname, referrer, properties, and context. analytics_event_daily_rollups columns include tenant_key, owner_email, org_id, event_date, event_name, app, template, and event_count. analytics_user_days columns include tenant_key, owner_email, org_id, event_date, and user_key. LLM observability events use event_name = '$ai_generation'; useful properties include $ai_trace_id/run_id, $ai_session_id/thread_id, $ai_model/model, $ai_provider/provider, $ai_input_tokens/input_tokens, $ai_output_tokens/output_tokens, cache_read_tokens, cache_write_tokens, cost_cents_x100, $ai_total_cost_usd/cost_usd, duration_ms/$ai_latency, status, tool_calls, successful_tools, failed_tools, tools, tools_truncated, delegated, delegation_protocol, caller_app, delegation_task_id, a2a_task_id, parent_run_id, parent_turn_id, and error_message/$ai_error. Agent Teams child runs use delegation_protocol = 'agent-team' and retain their own run_id while linking to the launching run through parent_run_id. The bounded tools array contains names, relative start times, durations, statuses, and coarse error classes only, never args or results; failed runs and interrupted tools remain queryable. session_recordings columns include id, session_id, user_id, anonymous_id, user_key, started_at, ended_at, duration_ms, chunk_count, event_count, page_count, error_count, rage_click_count, app, template, status, first_url, last_url, path, hostname, referrer, and metadata.",
|
|
19
19
|
schema: z.object({
|
|
20
20
|
sql: z
|
|
21
21
|
.string()
|
|
22
22
|
.describe(
|
|
23
|
-
"Read-only SQL over analytics_events, analytics_event_daily_rollups, analytics_user_days, and session_recordings. Use literal values, not bind placeholders. Prefer the daily rollups for counts, active-user, and retention questions.
|
|
23
|
+
"Read-only SQL over analytics_events, analytics_event_daily_rollups, analytics_user_days, and session_recordings. Use literal values, not bind placeholders. Prefer the daily rollups for counts, active-user, and retention questions. On the Builder.io production organization after the explicit BigQuery cutover, event and rollup reads use partitioned BigQuery tables/views while session_recordings remains in the SQL store; cross-backend joins are not supported. Before a large or historical query, call get-first-party-analytics-health and use a configured external backend when recommended: BigQuery for warehouse SQL and complete history, or Amplitude for product analytics, funnels, and retention. Connecting one does not automatically reroute /track events or backfill existing Neon data; the migration action performs that explicit prepare, backfill, and cutover sequence. Aggregate or project only needed columns and add a LIMIT for raw or high-cardinality reads; do not issue an unbounded raw-event scan or paginate a large cohort. An explicit all-time or lifetime request remains all-time, so do not invent a default lower time bound. Example: SELECT event_date, event_name, SUM(event_count) AS events FROM analytics_event_daily_rollups WHERE event_date >= '2026-05-01' AND event_date < '2026-06-01' GROUP BY event_date, event_name ORDER BY event_date, events DESC",
|
|
24
24
|
),
|
|
25
25
|
}),
|
|
26
26
|
outputSchema: z.object({
|
|
@@ -576,7 +576,6 @@ export default defineAction({
|
|
|
576
576
|
"Do not use `ops` or `panelOrder` for ordinary agent edits like moving charts, adding panels to an existing dashboard, changing widths, or updating panel config; call `mutate-dashboard` once with the full edit script. " +
|
|
577
577
|
"When this action is appropriate, provide only one of `ops`, `panelOrder`, or `config`; `config` replaces the whole dashboard config. " +
|
|
578
578
|
"First-party event panels must bind to a declared dashboard time filter with `{{timeRange}}` or date-range variables. Intentional fixed-window, cohort-history, and all-time exceptions must be explicit in `panel.config.timeScope`; unbounded first-party SQL is rejected at save time. " +
|
|
579
|
-
"To add a shipped catalog template's panels to an existing dashboard, prefer `install-dashboard-template` with `mergePanels: true` — it appends the template's panels in one call without you having to author each panel. " +
|
|
580
579
|
"The result is compact by default: `panelCount`, `appliedOps`, `panelOrder`, `firstPanelIds`, and `summary`. Set `returnConfig: true` only when you truly need the full config in the tool result. " +
|
|
581
580
|
"The UI auto-refreshes after this action — do NOT call `refresh-screen`.",
|
|
582
581
|
schema: z.object({
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
9
9
|
import { listAnalyticsAlertRules } from "../server/lib/analytics-alerts";
|
|
10
|
-
import { listDashboardCatalog } from "../server/lib/dashboard-catalog";
|
|
11
10
|
import { getAnalysis, getDashboard } from "../server/lib/dashboards-store";
|
|
12
11
|
import { getErrorIssue, listErrorIssues } from "../server/lib/error-capture.js";
|
|
13
12
|
import { listAnalyticsPublicKeys } from "../server/lib/first-party-analytics.js";
|
|
@@ -391,25 +390,6 @@ export default defineAction({
|
|
|
391
390
|
})),
|
|
392
391
|
};
|
|
393
392
|
}
|
|
394
|
-
} else if (nav?.view === "catalog") {
|
|
395
|
-
screen.page = "catalog";
|
|
396
|
-
const email = getRequestUserEmail();
|
|
397
|
-
if (email) {
|
|
398
|
-
const catalog = await listDashboardCatalog({
|
|
399
|
-
email,
|
|
400
|
-
orgId: getRequestOrgId() || null,
|
|
401
|
-
});
|
|
402
|
-
screen.dashboardTemplates = catalog.map((template) => ({
|
|
403
|
-
id: template.id,
|
|
404
|
-
name: template.name,
|
|
405
|
-
category: template.category,
|
|
406
|
-
dataSources: template.dataSources,
|
|
407
|
-
installed: template.installed,
|
|
408
|
-
installedDashboardIds: template.installedDashboards.map(
|
|
409
|
-
(dashboard) => dashboard.id,
|
|
410
|
-
),
|
|
411
|
-
}));
|
|
412
|
-
}
|
|
413
393
|
} else if (nav?.view === "agents") {
|
|
414
394
|
screen.page = "agents";
|
|
415
395
|
screen.agentsView = nav?.agentsView || "monitoring";
|
|
@@ -17,7 +17,6 @@ const pageTitleKeys: Record<string, string> = {
|
|
|
17
17
|
"/ask": "navigation.ask",
|
|
18
18
|
"/data-sources": "navigation.dataSources",
|
|
19
19
|
"/data-dictionary": "navigation.dataDictionary",
|
|
20
|
-
"/catalog": "navigation.templateCatalog",
|
|
21
20
|
"/analyses": "navigation.analyses",
|
|
22
21
|
"/sessions": "navigation.sessions",
|
|
23
22
|
"/monitoring": "navigation.monitoring",
|
|
@@ -98,9 +98,10 @@ export function useNavigationState() {
|
|
|
98
98
|
state.view = "data-sources";
|
|
99
99
|
} else if (pathname === "/data-dictionary") {
|
|
100
100
|
state.view = "data-dictionary";
|
|
101
|
-
} else if (
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
} else if (
|
|
102
|
+
pathname === "/settings" ||
|
|
103
|
+
pathname.startsWith("/settings/")
|
|
104
|
+
) {
|
|
104
105
|
state.view = "settings";
|
|
105
106
|
}
|
|
106
107
|
|
|
@@ -114,7 +115,7 @@ export function useNavigationState() {
|
|
|
114
115
|
if (cmd.view === "analyses") return "/dashboards";
|
|
115
116
|
if (cmd.view === "extensions" && cmd.extensionId)
|
|
116
117
|
return `/extensions/${cmd.extensionId}`;
|
|
117
|
-
if (cmd.view === "extensions") return "/settings
|
|
118
|
+
if (cmd.view === "extensions") return "/settings/extensions";
|
|
118
119
|
if (cmd.view === "sessions" && cmd.recordingId)
|
|
119
120
|
return `/sessions/${encodeURIComponent(cmd.recordingId)}`;
|
|
120
121
|
if (cmd.view === "sessions") return "/sessions";
|
|
@@ -146,7 +147,6 @@ export function useNavigationState() {
|
|
|
146
147
|
}
|
|
147
148
|
if (cmd.view === "data-sources") return "/data-sources";
|
|
148
149
|
if (cmd.view === "data-dictionary") return "/data-dictionary";
|
|
149
|
-
if (cmd.view === "catalog") return "/catalog";
|
|
150
150
|
if (cmd.view === "ask") return "/ask";
|
|
151
151
|
if (cmd.view === "settings") return "/settings";
|
|
152
152
|
if (cmd.view === "overview" || cmd.view === "home") return "/ask";
|