@agent-native/core 0.120.1 → 0.120.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +9 -0
- package/corpus/core/docs/content/extensions.mdx +23 -4
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +4 -0
- package/corpus/core/src/agent/run-manager.ts +36 -10
- package/corpus/core/src/agent/types.ts +2 -0
- package/corpus/core/src/client/extensions/ExtensionsListPage.tsx +16 -3
- package/corpus/core/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
- package/corpus/core/src/client/settings/SettingsPanel.tsx +10 -0
- package/corpus/core/src/deploy/build.ts +3 -0
- package/corpus/core/src/server/analytics.ts +154 -25
- package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +35 -6
- package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +2 -2
- package/corpus/core/src/templates/chat/netlify.toml +1 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
- package/corpus/core/src/vite/client.ts +6 -0
- package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +27 -43
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +19 -8
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +2 -2
- package/corpus/templates/analytics/AGENTS.md +20 -8
- package/corpus/templates/analytics/actions/get-explorer-dashboard.ts +3 -0
- package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +140 -46
- package/corpus/templates/analytics/actions/migrate-analytics-artifacts.ts +48 -0
- package/corpus/templates/analytics/actions/save-analysis.ts +2 -3
- package/corpus/templates/analytics/actions/view-screen.ts +1 -1
- package/corpus/templates/analytics/app/components/dashboard/DashboardMetadata.tsx +77 -0
- package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +7 -1
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +103 -502
- package/corpus/templates/analytics/app/global.css +30 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +2 -2
- package/corpus/templates/analytics/app/i18n-data.ts +80 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +49 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +54 -11
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +3 -53
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +23 -25
- package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +2 -2
- package/corpus/templates/analytics/app/routes/analyses._index.tsx +3 -2
- package/corpus/templates/analytics/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/analytics/changelog/2026-07-23-analytics-now-groups-saved-analyses-and-embedded-extensions-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-23-dashboard-menus-show-who-created-and-last-updated-each-dashb.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-23-dashboard-usage-now-loads-reliably-for-organizations-with-ma.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-23-long-dashboard-building-requests-now-continue-without-stoppi.md +6 -0
- package/corpus/templates/analytics/netlify.toml +4 -0
- package/corpus/templates/analytics/server/db/schema.ts +4 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -1
- package/corpus/templates/analytics/server/lib/agent-readable-resource-context.ts +1 -0
- package/corpus/templates/analytics/server/lib/migrate-analytics-artifacts.ts +1062 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +6 -52
- package/corpus/templates/analytics/server/plugins/core-routes.ts +1 -1
- package/corpus/templates/analytics/server/plugins/db.ts +10 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +36 -1
- package/corpus/templates/assets/actions/generate-image.ts +28 -1
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +46 -8
- package/corpus/templates/assets/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/assets/changelog/2026-07-23-assets-image-generation-now-recovers-after-a-completed-tool-.md +6 -0
- package/corpus/templates/assets/netlify.toml +1 -0
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +38 -8
- package/corpus/templates/brain/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/brain/netlify.toml +1 -0
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +43 -5
- package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +2 -16
- package/corpus/templates/calendar/netlify.toml +1 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +35 -6
- package/corpus/templates/chat/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/chat/netlify.toml +1 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +52 -6
- package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +2 -16
- package/corpus/templates/clips/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-23-meeting-recording-meters-and-dismissed-prompts.md +6 -0
- package/corpus/templates/clips/desktop/src/hooks/useMicMeter.ts +1 -1
- package/corpus/templates/clips/desktop/src/lib/meeting-notification-dismissal.ts +2 -0
- package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +1 -3
- package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +86 -0
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +24 -0
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +5 -69
- package/corpus/templates/clips/desktop/src/styles.css +35 -3
- package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +13 -44
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +119 -17
- package/corpus/templates/clips/netlify.toml +1 -0
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +3 -7
- package/corpus/templates/content/app/routes/_app.extensions._index.tsx +2 -2
- package/corpus/templates/content/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/content/netlify.toml +1 -0
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +55 -17
- package/corpus/templates/design/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/design/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/design/netlify.toml +1 -0
- package/corpus/templates/dispatch/app/dispatch-extensions.tsx +1 -1
- package/corpus/templates/dispatch/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/dispatch/netlify.toml +1 -0
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +41 -45
- package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +2 -2
- package/corpus/templates/forms/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/forms/netlify.toml +1 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +36 -5
- package/corpus/templates/macros/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/macros/netlify.toml +1 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -9
- package/corpus/templates/mail/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/mail/netlify.toml +1 -0
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +38 -5
- package/corpus/templates/plan/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/plan/netlify.toml +1 -0
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +47 -4
- package/corpus/templates/slides/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/slides/netlify.toml +1 -0
- package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +37 -6
- package/corpus/templates/tasks/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/tasks/app/routes/settings.tsx +31 -0
- package/corpus/templates/tasks/netlify.toml +1 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +4 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +9 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +25 -10
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/types.d.ts +2 -2
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts +5 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.js +5 -3
- package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
- package/dist/client/settings/ExtensionsSettingsContent.d.ts +2 -0
- package/dist/client/settings/ExtensionsSettingsContent.d.ts.map +1 -0
- package/dist/client/settings/ExtensionsSettingsContent.js +10 -0
- package/dist/client/settings/ExtensionsSettingsContent.js.map +1 -0
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +10 -1
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/deploy/build.js +1 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/server/analytics.d.ts +9 -4
- package/dist/server/analytics.d.ts.map +1 -1
- package/dist/server/analytics.js +111 -22
- package/dist/server/analytics.js.map +1 -1
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +35 -6
- package/dist/templates/chat/app/routes/extensions._index.tsx +2 -2
- package/dist/templates/chat/netlify.toml +1 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +2 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/extensions.mdx +23 -4
- package/package.json +1 -1
- package/src/agent/production-agent.ts +4 -0
- package/src/agent/run-manager.ts +36 -10
- package/src/agent/types.ts +2 -0
- package/src/client/extensions/ExtensionsListPage.tsx +16 -3
- package/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
- package/src/client/settings/SettingsPanel.tsx +10 -0
- package/src/deploy/build.ts +3 -0
- package/src/server/analytics.ts +154 -25
- package/src/templates/chat/app/components/layout/Sidebar.tsx +35 -6
- package/src/templates/chat/app/routes/extensions._index.tsx +2 -2
- package/src/templates/chat/netlify.toml +1 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
- package/src/vite/client.ts +6 -0
- package/corpus/templates/analytics/app/components/layout/NewAnalysisDialog.tsx +0 -165
- package/corpus/templates/analytics/app/pages/analyses/AnalysesList.tsx +0 -175
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
name: adhoc-analysis
|
|
3
3
|
description: >-
|
|
4
4
|
How to conduct ad-hoc analyses: gather data from multiple sources, synthesize
|
|
5
|
-
findings, save
|
|
5
|
+
findings, and save durable results as dashboard artifacts that anyone can re-run.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Ad-Hoc Analysis
|
|
9
9
|
|
|
10
|
-
Ad-hoc analyses are deep-dive investigations that cross-reference multiple data sources and produce a written report with findings.
|
|
10
|
+
Ad-hoc analyses are deep-dive investigations that cross-reference multiple data sources and produce a written report with findings. The durable user-facing result is a dashboard. Answer in chat first unless the user explicitly asks to save the result, create a reusable artifact, or re-run/update an existing saved analysis.
|
|
11
11
|
|
|
12
12
|
## When to Use
|
|
13
13
|
|
|
@@ -17,21 +17,20 @@ Use the ad-hoc analysis workflow when:
|
|
|
17
17
|
- The investigation involves cross-referencing (e.g., CRM deals matched against call recordings)
|
|
18
18
|
- The user explicitly asks for an "analysis" or "deep dive"
|
|
19
19
|
|
|
20
|
-
Save a reusable
|
|
20
|
+
Save a reusable dashboard artifact when:
|
|
21
21
|
|
|
22
22
|
- The user explicitly asks to save, create, publish, or re-run a saved analysis
|
|
23
23
|
- The user is already viewing or re-running an existing saved analysis
|
|
24
24
|
- The output needs a durable artifact because it includes generated chart images or a reusable refresh workflow
|
|
25
25
|
|
|
26
|
-
For one-off questions and exploratory deep dives, query the data and answer in chat. Do not call `save-analysis` just because the user said "analysis" or "deep dive".
|
|
26
|
+
For one-off questions and exploratory deep dives, query the data and answer in chat. Do not create a dashboard or call the legacy `save-analysis` action just because the user said "analysis" or "deep dive".
|
|
27
27
|
|
|
28
28
|
If the user asks for an analysis output that needs a bespoke interactive
|
|
29
29
|
surface, custom visualization, multi-step workflow, or UI that cannot be
|
|
30
|
-
faithfully represented
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
you built it as an extension.
|
|
30
|
+
faithfully represented by native dashboard panels, create an extension and
|
|
31
|
+
immediately embed it in the dashboard as one or more `chartType: "extension"`
|
|
32
|
+
panels with `config.extensionId`. Never leave the extension as a standalone
|
|
33
|
+
Analytics result or direct the user to an Extensions page.
|
|
35
34
|
|
|
36
35
|
## Workflow
|
|
37
36
|
|
|
@@ -159,46 +158,33 @@ Time range: Jan 1 – Mar 31, 2026
|
|
|
159
158
|
Filters: S1+ pipeline, closed-lost only
|
|
160
159
|
```
|
|
161
160
|
|
|
162
|
-
### Step 6: Save the
|
|
161
|
+
### Step 6: Save the Dashboard Artifact (only when requested)
|
|
163
162
|
|
|
164
|
-
Call `
|
|
163
|
+
Call `update-dashboard` with a complete dashboard config when the user asks for a saved/re-runnable analysis or this turn is creating a durable report. If the requested report needs bespoke UI, create the extension first and include its id in an extension panel.
|
|
165
164
|
|
|
166
165
|
```
|
|
167
|
-
|
|
168
|
-
--
|
|
169
|
-
--
|
|
170
|
-
--description "Deep dive into 54 Fusion deals closed-lost in Q1, cross-referenced with Gong calls and Slack activity"
|
|
171
|
-
--question "Why are we losing deals in Q1? Cross-reference with Gong calls and Slack."
|
|
172
|
-
--dataSources '["hubspot", "gong", "slack"]'
|
|
173
|
-
--instructions "1. Fetch closed-lost S1+ deals from HubSpot (pipeline: Fusion, close date: Q1 2026)
|
|
174
|
-
2. For each deal, fetch associated contacts and their emails
|
|
175
|
-
3. Search Gong calls matching those contact emails (lookback: 6 months before close date)
|
|
176
|
-
4. For top 15 deals by amount, search Slack for '{company name} fusion'
|
|
177
|
-
5. Calculate: total deals, avg deal size, win rate, Gong coverage rate
|
|
178
|
-
6. Break down by: lost reason, stage reached, deal size tier
|
|
179
|
-
7. Highlight deals with no Gong coverage (blind spots)
|
|
180
|
-
8. Save results with save-analysis using id='closed-lost-q1-2026'"
|
|
181
|
-
--resultMarkdown "[the full markdown report]"
|
|
182
|
-
--resultData '{"deals": [...], "metrics": {...}}'
|
|
166
|
+
update-dashboard
|
|
167
|
+
--dashboardId "closed-lost-q1-2026"
|
|
168
|
+
--config '{"name":"Q1 2026 Closed-Lost Analysis","panels":[{"id":"findings","title":"Findings","source":"first-party","chartType":"table","width":2,"sql":"...","config":{"description":"Evidence-backed report for the requested cohort."}}]}'
|
|
183
169
|
```
|
|
184
170
|
|
|
185
|
-
|
|
171
|
+
The dashboard config must preserve compact evidence from the real data-source action results you used: row samples, aggregate metrics, match decisions, call/message IDs, short transcript/message excerpts, coded themes, sentiment labels, and explicit provider errors for any gaps. Do not include full Gong transcripts, full tool outputs, or raw provider payload dumps. If you cannot query a source, do not save guessed dashboard content; report the unavailable/error result instead.
|
|
186
172
|
|
|
187
|
-
**Critical: Write good
|
|
173
|
+
**Critical: Write good dashboard definitions.** The dashboard description/config is what the agent uses on re-run. Be specific:
|
|
188
174
|
|
|
189
175
|
- Which actions to call with which parameters
|
|
190
176
|
- What filters to apply
|
|
191
177
|
- How to match records across sources
|
|
192
178
|
- What metrics to calculate
|
|
193
179
|
- What structure the output should have
|
|
194
|
-
- End with "
|
|
180
|
+
- End with "Update dashboard with id='...'"
|
|
195
181
|
|
|
196
182
|
### Step 7: Navigate to the Result
|
|
197
183
|
|
|
198
|
-
After saving, navigate the user to see the saved
|
|
184
|
+
After saving, navigate the user to see the saved dashboard:
|
|
199
185
|
|
|
200
186
|
```
|
|
201
|
-
navigate --view=
|
|
187
|
+
navigate --view=adhoc --dashboardId=closed-lost-q1-2026
|
|
202
188
|
```
|
|
203
189
|
|
|
204
190
|
## Re-Running an Analysis
|
|
@@ -209,7 +195,7 @@ When a user clicks "Re-run" on a saved analysis, the agent receives:
|
|
|
209
195
|
- The saved instructions (step-by-step)
|
|
210
196
|
- The analysis ID to update
|
|
211
197
|
|
|
212
|
-
Follow the instructions to gather fresh data, then call `
|
|
198
|
+
Follow the instructions to gather fresh data, then call `update-dashboard` with the same `dashboardId` to update the panels/report. Existing legacy analysis deep links remain readable, but new durable results must be written to dashboards.
|
|
213
199
|
|
|
214
200
|
If the user challenges the coverage of a chat answer or saved analysis ("why
|
|
215
201
|
aren't you pulling more deals?", "where is the updated response?"), rerun the
|
|
@@ -221,21 +207,19 @@ showing it or saving it.
|
|
|
221
207
|
|
|
222
208
|
| Action | Purpose |
|
|
223
209
|
| ----------------- | ---------------------------------------------------------------- |
|
|
224
|
-
| `
|
|
225
|
-
| `get-
|
|
226
|
-
| `list-
|
|
227
|
-
| `
|
|
228
|
-
| `navigate` | Navigate to analyses view: `--view=analyses [--analysisId=<id>]` |
|
|
210
|
+
| `update-dashboard` | Save or update the dashboard artifact and its panels |
|
|
211
|
+
| `get-sql-dashboard` | Retrieve a dashboard by ID |
|
|
212
|
+
| `list-sql-dashboards` | List dashboard artifacts |
|
|
213
|
+
| `navigate` | Navigate to a dashboard: `--view=adhoc --dashboardId=<id>` |
|
|
229
214
|
|
|
230
215
|
## Storage
|
|
231
216
|
|
|
232
|
-
|
|
217
|
+
Dashboard artifacts are stored in SQL and respect the normal dashboard access model. Legacy analyses remain in their existing SQL tables for compatibility and should not be used for new artifacts.
|
|
233
218
|
|
|
234
219
|
API endpoints (for UI consumption):
|
|
235
220
|
|
|
236
|
-
- `GET /api/
|
|
237
|
-
- `GET /api/
|
|
238
|
-
- `DELETE /api/analyses/{id}` — delete one
|
|
221
|
+
- `GET /api/sql-dashboards` — list dashboard artifacts
|
|
222
|
+
- `GET /api/sql-dashboards/{id}` — get one
|
|
239
223
|
|
|
240
224
|
## Best Practices
|
|
241
225
|
|
|
@@ -257,7 +241,7 @@ hold everything in one pass:
|
|
|
257
241
|
from the primary source (HubSpot, BigQuery, etc.).
|
|
258
242
|
2. **Chunk and persist** — process 5-10 items per iteration. For each chunk,
|
|
259
243
|
write a short per-item findings note (key signals, gaps, theme tags) as an
|
|
260
|
-
intermediate result to
|
|
244
|
+
intermediate result to the dashboard definition or agent scratch.
|
|
261
245
|
3. **Synthesize** — after all chunks are complete, read the intermediate notes
|
|
262
246
|
back in and produce the final cross-item synthesis (patterns, rankings,
|
|
263
247
|
themes, recommendations).
|
|
@@ -7,7 +7,7 @@ description: >-
|
|
|
7
7
|
|
|
8
8
|
# Dashboard Management
|
|
9
9
|
|
|
10
|
-
Dashboards are SQL-backed resources. New dashboards
|
|
10
|
+
Dashboards are the canonical SQL-backed Analytics resources. New dashboards, saved analyses, reports, and bespoke extensions are represented as dashboard artifacts—not as separate user-facing Analytics objects. Legacy analysis tables and actions remain available only for compatibility.
|
|
11
11
|
|
|
12
12
|
## Storage
|
|
13
13
|
|
|
@@ -25,6 +25,15 @@ Current storage:
|
|
|
25
25
|
|
|
26
26
|
Legacy settings keys such as `u:<email>:dashboard-*`, `u:<email>:sql-dashboard-*`, `o:<orgId>:sql-dashboard-*`, and `adhoc-analysis-*` are still read as a fallback and copied into SQL on access. Do not create new dashboard settings rows.
|
|
27
27
|
|
|
28
|
+
For organization-wide consolidation, use `migrate-analytics-artifacts` first
|
|
29
|
+
with `dryRun: true`. The write requires an organization owner/admin and the
|
|
30
|
+
exact confirmation token `MIGRATE_ANALYTICS_ARTIFACTS`. It materializes
|
|
31
|
+
organization-scoped legacy settings, creates dashboard blocks for saved
|
|
32
|
+
analyses and standalone extensions, archives exact duplicates, copies shares,
|
|
33
|
+
and removes legacy settings keys only after SQL rows are materialized. Source
|
|
34
|
+
rows remain recoverable. Private member-only rows are intentionally outside
|
|
35
|
+
this organization-scoped operation.
|
|
36
|
+
|
|
28
37
|
Use `mutate-dashboard` for existing dashboard edits. It resolves the current
|
|
29
38
|
user/org context, validates the resulting config, writes the SQL-backed record,
|
|
30
39
|
syncs collab, and returns compact proof. Use `update-dashboard` for new
|
|
@@ -104,13 +113,15 @@ standard panels, supported chart types, filters, variables, sections, and grid
|
|
|
104
113
|
layout.
|
|
105
114
|
|
|
106
115
|
If the user asks for a dashboard or analytical surface that needs bespoke UI or
|
|
107
|
-
code beyond the dashboard JSON/component model, create an extension
|
|
108
|
-
Examples include custom interaction flows, non-standard
|
|
109
|
-
multi-step workflows, highly custom layouts, custom
|
|
110
|
-
dashboard-like app that needs behavior the built-in
|
|
111
|
-
production mode, call `create-extension`
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
code beyond the dashboard JSON/component model, create an extension and embed it
|
|
117
|
+
in the dashboard. Examples include custom interaction flows, non-standard
|
|
118
|
+
visualizations, complex multi-step workflows, highly custom layouts, custom
|
|
119
|
+
client-side state, or a dashboard-like app that needs behavior the built-in
|
|
120
|
+
renderer cannot express. In production mode, call `create-extension`
|
|
121
|
+
automatically, then call `update-dashboard` with one or more
|
|
122
|
+
`chartType: "extension"` panels using `config.extensionId`. Never leave the
|
|
123
|
+
extension as a standalone Analytics result or direct the user to the Extensions
|
|
124
|
+
page.
|
|
114
125
|
|
|
115
126
|
## Embedding An Extension As A Panel
|
|
116
127
|
|
|
@@ -36,7 +36,7 @@ through `2026-05-02T04:00:00Z`.
|
|
|
36
36
|
|
|
37
37
|
## Showing Charts In Chat
|
|
38
38
|
|
|
39
|
-
For an in-chat answer, **emit a live `/chart` embed** — never `generate-chart`. The embed mounts a live `SqlChart` that re-queries when its source changes, and it doesn't choke on rigid JSON params the way the PNG action does. Full shape in `AGENTS.md` ("Inline Charts in Chat" section). Reach for `generate-chart` only when you're building a
|
|
39
|
+
For an in-chat answer, **emit a live `/chart` embed** — never `generate-chart`. The embed mounts a live `SqlChart` that re-queries when its source changes, and it doesn't choke on rigid JSON params the way the PNG action does. Full shape in `AGENTS.md` ("Inline Charts in Chat" section). Reach for `generate-chart` only when you're building a dashboard artifact that needs a persisted report image.
|
|
40
40
|
|
|
41
41
|
If `generate-chart` returns an error in any chat-answering flow, the recovery is to switch to the live embed, not to retry with reformatted params.
|
|
42
42
|
|
|
@@ -136,7 +136,7 @@ future analyses.
|
|
|
136
136
|
- Before finalizing an analytics answer, make the evidence trail explicit enough
|
|
137
137
|
to audit: source(s), time window, filters, sample size or row count, join or
|
|
138
138
|
match method, caveats/gaps, and what action to take next when useful.
|
|
139
|
-
- Data-source status, data-dictionary reads, dashboard dry-runs, `update-dashboard`, `generate-chart
|
|
139
|
+
- Data-source status, data-dictionary reads, dashboard dry-runs, `update-dashboard`, and `generate-chart` are not data queries. For dashboard artifacts, run at least one provider query action and preserve the result evidence in the final answer or dashboard config/description.
|
|
140
140
|
- Use action arguments such as `query`, `objectType`, `properties`, `owner`, `limit`, or provider-specific filters to narrow output; if an action returns a broad batch, filter it in your analysis and cite the records used.
|
|
141
141
|
- Update the relevant `.agents/skills/<provider>/SKILL.md` when you discover new patterns.
|
|
142
142
|
- For BigQuery queries, check `.agents/skills/bigquery/SKILL.md` first; if the data dictionary does not contain the exact table/columns, call `search-bigquery-schema`.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Analytics — Agent Guide
|
|
2
2
|
|
|
3
3
|
Analytics is an agent-native BI workspace. The agent manages data sources,
|
|
4
|
-
queries, dashboards, charts,
|
|
5
|
-
|
|
4
|
+
queries, dashboards, charts, and connected warehouse integrations through
|
|
5
|
+
actions and SQL-backed state. Dashboards are the canonical user-facing
|
|
6
|
+
analytics artifact; legacy analyses remain readable only for compatibility.
|
|
6
7
|
|
|
7
8
|
Keep this file essential. Querying, dashboard, warehouse, and implementation
|
|
8
9
|
details live in `.agents/skills/`.
|
|
@@ -175,13 +176,22 @@ membership id when its native update status reports `update-available`.
|
|
|
175
176
|
`/agents?view=dashboards` shows the
|
|
176
177
|
admin-only dashboard usage audit; call `list-dashboard-usage-stats` when
|
|
177
178
|
admins ask about dashboard created/modified dates, owners, last tracked
|
|
178
|
-
modifier, views, engagements, saved views, or cleanup candidates. The
|
|
179
|
+
modifier, views, edits, engagements, saved views, or cleanup candidates. The
|
|
180
|
+
dashboard overflow menu shows created/updated timestamps and their tracked
|
|
181
|
+
actors for both SQL and Explorer dashboards. The
|
|
179
182
|
Advanced menu opens `/agents?view=database`, where organization owners/admins
|
|
180
183
|
can connect other agent-native app databases and use the shared database admin
|
|
181
184
|
tool for table browsing, row editing, and SQL inspection. This database
|
|
182
185
|
surface is for connected target app databases, not broad access to all
|
|
183
186
|
Analytics data. Keep future admin additions inside this route instead of
|
|
184
187
|
adding many top-level sidebar tabs.
|
|
188
|
+
- The `migrate-analytics-artifacts` action is the organization-scoped
|
|
189
|
+
consolidation path. Run it first with `dryRun: true`, then use the exact
|
|
190
|
+
`confirm: "MIGRATE_ANALYTICS_ARTIFACTS"` token for an owner/admin-approved
|
|
191
|
+
write. It materializes legacy settings, turns saved analyses and standalone
|
|
192
|
+
extensions into dashboard blocks, archives exact duplicates, copies shares,
|
|
193
|
+
and keeps source rows recoverable. It intentionally covers organization-
|
|
194
|
+
scoped rows, not private member-only rows.
|
|
185
195
|
- For dashboard edits, default to `mutate-dashboard` with its typed
|
|
186
196
|
`dashboard.*` script API. It supports id-based panel moves, title/SQL/config
|
|
187
197
|
edits, inserts, duplication, removal, and dashboard field patches in one
|
|
@@ -212,11 +222,13 @@ membership id when its native update status reports `update-available`.
|
|
|
212
222
|
- `get-sql-dashboard` is compact by default for agents. Use its `panels`
|
|
213
223
|
summaries and `layout.panelOrder` / `layout.firstPanelIds` for orientation and
|
|
214
224
|
proof. Pass `includeConfig: true` only when full panel SQL/config is needed.
|
|
215
|
-
- Native dashboards
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
config/components
|
|
219
|
-
|
|
225
|
+
- Native dashboards are constrained artifacts. If a requested dashboard,
|
|
226
|
+
analysis/report surface, visualization, interaction model, custom layout, or
|
|
227
|
+
bespoke workflow cannot be done faithfully with the built-in dashboard JSON
|
|
228
|
+
config/components, automatically create an extension and embed it as one or
|
|
229
|
+
more `chartType: "extension"` panels using `config.extensionId`. Never leave
|
|
230
|
+
the extension standalone or direct the user to an Extensions page from
|
|
231
|
+
Analytics.
|
|
220
232
|
- For an existing extension-backed dashboard or migrated surface such as Risk
|
|
221
233
|
Meeting, separate data repair from visual redesign. Inspect the dashboard and
|
|
222
234
|
extension first, then call `update-extension` with exactly `id`,
|
|
@@ -33,6 +33,9 @@ export default defineAction({
|
|
|
33
33
|
ownerEmail: dash.ownerEmail,
|
|
34
34
|
orgId: dash.orgId,
|
|
35
35
|
visibility: dash.visibility,
|
|
36
|
+
createdAt: dash.createdAt,
|
|
37
|
+
updatedAt: dash.updatedAt,
|
|
38
|
+
updatedBy: dash.updatedBy,
|
|
36
39
|
role: dash.role,
|
|
37
40
|
canEdit: dash.canEdit,
|
|
38
41
|
canManage: dash.canManage,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core/action";
|
|
2
2
|
import { buildDeepLink } from "@agent-native/core/server";
|
|
3
|
-
import { and, eq, like, or, sql } from "drizzle-orm";
|
|
3
|
+
import { and, eq, isNull, like, or, sql } from "drizzle-orm";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
6
6
|
import { getDb, schema } from "../server/db/index.js";
|
|
@@ -21,6 +21,7 @@ type DashboardUsageStats = {
|
|
|
21
21
|
viewCount: number;
|
|
22
22
|
engagementCount: number;
|
|
23
23
|
eventEngagementCount: number;
|
|
24
|
+
editCount: number;
|
|
24
25
|
savedViewCount: number;
|
|
25
26
|
uniqueUserCount: number;
|
|
26
27
|
lastViewedAt: string | null;
|
|
@@ -96,6 +97,8 @@ export function dashboardIdFromEventLocation(
|
|
|
96
97
|
if (!raw) return null;
|
|
97
98
|
try {
|
|
98
99
|
const parsed = new URL(raw, "https://analytics.local");
|
|
100
|
+
const parsedDashboardId = dashboardIdFromPath(parsed.pathname);
|
|
101
|
+
if (parsedDashboardId) return parsedDashboardId;
|
|
99
102
|
if (
|
|
100
103
|
/(?:^|\/)(?:dashboards|adhoc)\/explorer-dashboard$/.test(parsed.pathname)
|
|
101
104
|
) {
|
|
@@ -124,7 +127,7 @@ function dashboardUrl(row: { id: string; kind: string }): string {
|
|
|
124
127
|
|
|
125
128
|
export default defineAction({
|
|
126
129
|
description:
|
|
127
|
-
"List admin-only dashboard usage and cleanup stats for every dashboard in the active organization. Includes lifecycle metadata, owner, last tracked modifier, pageviews, engagement events, unique viewers, saved view counts, archive/hidden state, and dashboard links. Requires active organization owner/admin role.",
|
|
130
|
+
"List admin-only dashboard usage and cleanup stats for every dashboard in the active organization. Includes lifecycle metadata, owner, last tracked modifier, pageviews, edit counts, engagement events, unique viewers, saved view counts, archive/hidden state, and dashboard links. Requires active organization owner/admin role.",
|
|
128
131
|
schema: z.object({}),
|
|
129
132
|
http: { method: "GET" },
|
|
130
133
|
readOnly: true,
|
|
@@ -144,24 +147,120 @@ export default defineAction({
|
|
|
144
147
|
// guard:allow-unscoped — org owner/admin audit intentionally spans all
|
|
145
148
|
// dashboard rows in the active org after requireDbAdminContextFromRequest.
|
|
146
149
|
const dashboardRows = await db
|
|
147
|
-
.select(
|
|
150
|
+
.select({
|
|
151
|
+
id: schema.dashboards.id,
|
|
152
|
+
kind: schema.dashboards.kind,
|
|
153
|
+
title: schema.dashboards.title,
|
|
154
|
+
config: schema.dashboards.config,
|
|
155
|
+
ownerEmail: schema.dashboards.ownerEmail,
|
|
156
|
+
visibility: schema.dashboards.visibility,
|
|
157
|
+
createdAt: schema.dashboards.createdAt,
|
|
158
|
+
updatedAt: schema.dashboards.updatedAt,
|
|
159
|
+
updatedBy: schema.dashboards.updatedBy,
|
|
160
|
+
archivedAt: schema.dashboards.archivedAt,
|
|
161
|
+
hiddenAt: schema.dashboards.hiddenAt,
|
|
162
|
+
hiddenBy: schema.dashboards.hiddenBy,
|
|
163
|
+
})
|
|
148
164
|
.from(schema.dashboards)
|
|
149
165
|
.where(eq(schema.dashboards.orgId, admin.orgId));
|
|
150
166
|
|
|
167
|
+
if (dashboardRows.length === 0) return [];
|
|
168
|
+
|
|
151
169
|
const dashboardIds = new Set<string>(
|
|
152
170
|
dashboardRows.map((row: { id: string }) => row.id),
|
|
153
171
|
);
|
|
154
172
|
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
173
|
+
const analyticsUserIdentity = sql<
|
|
174
|
+
string | null
|
|
175
|
+
>`coalesce(nullif(${schema.analyticsEvents.userKey}, ''), nullif(${schema.analyticsEvents.userId}, ''), nullif(${schema.analyticsEvents.anonymousId}, ''), nullif(${schema.analyticsEvents.sessionId}, ''))`;
|
|
176
|
+
const indexedDashboardEventLocation = or(
|
|
177
|
+
like(schema.analyticsEvents.path, "/dashboards/%"),
|
|
178
|
+
like(schema.analyticsEvents.path, "/adhoc/%"),
|
|
179
|
+
);
|
|
180
|
+
const legacyAbsoluteUrlDashboardEventLocation = and(
|
|
181
|
+
or(
|
|
182
|
+
isNull(schema.analyticsEvents.path),
|
|
183
|
+
eq(schema.analyticsEvents.path, ""),
|
|
184
|
+
),
|
|
185
|
+
or(
|
|
186
|
+
like(schema.analyticsEvents.url, "%/dashboards/%"),
|
|
187
|
+
like(schema.analyticsEvents.url, "%/adhoc/%"),
|
|
188
|
+
),
|
|
189
|
+
);
|
|
190
|
+
const dashboardEventLocation = or(
|
|
191
|
+
indexedDashboardEventLocation,
|
|
192
|
+
legacyAbsoluteUrlDashboardEventLocation,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
const [savedViewRows, revisionRows, eventRows, eventUserRows] =
|
|
196
|
+
await Promise.all([
|
|
197
|
+
db
|
|
198
|
+
.select({
|
|
199
|
+
dashboardId: schema.dashboardViews.dashboardId,
|
|
200
|
+
count: sql<number>`count(*)`,
|
|
201
|
+
lastSavedViewAt: sql<
|
|
202
|
+
string | null
|
|
203
|
+
>`max(${schema.dashboardViews.createdAt})`,
|
|
204
|
+
})
|
|
205
|
+
.from(schema.dashboardViews)
|
|
206
|
+
.innerJoin(
|
|
207
|
+
schema.dashboards,
|
|
208
|
+
and(
|
|
209
|
+
eq(schema.dashboardViews.dashboardId, schema.dashboards.id),
|
|
210
|
+
eq(schema.dashboards.orgId, admin.orgId),
|
|
211
|
+
),
|
|
212
|
+
)
|
|
213
|
+
.groupBy(schema.dashboardViews.dashboardId),
|
|
214
|
+
db
|
|
215
|
+
.select({
|
|
216
|
+
dashboardId: schema.dashboardRevisions.dashboardId,
|
|
217
|
+
count: sql<number>`count(*)`,
|
|
218
|
+
})
|
|
219
|
+
.from(schema.dashboardRevisions)
|
|
220
|
+
.where(eq(schema.dashboardRevisions.orgId, admin.orgId))
|
|
221
|
+
.groupBy(schema.dashboardRevisions.dashboardId),
|
|
222
|
+
db
|
|
223
|
+
.select({
|
|
224
|
+
path: schema.analyticsEvents.path,
|
|
225
|
+
url: schema.analyticsEvents.url,
|
|
226
|
+
eventName: schema.analyticsEvents.eventName,
|
|
227
|
+
count: sql<number>`count(*)`,
|
|
228
|
+
lastSeenAt: sql<
|
|
229
|
+
string | null
|
|
230
|
+
>`max(${schema.analyticsEvents.receivedAt})`,
|
|
231
|
+
})
|
|
232
|
+
.from(schema.analyticsEvents)
|
|
233
|
+
.where(
|
|
234
|
+
and(
|
|
235
|
+
eq(schema.analyticsEvents.orgId, admin.orgId),
|
|
236
|
+
dashboardEventLocation,
|
|
237
|
+
),
|
|
238
|
+
)
|
|
239
|
+
.groupBy(
|
|
240
|
+
schema.analyticsEvents.path,
|
|
241
|
+
schema.analyticsEvents.url,
|
|
242
|
+
schema.analyticsEvents.eventName,
|
|
243
|
+
),
|
|
244
|
+
db
|
|
245
|
+
.select({
|
|
246
|
+
path: schema.analyticsEvents.path,
|
|
247
|
+
url: schema.analyticsEvents.url,
|
|
248
|
+
userIdentity: analyticsUserIdentity,
|
|
249
|
+
})
|
|
250
|
+
.from(schema.analyticsEvents)
|
|
251
|
+
.where(
|
|
252
|
+
and(
|
|
253
|
+
eq(schema.analyticsEvents.orgId, admin.orgId),
|
|
254
|
+
dashboardEventLocation,
|
|
255
|
+
sql`${analyticsUserIdentity} IS NOT NULL`,
|
|
256
|
+
),
|
|
257
|
+
)
|
|
258
|
+
.groupBy(
|
|
259
|
+
schema.analyticsEvents.path,
|
|
260
|
+
schema.analyticsEvents.url,
|
|
261
|
+
analyticsUserIdentity,
|
|
262
|
+
),
|
|
263
|
+
]);
|
|
165
264
|
|
|
166
265
|
const savedViewsByDashboard = new Map<
|
|
167
266
|
string,
|
|
@@ -179,38 +278,15 @@ export default defineAction({
|
|
|
179
278
|
});
|
|
180
279
|
}
|
|
181
280
|
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
userIdentity: analyticsUserIdentity,
|
|
192
|
-
lastSeenAt: sql<
|
|
193
|
-
string | null
|
|
194
|
-
>`max(${schema.analyticsEvents.receivedAt})`,
|
|
195
|
-
})
|
|
196
|
-
.from(schema.analyticsEvents)
|
|
197
|
-
.where(
|
|
198
|
-
and(
|
|
199
|
-
eq(schema.analyticsEvents.orgId, admin.orgId),
|
|
200
|
-
or(
|
|
201
|
-
like(schema.analyticsEvents.path, "%/dashboards/%"),
|
|
202
|
-
like(schema.analyticsEvents.path, "%/adhoc/%"),
|
|
203
|
-
like(schema.analyticsEvents.url, "%/dashboards/%"),
|
|
204
|
-
like(schema.analyticsEvents.url, "%/adhoc/%"),
|
|
205
|
-
),
|
|
206
|
-
),
|
|
207
|
-
)
|
|
208
|
-
.groupBy(
|
|
209
|
-
schema.analyticsEvents.path,
|
|
210
|
-
schema.analyticsEvents.url,
|
|
211
|
-
schema.analyticsEvents.eventName,
|
|
212
|
-
analyticsUserIdentity,
|
|
213
|
-
);
|
|
281
|
+
const editsByDashboard = new Map<string, number>();
|
|
282
|
+
for (const row of revisionRows as Array<{
|
|
283
|
+
dashboardId: string;
|
|
284
|
+
count: unknown;
|
|
285
|
+
}>) {
|
|
286
|
+
if (dashboardIds.has(row.dashboardId)) {
|
|
287
|
+
editsByDashboard.set(row.dashboardId, toNumber(row.count));
|
|
288
|
+
}
|
|
289
|
+
}
|
|
214
290
|
|
|
215
291
|
const eventsByDashboard = new Map<
|
|
216
292
|
string,
|
|
@@ -226,7 +302,6 @@ export default defineAction({
|
|
|
226
302
|
url: string | null;
|
|
227
303
|
eventName: string;
|
|
228
304
|
count: unknown;
|
|
229
|
-
userIdentity: string | null;
|
|
230
305
|
lastSeenAt: string | null;
|
|
231
306
|
}>) {
|
|
232
307
|
const dashboardId = dashboardIdFromEventLocation(row.path, row.url);
|
|
@@ -248,6 +323,22 @@ export default defineAction({
|
|
|
248
323
|
} else {
|
|
249
324
|
current.eventEngagementCount += count;
|
|
250
325
|
}
|
|
326
|
+
eventsByDashboard.set(dashboardId, current);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
for (const row of eventUserRows as Array<{
|
|
330
|
+
path: string | null;
|
|
331
|
+
url: string | null;
|
|
332
|
+
userIdentity: string | null;
|
|
333
|
+
}>) {
|
|
334
|
+
const dashboardId = dashboardIdFromEventLocation(row.path, row.url);
|
|
335
|
+
if (!dashboardId || !dashboardIds.has(dashboardId)) continue;
|
|
336
|
+
const current = eventsByDashboard.get(dashboardId) ?? {
|
|
337
|
+
viewCount: 0,
|
|
338
|
+
eventEngagementCount: 0,
|
|
339
|
+
uniqueUsers: new Set<string>(),
|
|
340
|
+
lastViewedAt: null,
|
|
341
|
+
};
|
|
251
342
|
if (row.userIdentity) current.uniqueUsers.add(row.userIdentity);
|
|
252
343
|
eventsByDashboard.set(dashboardId, current);
|
|
253
344
|
}
|
|
@@ -281,6 +372,7 @@ export default defineAction({
|
|
|
281
372
|
hiddenBy: row.hiddenBy ?? null,
|
|
282
373
|
viewCount: events.viewCount,
|
|
283
374
|
eventEngagementCount: events.eventEngagementCount,
|
|
375
|
+
editCount: editsByDashboard.get(row.id) ?? 0,
|
|
284
376
|
savedViewCount: savedViews.count,
|
|
285
377
|
engagementCount: events.eventEngagementCount + savedViews.count,
|
|
286
378
|
uniqueUserCount: events.uniqueUsers.size,
|
|
@@ -293,6 +385,8 @@ export default defineAction({
|
|
|
293
385
|
.sort((a, b) => {
|
|
294
386
|
const views = b.viewCount - a.viewCount;
|
|
295
387
|
if (views !== 0) return views;
|
|
388
|
+
const edits = b.editCount - a.editCount;
|
|
389
|
+
if (edits !== 0) return edits;
|
|
296
390
|
return b.updatedAt.localeCompare(a.updatedAt);
|
|
297
391
|
});
|
|
298
392
|
},
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core/action";
|
|
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";
|
|
9
|
+
import {
|
|
10
|
+
migrateAnalyticsArtifacts,
|
|
11
|
+
type AnalyticsArtifactMigrationContext,
|
|
12
|
+
} from "../server/lib/migrate-analytics-artifacts.js";
|
|
13
|
+
|
|
14
|
+
const confirmation = "MIGRATE_ANALYTICS_ARTIFACTS" as const;
|
|
15
|
+
|
|
16
|
+
export default defineAction({
|
|
17
|
+
description:
|
|
18
|
+
"Inventory or consolidate all organization-scoped Analytics dashboards, saved analyses, and extensions into the canonical Dashboards list. The default is a read-only dry run. A write requires an organization owner/admin and confirm=MIGRATE_ANALYTICS_ARTIFACTS; exact duplicates are archived/hidden, source rows remain recoverable, shares are copied, and legacy settings keys are removed only after SQL materialization.",
|
|
19
|
+
schema: z.object({
|
|
20
|
+
dryRun: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.optional()
|
|
23
|
+
.default(true)
|
|
24
|
+
.describe("Inspect the migration without writing when true (default)."),
|
|
25
|
+
confirm: z
|
|
26
|
+
.literal(confirmation)
|
|
27
|
+
.optional()
|
|
28
|
+
.describe(
|
|
29
|
+
"Required for writes: MIGRATE_ANALYTICS_ARTIFACTS. Do not send this for a dry run.",
|
|
30
|
+
),
|
|
31
|
+
}),
|
|
32
|
+
needsApproval: ({ dryRun }) => !dryRun,
|
|
33
|
+
run: async ({ dryRun, confirm }, ctx) => {
|
|
34
|
+
const userEmail = getRequestUserEmail() || ctx?.userEmail;
|
|
35
|
+
const orgId = getRequestOrgId() || ctx?.orgId || null;
|
|
36
|
+
const admin = await requireAnalyticsAdminContext({ userEmail, orgId });
|
|
37
|
+
if (!dryRun && confirm !== confirmation) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Refusing the Analytics organization migration without confirm=${confirmation}. Run a dry run first, then repeat with the exact confirmation token.`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
const migrationContext: AnalyticsArtifactMigrationContext = {
|
|
43
|
+
userEmail: admin.userEmail,
|
|
44
|
+
orgId: admin.orgId,
|
|
45
|
+
};
|
|
46
|
+
return migrateAnalyticsArtifacts(migrationContext, { dryRun });
|
|
47
|
+
},
|
|
48
|
+
});
|
|
@@ -113,9 +113,8 @@ function assertCompactAnalysisPayload(args: {
|
|
|
113
113
|
|
|
114
114
|
export default defineAction({
|
|
115
115
|
description:
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"Saved analyses appear in the Analyses sidebar, so do not use this as scratch storage, as a transient summary, or as a duplicate companion artifact when creating a dashboard or extension unless the user explicitly asked for a saved analysis too. " +
|
|
116
|
+
"Legacy compatibility only: use this to re-run or update an existing saved analysis when the user explicitly names its legacy analysis id or asks to preserve that legacy record. Do not call this to create a new saved analysis, report, visualization, or bespoke workflow; new requests become dashboards, using update-dashboard and embedding any bespoke extension as one or more dashboard panels. Stores the legacy analysis question, instructions for re-running, data sources used, and compact results. " +
|
|
117
|
+
"Do not use this as scratch storage, a transient summary, or a duplicate companion artifact for a dashboard. " +
|
|
119
118
|
"Call this only after you've gathered real evidence and include non-empty, compact resultData with structured evidence from those data-source action results. For qualitative analyses, resultData may include call/message IDs, short transcript excerpts, coded themes, mention counts, and sentiment labels derived from actual source records. Never include full Gong transcripts, full tool outputs, or bulk raw provider payloads.",
|
|
120
119
|
schema: z.object({
|
|
121
120
|
id: z
|
|
@@ -438,7 +438,7 @@ export default defineAction({
|
|
|
438
438
|
includes: [
|
|
439
439
|
"dashboard created and modified dates",
|
|
440
440
|
"last tracked modifier",
|
|
441
|
-
"view and engagement counts",
|
|
441
|
+
"view, edit, and engagement counts",
|
|
442
442
|
"saved view counts",
|
|
443
443
|
"hidden and archived state",
|
|
444
444
|
],
|