@agent-native/core 0.141.6 → 0.144.0

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.
Files changed (501) hide show
  1. package/agent-native.eject.json +9 -0
  2. package/corpus/README.md +1 -1
  3. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +3 -14
  4. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +11 -6
  5. package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +5 -5
  6. package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +19 -0
  7. package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +296 -0
  8. package/corpus/templates/analytics/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  9. package/corpus/templates/analytics/.agents/skills/turn-into-skill/SKILL.md +112 -0
  10. package/corpus/templates/analytics/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  11. package/corpus/templates/analytics/AGENTS.md +37 -40
  12. package/corpus/templates/analytics/actions/compose-dashboard.ts +1 -1
  13. package/corpus/templates/analytics/actions/ensure-native-v2-dashboards.ts +1 -1
  14. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +17 -22
  15. package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +135 -0
  16. package/corpus/templates/analytics/actions/navigate.ts +5 -6
  17. package/corpus/templates/analytics/actions/provider-api-register.ts +50 -0
  18. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +46 -13
  19. package/corpus/templates/analytics/actions/test-custom-api-connection.ts +106 -0
  20. package/corpus/templates/analytics/actions/update-dashboard.ts +0 -1
  21. package/corpus/templates/analytics/actions/view-screen.ts +0 -20
  22. package/corpus/templates/analytics/app/components/CustomApiCard.tsx +430 -0
  23. package/corpus/templates/analytics/app/components/layout/Header.tsx +0 -1
  24. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +5 -5
  25. package/corpus/templates/analytics/app/i18n-data.ts +682 -90
  26. package/corpus/templates/analytics/app/lib/native-mcp-exclusions.ts +6 -0
  27. package/corpus/templates/analytics/app/lib/sql-query.ts +33 -6
  28. package/corpus/templates/analytics/app/pages/Agents.tsx +0 -3
  29. package/corpus/templates/analytics/app/pages/DataSources.tsx +4 -0
  30. package/corpus/templates/analytics/app/pages/Settings.tsx +22 -43
  31. package/corpus/templates/analytics/app/pages/settings/settings-search.ts +23 -20
  32. package/corpus/templates/analytics/app/routes/extensions._index.tsx +1 -1
  33. package/corpus/templates/analytics/app/routes/settings.$.tsx +1 -0
  34. package/corpus/templates/analytics/app/routes/team.tsx +1 -1
  35. package/corpus/templates/analytics/changelog/2026-08-05-settings-no-longer-includes-an-unnecessary-about-section.md +6 -0
  36. package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-load-reliably-during-background-data-sw.md +6 -0
  37. package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-remain-responsive-while-historical-data.md +6 -0
  38. package/corpus/templates/analytics/changelog/2026-08-06-analytics-query-results-now-render-as-a-table-with-csv-downl.md +6 -0
  39. package/corpus/templates/analytics/changelog/2026-08-06-connect-public-https-custom-apis-and-hand-tested-endpoints-t.md +6 -0
  40. package/corpus/templates/analytics/changelog/2026-08-06-durable-agent-worker-memory.md +6 -0
  41. package/corpus/templates/analytics/changelog/2026-08-06-live-dashboard-panels-use-the-shared-query-timeout.md +6 -0
  42. package/corpus/templates/analytics/changelog/2026-08-06-on-demand-billing-is-available-as-a-native-dashboard-with-ta.md +6 -0
  43. package/corpus/templates/analytics/changelog/2026-08-06-visible-dashboard-names-are-unique.md +6 -0
  44. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +1 -1
  45. package/corpus/templates/analytics/netlify.toml +7 -0
  46. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +4 -0
  47. package/corpus/templates/analytics/scripts/first-party-analytics-bigquery.sql +104 -0
  48. package/corpus/templates/analytics/server/db/index.ts +27 -0
  49. package/corpus/templates/analytics/server/db/schema.ts +10 -0
  50. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -2
  51. package/corpus/templates/analytics/server/lib/dashboards-store.ts +227 -60
  52. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +1147 -0
  53. package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +34 -15
  54. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +57 -4
  55. package/corpus/templates/analytics/server/lib/native-v2-dashboards.ts +227 -1
  56. package/corpus/templates/analytics/server/lib/real-data-actions.ts +1 -3
  57. package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -4
  58. package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +1 -0
  59. package/corpus/templates/analytics/server/plugins/db.ts +52 -18
  60. package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +36 -8
  61. package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +16 -1
  62. package/corpus/templates/assets/.agents/skills/library-management/SKILL.md +16 -1
  63. package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +296 -0
  64. package/corpus/templates/assets/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  65. package/corpus/templates/assets/.agents/skills/turn-into-skill/SKILL.md +112 -0
  66. package/corpus/templates/assets/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  67. package/corpus/templates/assets/AGENTS.md +1 -0
  68. package/corpus/templates/assets/actions/_helpers.ts +12 -0
  69. package/corpus/templates/assets/actions/generate-image.ts +9 -3
  70. package/corpus/templates/assets/actions/import-style-from-url.ts +115 -0
  71. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +3 -1
  72. package/corpus/templates/assets/app/routes/extensions._index.tsx +1 -1
  73. package/corpus/templates/assets/app/routes/settings.$.tsx +1 -0
  74. package/corpus/templates/assets/app/routes/settings.tsx +5 -0
  75. package/corpus/templates/assets/app/routes/team.tsx +1 -1
  76. package/corpus/templates/assets/changelog/2026-08-05-brand-kits-can-import-a-website-s-hydrated-visual-language-a.md +6 -0
  77. package/corpus/templates/assets/changelog/2026-08-05-generated-images-now-hand-off-embeddable-previews-to-other-w.md +6 -0
  78. package/corpus/templates/assets/server/lib/generation.ts +58 -0
  79. package/corpus/templates/assets/shared/api.ts +12 -0
  80. package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +296 -0
  81. package/corpus/templates/brain/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  82. package/corpus/templates/brain/.agents/skills/turn-into-skill/SKILL.md +112 -0
  83. package/corpus/templates/brain/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  84. package/corpus/templates/brain/actions/list-connection-providers.ts +24 -3
  85. package/corpus/templates/brain/app/lib/dispatch-links.ts +44 -0
  86. package/corpus/templates/brain/app/routes/extensions._index.tsx +1 -1
  87. package/corpus/templates/brain/app/routes/sources.tsx +15 -7
  88. package/corpus/templates/brain/app/routes/team.tsx +1 -1
  89. package/corpus/templates/brain/app/routes.ts +1 -1
  90. package/corpus/templates/brain/changelog/2026-08-06-brain-provider-setup-links-open-dispatch-correctly-in-standa.md +6 -0
  91. package/corpus/templates/brain/server/plugins/agent-chat.ts +1 -0
  92. package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +26 -0
  93. package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +296 -0
  94. package/corpus/templates/calendar/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  95. package/corpus/templates/calendar/.agents/skills/turn-into-skill/SKILL.md +112 -0
  96. package/corpus/templates/calendar/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  97. package/corpus/templates/calendar/AGENTS.md +11 -32
  98. package/corpus/templates/calendar/actions/update-event.ts +107 -1
  99. package/corpus/templates/calendar/app/components/calendar/EventCalendarSelect.tsx +83 -0
  100. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +57 -0
  101. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +59 -73
  102. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +3 -1
  103. package/corpus/templates/calendar/app/hooks/use-events.ts +4 -1
  104. package/corpus/templates/calendar/app/i18n-data.ts +20 -0
  105. package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +1 -1
  106. package/corpus/templates/calendar/app/routes/_app.settings.$.tsx +1 -0
  107. package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
  108. package/corpus/templates/calendar/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
  109. package/corpus/templates/calendar/changelog/2026-08-06-existing-events-can-move-between-connected-google-account-ca.md +6 -0
  110. package/corpus/templates/calendar/server/lib/google-calendar.ts +101 -0
  111. package/corpus/templates/calendar/server/plugins/agent-chat.ts +7 -1
  112. package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
  113. package/corpus/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  114. package/corpus/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
  115. package/corpus/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  116. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
  117. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  118. package/corpus/templates/chat/app/root.tsx +1 -1
  119. package/corpus/templates/chat/app/routes/agent.tsx +7 -7
  120. package/corpus/templates/chat/app/routes/extensions._index.tsx +1 -1
  121. package/corpus/templates/chat/app/routes/settings.$.tsx +1 -0
  122. package/corpus/templates/chat/app/routes/team.tsx +1 -1
  123. package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +296 -0
  124. package/corpus/templates/clips/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  125. package/corpus/templates/clips/.agents/skills/turn-into-skill/SKILL.md +112 -0
  126. package/corpus/templates/clips/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  127. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +9 -24
  128. package/corpus/templates/clips/app/components/editor/timeline-geometry.ts +15 -0
  129. package/corpus/templates/clips/app/components/editor/waveform.tsx +4 -17
  130. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  131. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +14 -3
  132. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +1 -1
  133. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +1 -1
  134. package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +1 -1
  135. package/corpus/templates/clips/app/routes/_app.settings.$.tsx +1 -0
  136. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +28 -38
  137. package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -27
  138. package/corpus/templates/clips/changelog/2026-08-06-clips-recovers-from-stalled-recording-setup-without-requirin.md +6 -0
  139. package/corpus/templates/clips/changelog/2026-08-06-clips-starts-faster-after-a-deploy-or-idle-period-startup-no.md +6 -0
  140. package/corpus/templates/clips/changelog/2026-08-06-deleting-a-recording-returns-cleanly-to-the-library-and-fit-.md +6 -0
  141. package/corpus/templates/clips/changelog/2026-08-06-hide-clip-insights-from-viewers-without-analytics-access.md +6 -0
  142. package/corpus/templates/clips/desktop/src/app.tsx +48 -20
  143. package/corpus/templates/clips/desktop/src/lib/recorder.ts +275 -74
  144. package/corpus/templates/clips/desktop/src/lib/recording-start-guard.ts +84 -0
  145. package/corpus/templates/clips/desktop/src/overlays/toolbar.tsx +14 -4
  146. package/corpus/templates/clips/server/plugins/db.ts +214 -26
  147. package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +296 -0
  148. package/corpus/templates/content/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  149. package/corpus/templates/content/.agents/skills/turn-into-skill/SKILL.md +112 -0
  150. package/corpus/templates/content/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  151. package/corpus/templates/content/app/routes/_app.extensions._index.tsx +1 -1
  152. package/corpus/templates/content/app/routes/_app.settings.$.tsx +1 -0
  153. package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
  154. package/corpus/templates/content/e2e/global-setup.ts +1 -1
  155. package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +296 -0
  156. package/corpus/templates/crm/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  157. package/corpus/templates/crm/.agents/skills/turn-into-skill/SKILL.md +112 -0
  158. package/corpus/templates/crm/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  159. package/corpus/templates/crm/changelog/2026-08-06-crm-starts-faster-after-a-deploy-or-idle-period-one-time-dat.md +6 -0
  160. package/corpus/templates/crm/server/plugins/db.ts +11 -8
  161. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +36 -1
  162. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +6 -1
  163. package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +296 -0
  164. package/corpus/templates/design/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  165. package/corpus/templates/design/.agents/skills/turn-into-skill/SKILL.md +112 -0
  166. package/corpus/templates/design/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  167. package/corpus/templates/design/actions/analyze-brand-assets.ts +7 -7
  168. package/corpus/templates/design/actions/import-from-url.ts +6 -5
  169. package/corpus/templates/design/app/components/design/LayersPanel.tsx +27 -18
  170. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +2 -2
  171. package/corpus/templates/design/app/pages/Index.tsx +6 -2
  172. package/corpus/templates/design/app/routes/extensions._index.tsx +1 -1
  173. package/corpus/templates/design/app/routes/settings.$.tsx +1 -0
  174. package/corpus/templates/design/app/routes/team.tsx +1 -1
  175. package/corpus/templates/design/changelog/2026-08-05-deleting-a-design-from-the-home-page-no-longer-leaves-the-ap.md +6 -0
  176. package/corpus/templates/design/changelog/2026-08-05-renaming-a-layer-now-focuses-its-name-field-automatically.md +6 -0
  177. package/corpus/templates/design/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-de.md +6 -0
  178. package/corpus/templates/design/e2e/global-setup.ts +1 -1
  179. package/corpus/templates/design/server/plugins/agent-chat.ts +2 -0
  180. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +296 -0
  181. package/corpus/templates/dispatch/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  182. package/corpus/templates/dispatch/.agents/skills/turn-into-skill/SKILL.md +112 -0
  183. package/corpus/templates/dispatch/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  184. package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
  185. package/corpus/templates/dispatch/app/routes/settings.$.tsx +1 -0
  186. package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
  187. package/corpus/templates/dispatch/changelog/2026-08-06-ready-workspace-apps-stay-one-click-away-in-a-compact-dispat.md +6 -0
  188. package/corpus/templates/dispatch/changelog/2026-08-06-shared-vault-values-and-management-are-now-restricted-to-wor.md +6 -0
  189. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +296 -0
  190. package/corpus/templates/factory/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  191. package/corpus/templates/factory/.agents/skills/turn-into-skill/SKILL.md +112 -0
  192. package/corpus/templates/factory/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  193. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +1 -1
  194. package/corpus/templates/factory/app/routes/extensions._index.tsx +1 -1
  195. package/corpus/templates/factory/app/routes/settings.$.tsx +1 -0
  196. package/corpus/templates/factory/app/routes/team.tsx +1 -1
  197. package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +296 -0
  198. package/corpus/templates/forms/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  199. package/corpus/templates/forms/.agents/skills/turn-into-skill/SKILL.md +112 -0
  200. package/corpus/templates/forms/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  201. package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +1 -1
  202. package/corpus/templates/forms/app/routes/_app.settings.$.tsx +1 -0
  203. package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
  204. package/corpus/templates/forms/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
  205. package/corpus/templates/forms/server/plugins/agent-chat.ts +4 -0
  206. package/corpus/templates/forms/shared/navigation.ts +1 -1
  207. package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +296 -0
  208. package/corpus/templates/macros/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  209. package/corpus/templates/macros/.agents/skills/turn-into-skill/SKILL.md +112 -0
  210. package/corpus/templates/macros/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  211. package/corpus/templates/macros/app/routes/extensions._index.tsx +1 -1
  212. package/corpus/templates/macros/app/routes/settings.$.tsx +1 -0
  213. package/corpus/templates/macros/app/routes/team.tsx +1 -1
  214. package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +296 -0
  215. package/corpus/templates/mail/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  216. package/corpus/templates/mail/.agents/skills/turn-into-skill/SKILL.md +112 -0
  217. package/corpus/templates/mail/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  218. package/corpus/templates/mail/app/routes/extensions._index.tsx +1 -1
  219. package/corpus/templates/mail/app/routes/settings.$.tsx +1 -0
  220. package/corpus/templates/mail/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
  221. package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
  222. package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +296 -0
  223. package/corpus/templates/plan/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  224. package/corpus/templates/plan/.agents/skills/turn-into-skill/SKILL.md +112 -0
  225. package/corpus/templates/plan/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  226. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
  227. package/corpus/templates/plan/app/routes/extensions._index.tsx +1 -1
  228. package/corpus/templates/plan/app/routes/settings.$.tsx +1 -0
  229. package/corpus/templates/plan/app/routes/team.tsx +1 -1
  230. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +48 -5
  231. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +40 -2
  232. package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +6 -0
  233. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +15 -2
  234. package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +29 -24
  235. package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +296 -0
  236. package/corpus/templates/slides/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  237. package/corpus/templates/slides/.agents/skills/turn-into-skill/SKILL.md +112 -0
  238. package/corpus/templates/slides/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  239. package/corpus/templates/slides/AGENTS.md +7 -9
  240. package/corpus/templates/slides/_gitignore +1 -0
  241. package/corpus/templates/slides/actions/analyze-brand-assets.ts +7 -7
  242. package/corpus/templates/slides/actions/export-pptx.ts +402 -36
  243. package/corpus/templates/slides/actions/import-file.ts +46 -85
  244. package/corpus/templates/slides/actions/import-from-url.ts +6 -6
  245. package/corpus/templates/slides/actions/import-google-slides-reference.ts +271 -12
  246. package/corpus/templates/slides/actions/import-pptx.ts +85 -60
  247. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +10 -13
  248. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +1 -1
  249. package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +5 -1
  250. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +25 -12
  251. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +112 -57
  252. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +202 -0
  253. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +26 -14
  254. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +176 -0
  255. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +182 -141
  256. package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
  257. package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +18 -0
  258. package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +85 -0
  259. package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -0
  260. package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +13 -3
  261. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +27 -1
  262. package/corpus/templates/slides/app/context/DeckContext.tsx +71 -20
  263. package/corpus/templates/slides/app/global.css +6 -0
  264. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  265. package/corpus/templates/slides/app/lib/create-deck-generation.ts +10 -6
  266. package/corpus/templates/slides/app/lib/deck-preview-frame.ts +15 -0
  267. package/corpus/templates/slides/app/lib/deck-share-links.ts +9 -0
  268. package/corpus/templates/slides/app/lib/export-pptx-client.ts +89 -0
  269. package/corpus/templates/slides/app/lib/slide-animation-elements.ts +3 -0
  270. package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -0
  271. package/corpus/templates/slides/app/pages/Index.tsx +107 -6
  272. package/corpus/templates/slides/app/routes/extensions._index.tsx +1 -1
  273. package/corpus/templates/slides/app/routes/settings.$.tsx +1 -0
  274. package/corpus/templates/slides/app/routes/team.tsx +1 -1
  275. package/corpus/templates/slides/changelog/2026-08-05-failed-deck-creation-and-reference-uploads-now-recover-clean.md +6 -0
  276. package/corpus/templates/slides/changelog/2026-08-05-slides-recover-completed-generation-results-after-a-sync-hic.md +6 -0
  277. package/corpus/templates/slides/changelog/2026-08-05-website-url-imports-now-capture-hydrated-browser-computed-st.md +6 -0
  278. package/corpus/templates/slides/changelog/2026-08-06-clicking-the-gray-canvas-around-a-slide-clears-its-selection.md +6 -0
  279. package/corpus/templates/slides/changelog/2026-08-06-deck-thumbnails-keep-a-consistent-listing-frame-across-aspec.md +6 -0
  280. package/corpus/templates/slides/changelog/2026-08-06-deep-linked-decks-open-directly-instead-of-being-interrupted.md +6 -0
  281. package/corpus/templates/slides/changelog/2026-08-06-google-slides-exports-now-show-clear-import-steps-when-direc.md +6 -0
  282. package/corpus/templates/slides/changelog/2026-08-06-import-pdf-google-slides-and-powerpoint-decks-directly-from-.md +6 -0
  283. package/corpus/templates/slides/changelog/2026-08-06-imported-powerpoint-exports-keep-text-and-images-editable-an.md +6 -0
  284. package/corpus/templates/slides/changelog/2026-08-06-presentation-prompts-continue-adding-rendered-slides-until-t.md +6 -0
  285. package/corpus/templates/slides/changelog/2026-08-06-public-decks-now-share-read-only-presentation-links-by-defau.md +6 -0
  286. package/corpus/templates/slides/changelog/2026-08-06-slides-offers-a-direct-connect-google-button-when-a-drive-co.md +6 -0
  287. package/corpus/templates/slides/changelog/2026-08-06-slides-preserve-uploaded-pdf-layouts-accept-larger-reference.md +6 -0
  288. package/corpus/templates/slides/changelog/2026-08-06-styled-words-stay-part-of-their-text-box-instead-of-becoming.md +6 -0
  289. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +7 -20
  290. package/corpus/templates/slides/server/handlers/import/html-converter.ts +236 -13
  291. package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +67 -0
  292. package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +2 -0
  293. package/corpus/templates/slides/server/handlers/uploads.ts +7 -3
  294. package/corpus/templates/slides/server/lib/chat-attachments.ts +6 -3
  295. package/corpus/templates/slides/server/lib/emails.ts +7 -2
  296. package/corpus/templates/slides/server/lib/google-docs-error.ts +50 -0
  297. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +1 -0
  298. package/corpus/templates/slides/server/lib/import-asset-storage.ts +127 -0
  299. package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -3
  300. package/corpus/templates/slides/server/routes/api/import-assets/[token].get.ts +70 -0
  301. package/corpus/templates/slides/shared/upload-types.ts +3 -0
  302. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +296 -0
  303. package/corpus/templates/tasks/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  304. package/corpus/templates/tasks/.agents/skills/turn-into-skill/SKILL.md +112 -0
  305. package/corpus/templates/tasks/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  306. package/corpus/templates/tasks/app/components/layout/Header.tsx +3 -1
  307. package/corpus/templates/tasks/app/routes/extensions._index.tsx +1 -1
  308. package/corpus/templates/tasks/app/routes/settings.$.tsx +1 -0
  309. package/dist/agent/engine/ai-sdk-engine.js +49 -3
  310. package/dist/agent/production-agent.d.ts +18 -0
  311. package/dist/agent/production-agent.js +80 -1
  312. package/dist/agent/types.d.ts +7 -0
  313. package/dist/cli/agent-plugin.d.ts +112 -0
  314. package/dist/cli/agent-plugin.js +1081 -0
  315. package/dist/cli/app-skill.js +39 -1
  316. package/dist/cli/code-agent-executor.d.ts +3 -0
  317. package/dist/cli/code-agent-executor.js +51 -13
  318. package/dist/cli/index.js +13 -0
  319. package/dist/cli/templates-meta.js +1 -1
  320. package/dist/client/AgentPanel.d.ts +3 -1
  321. package/dist/client/AgentPanel.js +9 -2
  322. package/dist/client/AssistantChat.d.ts +8 -0
  323. package/dist/client/AssistantChat.js +23 -8
  324. package/dist/client/NewWorkspaceAppFlow.js +1 -0
  325. package/dist/client/agent-chat-adapter.d.ts +1 -1
  326. package/dist/client/agent-chat-adapter.js +153 -7
  327. package/dist/client/agent-page/AgentWorkspaceContent.d.ts +1 -1
  328. package/dist/client/agent-page/AgentWorkspaceContent.js +13 -13
  329. package/dist/client/assistant-ui-recovery.d.ts +2 -1
  330. package/dist/client/assistant-ui-recovery.js +7 -3
  331. package/dist/client/chat/run-recovery.js +5 -1
  332. package/dist/client/embed-auth.js +6 -2
  333. package/dist/client/error-format.js +12 -0
  334. package/dist/client/integrations/IntegrationsPanel.js +40 -6
  335. package/dist/client/onboarding/FirstRunOnboarding.js +11 -4
  336. package/dist/client/org/OrgSwitcher.js +2 -2
  337. package/dist/client/org/TeamPage.js +92 -72
  338. package/dist/client/require-session.d.ts +1 -1
  339. package/dist/client/require-session.js +4 -4
  340. package/dist/client/resources/McpConnectionSuggestion.d.ts +1 -0
  341. package/dist/client/resources/McpConnectionSuggestion.js +27 -10
  342. package/dist/client/resources/McpIntegrationDialog.js +77 -45
  343. package/dist/client/resources/mcp-integration-catalog.d.ts +13 -1
  344. package/dist/client/resources/mcp-integration-catalog.js +255 -2
  345. package/dist/client/resources/mcp-integration-logos.js +18 -2
  346. package/dist/client/resources/use-mcp-servers.d.ts +5 -0
  347. package/dist/client/resources/use-mcp-servers.js +36 -0
  348. package/dist/client/settings/AccountSettingsCard.js +42 -36
  349. package/dist/client/settings/AutomationsSection.js +1 -1
  350. package/dist/client/settings/DemoModeSection.d.ts +3 -1
  351. package/dist/client/settings/DemoModeSection.js +4 -1
  352. package/dist/client/settings/ExtensionsSettingsContent.js +1 -1
  353. package/dist/client/settings/SchedulingTimezoneField.d.ts +3 -1
  354. package/dist/client/settings/SchedulingTimezoneField.js +9 -5
  355. package/dist/client/settings/SettingsPanel.d.ts +4 -1
  356. package/dist/client/settings/SettingsPanel.js +21 -21
  357. package/dist/client/settings/SettingsTabsPage.d.ts +2 -2
  358. package/dist/client/settings/SettingsTabsPage.js +98 -45
  359. package/dist/client/settings/VoiceTranscriptionSection.js +6 -1
  360. package/dist/client/settings/useSettingsPanelController.js +47 -8
  361. package/dist/collab/routes.d.ts +1 -1
  362. package/dist/db/client.d.ts +9 -0
  363. package/dist/db/client.js +51 -16
  364. package/dist/db/create-get-db.js +2 -2
  365. package/dist/db/ddl-guard.d.ts +11 -10
  366. package/dist/db/ddl-guard.js +40 -12
  367. package/dist/deploy/build.d.ts +2 -0
  368. package/dist/deploy/build.js +97 -4
  369. package/dist/deploy/workspace-deploy.js +0 -2
  370. package/dist/guards/no-env-credentials.js +9 -0
  371. package/dist/ingestion/index.d.ts +1 -1
  372. package/dist/ingestion/pptx.d.ts +68 -0
  373. package/dist/ingestion/pptx.js +660 -213
  374. package/dist/ingestion/website.d.ts +30 -0
  375. package/dist/integrations/plugin.js +9 -6
  376. package/dist/localization/default-messages.d.ts +59 -0
  377. package/dist/localization/default-messages.js +62 -2
  378. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  379. package/dist/mcp-client/oauth-routes.d.ts +2 -0
  380. package/dist/mcp-client/oauth-routes.js +74 -7
  381. package/dist/mcp-client/routes.d.ts +1 -0
  382. package/dist/mcp-client/routes.js +49 -0
  383. package/dist/navigation/index.js +16 -5
  384. package/dist/notifications/routes.d.ts +1 -1
  385. package/dist/observability/routes.d.ts +3 -3
  386. package/dist/onboarding/app-profile.js +11 -0
  387. package/dist/progress/routes.d.ts +1 -1
  388. package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
  389. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  390. package/dist/resources/store.js +15 -1
  391. package/dist/scripts/call-agent.js +45 -4
  392. package/dist/secrets/routes.d.ts +6 -6
  393. package/dist/server/agent-chat/action-filters-a2a.d.ts +1 -1
  394. package/dist/server/agent-chat/action-filters-a2a.js +36 -1
  395. package/dist/server/agent-chat-plugin.js +29 -8
  396. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  397. package/dist/server/auth.js +55 -17
  398. package/dist/server/better-auth-instance.js +5 -3
  399. package/dist/server/core-routes-plugin.d.ts +8 -1
  400. package/dist/server/core-routes-plugin.js +28 -3
  401. package/dist/server/credential-provider.d.ts +3 -3
  402. package/dist/server/credential-provider.js +90 -4
  403. package/dist/server/identity-sso.js +2 -1
  404. package/dist/server/onboarding-html.d.ts +2 -0
  405. package/dist/server/onboarding-html.js +171 -62
  406. package/dist/server/realtime-token.d.ts +1 -1
  407. package/dist/server/self-dispatch.d.ts +5 -4
  408. package/dist/server/self-dispatch.js +25 -14
  409. package/dist/server/ssr-handler.d.ts +1 -1
  410. package/dist/server/ssr-handler.js +1 -1
  411. package/dist/server/workspace-provider-oauth.js +1 -1
  412. package/dist/setup-connections/onboarding.js +1 -1
  413. package/dist/shared/cache-control.d.ts +26 -2
  414. package/dist/shared/cache-control.js +43 -2
  415. package/dist/shared/index.d.ts +1 -1
  416. package/dist/shared/index.js +1 -1
  417. package/dist/shared/password-policy.d.ts +3 -0
  418. package/dist/shared/password-policy.js +3 -0
  419. package/dist/shared/sign-in-journey.d.ts +5 -2
  420. package/dist/shared/sign-in-journey.js +10 -4
  421. package/dist/sharing/actions/set-resource-visibility.js +16 -4
  422. package/dist/sharing/registry.d.ts +14 -0
  423. package/dist/styles/agent-native.css +6 -0
  424. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
  425. package/dist/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  426. package/dist/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
  427. package/dist/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  428. package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
  429. package/dist/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  430. package/dist/templates/chat/app/root.tsx +1 -1
  431. package/dist/templates/chat/app/routes/agent.tsx +7 -7
  432. package/dist/templates/chat/app/routes/extensions._index.tsx +1 -1
  433. package/dist/templates/chat/app/routes/settings.$.tsx +1 -0
  434. package/dist/templates/chat/app/routes/team.tsx +1 -1
  435. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
  436. package/dist/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  437. package/dist/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
  438. package/dist/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  439. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
  440. package/dist/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  441. package/dist/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
  442. package/dist/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  443. package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
  444. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
  445. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
  446. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
  447. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
  448. package/dist/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  449. package/dist/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
  450. package/dist/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  451. package/dist/templates/workspace-root/AGENTS.md +7 -0
  452. package/dist/user-profile/actions/change-password.js +8 -3
  453. package/dist/user-profile/actions/set-password.js +5 -1
  454. package/dist/vite/action-types-plugin.js +59 -0
  455. package/docs/content/authentication.mdx +4 -5
  456. package/docs/content/skills-guide.mdx +13 -0
  457. package/docs/content/template-analytics-developers.mdx +1 -1
  458. package/docs/content/template-calendar-developers.mdx +1 -1
  459. package/docs/content/template-chat-developers.mdx +2 -2
  460. package/docs/content/template-content-developers.mdx +1 -1
  461. package/docs/content/template-mail-developers.mdx +1 -1
  462. package/docs/content/template-plan-developers.mdx +1 -1
  463. package/docs/content/toolkit-command-navigation.mdx +6 -6
  464. package/docs/content/toolkit-org-team.mdx +1 -1
  465. package/docs/content/toolkit-settings.mdx +8 -8
  466. package/docs/content/toolkit-setup-connections.mdx +1 -1
  467. package/package.json +6 -2
  468. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
  469. package/src/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  470. package/src/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
  471. package/src/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  472. package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
  473. package/src/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  474. package/src/templates/chat/app/root.tsx +1 -1
  475. package/src/templates/chat/app/routes/agent.tsx +7 -7
  476. package/src/templates/chat/app/routes/extensions._index.tsx +1 -1
  477. package/src/templates/chat/app/routes/settings.$.tsx +1 -0
  478. package/src/templates/chat/app/routes/team.tsx +1 -1
  479. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
  480. package/src/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  481. package/src/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
  482. package/src/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  483. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
  484. package/src/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  485. package/src/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
  486. package/src/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  487. package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
  488. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +37 -6
  489. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +4 -2
  490. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
  491. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
  492. package/src/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  493. package/src/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
  494. package/src/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  495. package/src/templates/workspace-root/AGENTS.md +7 -0
  496. package/corpus/templates/analytics/.agents/skills/dashboard-management/references/template-catalog-and-demo.md +0 -62
  497. package/corpus/templates/analytics/actions/install-dashboard-template.ts +0 -369
  498. package/corpus/templates/analytics/actions/list-dashboard-templates.ts +0 -47
  499. package/corpus/templates/analytics/actions/list-native-v2-dashboard-templates.ts +0 -34
  500. package/corpus/templates/analytics/app/routes/catalog.tsx +0 -240
  501. package/src/templates/default/actions/navigate.spec.ts +0 -53
@@ -1,50 +1,41 @@
1
1
  # Analytics — Agent Guide
2
2
 
3
- Analytics is an agent-native BI workspace for data sources, queries, dashboards,
4
- charts, and warehouse integrations. Dashboards are the canonical user-facing
5
- artifact; legacy analyses remain readable only for compatibility.
3
+ Analytics is an agent-native BI workspace for sources, queries, dashboards,
4
+ charts, and warehouse integrations. Dashboards are canonical; legacy analyses
5
+ remain readable for compatibility.
6
6
 
7
- Use all connected sources and MCP tools; reason over fetched data here, and do
8
- not suggest another AI tool.
7
+ Use connected sources and MCP tools; reason over fetched data here, not via
8
+ another AI tool.
9
9
 
10
10
  Prompt cap: 6,000; put detail in `.agents/skills/*`.
11
11
 
12
- Before building common workspace or agent UI, read `agent-native-toolkit`; use
13
- `customizing-agent-native` for the configure → compose → eject → propose
14
- ladder.
12
+ Before building common workspace or agent UI, read `agent-native-toolkit` to
13
+ discover existing primitives and patterns. Read `customizing-agent-native`
14
+ before adapting shared UI: configure → compose → eject → propose.
15
15
 
16
16
  ## How To Answer A Data Question
17
17
 
18
- 1. **Search existing work first.** Call `search-analytics-query-catalog` before
19
- writing a query. Adapt the closest saved SQL to the requested filters and
20
- window, run it once, and stop.
21
- 2. **One bounded call.** List, filter, count, and cohort questions ("which X,
22
- excluding Y") are a single SQL statement, or one `run-code` script that
23
- filters server-side. Never page through a cohort or fan out per item to apply
24
- a filter.
25
- 3. **Escalate only on a miss.** If the catalog returns nothing usable, make at
26
- most one discovery pass (`list-data-dictionary`, `search-bigquery-schema`,
27
- `data-source-status`), then query. Don't cross-check or add breakdowns
28
- nobody asked for.
29
- 4. **Answer in chat.** Give the result directly with a short table or inline
30
- chart — never deflect to "check the dashboard." Keep native data widgets to
31
- already-summarized data (≤50 rows); above that, state the total and show the
32
- top rows.
33
- 5. **Deliver exports in chat.** See `analysis-workspace`; never return only a
34
- path or tell the user to find a download elsewhere.
35
- 6. **Chunk only for reading.** Group into 5-10 with per-item notes only when 30+
36
- items each need qualitative reading no query can do (call transcripts, ticket
37
- threads). Chunking a question a query could answer is the most expensive
38
- mistake available here. See `adhoc-analysis`.
18
+ 1. **Search existing work first.** Call `search-analytics-query-catalog`, adapt
19
+ the closest saved SQL to the requested filters/window, run it once, and stop.
20
+ 2. **One bounded call.** List/filter/count/cohort questions are one SQL statement
21
+ or one server-side `run-code` script; never page or fan out per item.
22
+ 3. **Escalate on a miss.** If the catalog has no usable result, make one discovery
23
+ pass (`list-data-dictionary`, `search-bigquery-schema`, `data-source-status`),
24
+ then query; don't cross-check or add unasked breakdowns.
25
+ 4. **Answer in chat.** Return a short table or inline chart, not a dashboard
26
+ pointer. Native widgets show summarized data (≤50 rows); above that, state the
27
+ total and top rows.
28
+ 5. **Deliver exports in chat.** See `analysis-workspace`; don't return only a path.
29
+ 6. **Chunk only reading.** Group 5-10 only for 30+ qualitative items when a query
30
+ cannot answer; don't chunk queryable questions. See `adhoc-analysis`.
39
31
 
40
32
  ## Core Rules
41
33
 
42
- - A sibling app asking over A2A sends a question or shaped input, never SQL. It
43
- lacks this app's schema, data dictionary, dashboards, and dialect knowledge,
44
- so raw-query actions (`sql`, `code`, `script`, `expression`) are not
45
- sibling-invocable. Prefer natural-language delegation so this app retains its
46
- instructions, source selection, and tools. Shaped reads are stable contracts,
47
- not workarounds for delegation; this app still owns the query.
34
+ - A sibling app asking over A2A sends a question or shaped input, never SQL.
35
+ Raw-query actions (`sql`, `code`, `script`, `expression`) are not
36
+ sibling-invocable because this app owns schema, source selection, and tools.
37
+ Prefer natural-language delegation; shaped reads are stable contracts, not
38
+ delegation workarounds.
48
39
  - For open-ended delegated requests, choose a safe default and label partial.
49
40
  - Data integrity first. Never invent numbers, dimensions, filters, or source
50
41
  semantics; only present values you actually retrieved, and state uncertainty.
@@ -54,9 +45,15 @@ ladder.
54
45
  access checks with raw SQL for ownable resources.
55
46
  - Provider actions are bounded shortcuts, not limits. For broad or
56
47
  absence-sensitive Gong work, stage raw API data and use
57
- `query-staged-dataset` or a Data Program; if raw transcript bodies are
58
- required, use `provider-corpus-job`. See `provider-api`, `data-programs`, and
59
- `gong`.
48
+ `query-staged-dataset` or a Data Program; use `provider-corpus-job` for raw
49
+ transcript bodies. See `provider-api`, `data-programs`, and `gong`.
50
+ - Custom APIs use the `provider-api-register` action for public HTTPS provider
51
+ metadata and `test-custom-api-connection` for bounded GET previews. Store
52
+ credential values in Settings, pass only key names to provider actions, and
53
+ hand successful endpoint tests to `save-data-program` for refreshable panels.
54
+ - Hosted Analytics cannot reach localhost or private network APIs. Use a
55
+ deployed HTTPS endpoint or an explicitly supported secure tunnel; never
56
+ weaken the provider runtime's SSRF boundary.
60
57
  - Create dashboards, panels, or saved artifacts only when explicitly asked;
61
58
  suggest and wait otherwise. Scope them to the question, avoid decorative
62
59
  metrics, and never modify existing dashboards without a directive.
@@ -81,7 +78,7 @@ ladder.
81
78
  ## Application State
82
79
 
83
80
  - `navigation` exposes the current dashboard, analysis, source, chart, and
84
- selection. `navigate` moves the user, including `view="catalog"`,
81
+ selection. `navigate` moves the user between supported Analytics surfaces,
85
82
  `"sessions"`, `"monitoring"`, and `"agents"`. Use `view-screen` when the
86
83
  active context is unclear.
87
84
  - Clicking a panel stages it as a chat context chip and writes `selected-object`
@@ -97,7 +94,7 @@ Read the relevant skill before deeper work:
97
94
  - `cross-source-analysis` for questions spanning sources (identity stitching,
98
95
  de-duplication).
99
96
  - `dashboard-management` for dashboard/panel storage, layout, extensions,
100
- mutation, sharing, and the template catalog.
97
+ mutation and sharing.
101
98
  - `adhoc-analysis` and `analysis-workspace` for one-off answers and large
102
99
  multi-source work.
103
100
  - `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 / install-dashboard-template).
32
+ * the change in real time (mirrors update-dashboard).
33
33
  */
34
34
  async function syncToCollab(
35
35
  dashboardId: string,
@@ -235,7 +235,7 @@ export async function ensureNativeV2Dashboards(
235
235
 
236
236
  export default defineAction({
237
237
  description:
238
- "Provision the four reusable native Analytics v2 dashboard patterns for the active organization from explicit Data Program bindings. " +
238
+ "Provision the reusable native Analytics v2 dashboard patterns, including On Demand Billing, for the active organization from explicit Data Program bindings. " +
239
239
  "This is an admin-only post-deploy action: it validates every program exists and exposes the manifest's required output columns, shares the bound programs with the organization, creates deterministic native-* dashboard copies, and never changes the legacy extension dashboards. " +
240
240
  "Re-running preserves existing v2 dashboard edits unless overwrite=true.",
241
241
  schema: z.object({
@@ -1,4 +1,5 @@
1
1
  import { defineAction } from "@agent-native/core/action";
2
+ import { isPostgres } from "@agent-native/core/db";
2
3
  import { buildDeepLink } from "@agent-native/core/server";
3
4
  import { and, eq, isNull, like, or, sql } from "drizzle-orm";
4
5
  import { z } from "zod";
@@ -40,24 +41,8 @@ function toNumber(value: unknown): number {
40
41
  return 0;
41
42
  }
42
43
 
43
- function parseConfig(value: unknown): Record<string, unknown> {
44
- if (value && typeof value === "object" && !Array.isArray(value)) {
45
- return value as Record<string, unknown>;
46
- }
47
- if (typeof value !== "string") return {};
48
- try {
49
- const parsed = JSON.parse(value);
50
- return parsed && typeof parsed === "object" && !Array.isArray(parsed)
51
- ? parsed
52
- : {};
53
- } catch {
54
- return {};
55
- }
56
- }
57
-
58
- function dashboardName(row: { title: string; config: unknown }): string {
59
- const config = parseConfig(row.config);
60
- const configName = config.name;
44
+ function dashboardName(row: { title: string; configName: unknown }): string {
45
+ const configName = row.configName;
61
46
  if (typeof configName === "string" && configName.trim()) {
62
47
  return configName.trim();
63
48
  }
@@ -66,11 +51,10 @@ function dashboardName(row: { title: string; config: unknown }): string {
66
51
 
67
52
  function dashboardPanelCount(row: {
68
53
  kind: string;
69
- config: unknown;
54
+ panelCount: unknown;
70
55
  }): number | null {
71
56
  if (row.kind !== "sql") return null;
72
- const panels = parseConfig(row.config).panels;
73
- return Array.isArray(panels) ? panels.length : 0;
57
+ return toNumber(row.panelCount);
74
58
  }
75
59
 
76
60
  export function dashboardIdFromPath(path: string | null): string | null {
@@ -143,6 +127,16 @@ export default defineAction({
143
127
  run: async (_args, ctx) => {
144
128
  const admin = await requireDbAdminContextFromRequest(ctx);
145
129
  const db = getDb() as any;
130
+ const configName = isPostgres()
131
+ ? sql<string | null>`(${schema.dashboards.config}::jsonb ->> 'name')`
132
+ : sql<string | null>`json_extract(${schema.dashboards.config}, '$.name')`;
133
+ const panelCount = isPostgres()
134
+ ? sql<
135
+ number | null
136
+ >`CASE WHEN ${schema.dashboards.kind} = 'sql' AND jsonb_typeof(${schema.dashboards.config}::jsonb -> 'panels') = 'array' THEN jsonb_array_length(${schema.dashboards.config}::jsonb -> 'panels') ELSE 0 END`
137
+ : sql<
138
+ number | null
139
+ >`CASE WHEN ${schema.dashboards.kind} = 'sql' AND json_type(json_extract(${schema.dashboards.config}, '$.panels')) = 'array' THEN json_array_length(json_extract(${schema.dashboards.config}, '$.panels')) ELSE 0 END`;
146
140
 
147
141
  // guard:allow-unscoped — org owner/admin audit intentionally spans all
148
142
  // dashboard rows in the active org after requireDbAdminContextFromRequest.
@@ -151,7 +145,8 @@ export default defineAction({
151
145
  id: schema.dashboards.id,
152
146
  kind: schema.dashboards.kind,
153
147
  title: schema.dashboards.title,
154
- config: schema.dashboards.config,
148
+ configName,
149
+ panelCount,
155
150
  ownerEmail: schema.dashboards.ownerEmail,
156
151
  visibility: schema.dashboards.visibility,
157
152
  createdAt: schema.dashboards.createdAt,
@@ -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
+ });
@@ -6,11 +6,10 @@ import {
6
6
  } from "@agent-native/core/server";
7
7
  import { z } from "zod";
8
8
 
9
- import { listDashboardSummaries } from "../server/lib/dashboards-store";
10
-
11
- function normalizeDashboardName(value: string): string {
12
- return value.trim().replace(/\s+/g, " ").toLowerCase();
13
- }
9
+ import {
10
+ listDashboardSummaries,
11
+ normalizeDashboardName,
12
+ } from "../server/lib/dashboards-store";
14
13
 
15
14
  async function resolveDashboardIdByName(name: string): Promise<string> {
16
15
  const email = getRequestUserEmail();
@@ -50,7 +49,7 @@ export default defineAction({
50
49
  .string()
51
50
  .optional()
52
51
  .describe(
53
- "View to navigate to (ask, adhoc, analyses, extensions, sessions, monitoring, agents, catalog, data-dictionary, data-sources, settings)",
52
+ "View to navigate to (ask, adhoc, analyses, extensions, sessions, monitoring, agents, data-dictionary, data-sources, settings)",
54
53
  ),
55
54
  dashboardId: z
56
55
  .string()
@@ -0,0 +1,50 @@
1
+ import { getDbExec } from "@agent-native/core/db";
2
+ import {
3
+ createCustomProviderRegistrationAction,
4
+ CustomProviderRegistrationSchema,
5
+ } from "@agent-native/core/provider-api/actions/custom-provider-registration";
6
+ import { getCredentialContext } from "@agent-native/core/server/request-context";
7
+ import { z } from "zod";
8
+
9
+ async function resolveCallerOrgRole(orgId: string, email: string) {
10
+ try {
11
+ const { rows } = await getDbExec().execute({
12
+ sql: `SELECT role FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,
13
+ args: [orgId, email.toLowerCase()],
14
+ });
15
+ const role = (rows[0] as { role?: unknown } | undefined)?.role;
16
+ return typeof role === "string" && role ? role : null;
17
+ } catch {
18
+ return null;
19
+ }
20
+ }
21
+
22
+ const schema = CustomProviderRegistrationSchema.superRefine((value, ctx) => {
23
+ if (value.operation === "upsert" && value.baseUrl) {
24
+ try {
25
+ const url = new URL(value.baseUrl);
26
+ if (url.protocol !== "https:") {
27
+ ctx.addIssue({
28
+ code: z.ZodIssueCode.custom,
29
+ path: ["baseUrl"],
30
+ message: "baseUrl must use public HTTPS.",
31
+ });
32
+ }
33
+ } catch {
34
+ // The shared schema reports malformed URLs.
35
+ }
36
+ }
37
+ });
38
+
39
+ const action = createCustomProviderRegistrationAction({
40
+ schema,
41
+ getContext: getCredentialContext,
42
+ resolveOrgRole: resolveCallerOrgRole,
43
+ description:
44
+ "Register or update an Analytics custom API provider. Stores credential key names only, never secret values. Requires a public HTTPS base URL and owner/admin organization access.",
45
+ });
46
+
47
+ // The shared factory owns registration, validation, and mutation authorization;
48
+ // this wrapper only adds Analytics' transport contract and base URL policy.
49
+ // Static action registry marker: createCustomProviderRegistrationAction returns defineAction.
50
+ export default { ...action, http: { method: "POST" as const } };
@@ -1,4 +1,9 @@
1
- import { defineAction } from "@agent-native/core";
1
+ import {
2
+ ACTION_CHAT_UI_DATA_TABLE_RENDERER,
3
+ dataTableWidgetResultSchema,
4
+ defineAction,
5
+ } from "@agent-native/core";
6
+ import { createDataTableWidgetResult } from "@agent-native/core/data-widgets";
2
7
  import {
3
8
  getRequestOrgId,
4
9
  getRequestUserEmail,
@@ -13,25 +18,50 @@ function resolveScope() {
13
18
  return { userEmail, orgId: getRequestOrgId() || null };
14
19
  }
15
20
 
21
+ function toDataTableResult(result: {
22
+ rows: Record<string, unknown>[];
23
+ schema: { name: string; type: string }[];
24
+ }) {
25
+ const numericTypes = new Set([
26
+ "number",
27
+ "integer",
28
+ "float",
29
+ "double",
30
+ "decimal",
31
+ "numeric",
32
+ ]);
33
+
34
+ return createDataTableWidgetResult({
35
+ widgetId: "analytics.query.v1",
36
+ title: "Analytics query result",
37
+ table: {
38
+ title: "Analytics query result",
39
+ columns: result.schema.map(({ name, type }) => ({
40
+ key: name,
41
+ label: name,
42
+ ...(numericTypes.has(type.toLowerCase()) ? { align: "right" } : {}),
43
+ })),
44
+ rows: result.rows,
45
+ },
46
+ });
47
+ }
48
+
16
49
  export default defineAction({
17
50
  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. The rollups are updated transactionally with new ingest, and a durable scheduled job backfills existing analytics_events after deployment. Until that job completes, use analytics_events only for bounded recent drill-downs with an explicit event_date or timestamp range. 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, so use that provider's explicit collection or export path before querying it. Aggregate, 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. 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.",
51
+ "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
52
  schema: z.object({
20
53
  sql: z
21
54
  .string()
22
55
  .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. A durable scheduled job repairs historical rollups after deployment; until it completes, use an explicit event_date or timestamp range for bounded analytics_events reads. 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. 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",
56
+ "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
57
  ),
25
58
  }),
26
- outputSchema: z.object({
27
- rows: z.array(z.record(z.string(), z.unknown())),
28
- schema: z.array(
29
- z.object({
30
- name: z.string(),
31
- type: z.string(),
32
- }),
33
- ),
34
- }),
59
+ outputSchema: dataTableWidgetResultSchema,
60
+ chatUI: {
61
+ renderer: ACTION_CHAT_UI_DATA_TABLE_RENDERER,
62
+ title: "Analytics query result",
63
+ description: "Render query rows as a native table with CSV download.",
64
+ },
35
65
  readOnly: true,
36
66
  // No raw HTTP or connector-catalog route: SQL would land in query strings,
37
67
  // logs, or a caller that lacks this app's schema and data dictionary. This
@@ -40,6 +70,9 @@ export default defineAction({
40
70
  http: false,
41
71
  publicAgent: { expose: true, readOnly: true, requiresAuth: true },
42
72
  run: async (args) => {
43
- return queryFirstPartyAnalytics(args.sql, resolveScope(), { cache: true });
73
+ const result = await queryFirstPartyAnalytics(args.sql, resolveScope(), {
74
+ cache: true,
75
+ });
76
+ return toDataTableResult(result);
44
77
  },
45
78
  });
@@ -0,0 +1,106 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { extractItemsArray } from "@agent-native/core/provider-api/staging";
3
+ import { z } from "zod";
4
+
5
+ import { getAnalyticsProviderApiRuntime } from "../server/lib/provider-api";
6
+
7
+ const secretKey = /pass(word)?|secret|token|api[-_]?key|authorization/i;
8
+ const Input = z.object({
9
+ provider: z.string().min(1),
10
+ path: z.string().min(1),
11
+ query: z.record(z.string(), z.unknown()).optional(),
12
+ itemsPath: z.string().min(1).optional(),
13
+ });
14
+
15
+ function redact(value: unknown): unknown {
16
+ if (Array.isArray(value)) return value.map(redact);
17
+ if (!value || typeof value !== "object") return value;
18
+ return Object.fromEntries(
19
+ Object.entries(value).map(([key, entry]) => [
20
+ key,
21
+ secretKey.test(key) ? "[redacted]" : redact(entry),
22
+ ]),
23
+ );
24
+ }
25
+
26
+ export default defineAction({
27
+ description:
28
+ "Test an Analytics custom API connection with a bounded authenticated GET and return a safe row preview.",
29
+ schema: Input,
30
+ agentTool: false,
31
+ http: { method: "POST" },
32
+ readOnly: true,
33
+ run: async ({ provider, path, query, itemsPath }) => {
34
+ try {
35
+ const result = (await getAnalyticsProviderApiRuntime().executeRequest({
36
+ provider,
37
+ method: "GET",
38
+ path,
39
+ ...(query ? { query } : {}),
40
+ auth: "default",
41
+ maxBytes: 1_000_000,
42
+ timeoutMs: 10_000,
43
+ })) as {
44
+ response?: {
45
+ ok?: boolean;
46
+ status?: number;
47
+ statusText?: string;
48
+ json?: unknown;
49
+ truncated?: boolean;
50
+ };
51
+ };
52
+ const response = result.response;
53
+ const status = response?.status ?? 0;
54
+ const statusText = response?.statusText ?? "";
55
+ if (!response?.ok) {
56
+ return {
57
+ ok: false,
58
+ status,
59
+ statusText,
60
+ rowCount: 0,
61
+ columns: [],
62
+ sampleRows: [],
63
+ itemsPath: itemsPath ?? null,
64
+ truncated: false,
65
+ error: `Custom API request failed with HTTP ${status}${statusText ? ` ${statusText}` : ""}.`,
66
+ };
67
+ }
68
+ const rows = extractItemsArray(response.json, itemsPath ?? "auto");
69
+ const sampleRows = rows.slice(0, 5).map((row) => redact(row));
70
+ const columns = Array.from(
71
+ new Set(
72
+ rows.flatMap((row) =>
73
+ row && typeof row === "object" && !Array.isArray(row)
74
+ ? Object.keys(row)
75
+ : [],
76
+ ),
77
+ ),
78
+ );
79
+ return {
80
+ ok: true,
81
+ status,
82
+ statusText,
83
+ rowCount: rows.length,
84
+ columns,
85
+ sampleRows,
86
+ itemsPath: itemsPath ?? "auto",
87
+ truncated: Boolean(response.truncated),
88
+ };
89
+ } catch (error) {
90
+ return {
91
+ ok: false,
92
+ status: 0,
93
+ statusText: "",
94
+ rowCount: 0,
95
+ columns: [],
96
+ sampleRows: [],
97
+ itemsPath: itemsPath ?? null,
98
+ truncated: false,
99
+ error:
100
+ error instanceof Error
101
+ ? `Custom API connection failed: ${error.message}`
102
+ : "Custom API connection failed.",
103
+ };
104
+ }
105
+ },
106
+ });
@@ -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({