@agent-native/core 0.120.1 → 0.120.3

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 (396) hide show
  1. package/corpus/README.md +3 -3
  2. package/corpus/core/CHANGELOG.md +29 -0
  3. package/corpus/core/docs/content/extensions.mdx +23 -4
  4. package/corpus/core/package.json +1 -1
  5. package/corpus/core/src/agent/production-agent.ts +4 -0
  6. package/corpus/core/src/agent/run-manager.ts +36 -10
  7. package/corpus/core/src/agent/types.ts +2 -0
  8. package/corpus/core/src/cli/context-xray-local.ts +1 -1
  9. package/corpus/core/src/cli/index.ts +63 -18
  10. package/corpus/core/src/cli/skills.ts +5 -0
  11. package/corpus/core/src/cli/telemetry.ts +118 -1
  12. package/corpus/core/src/client/AgentPanel.tsx +10 -0
  13. package/corpus/core/src/client/CommandMenu.tsx +13 -1
  14. package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +39 -4
  15. package/corpus/core/src/client/analytics.ts +13 -0
  16. package/corpus/core/src/client/error-capture.ts +6 -1
  17. package/corpus/core/src/client/extensions/ExtensionsListPage.tsx +28 -8
  18. package/corpus/core/src/client/extensions/agent-native-extension-runtime.ts +1 -1
  19. package/corpus/core/src/client/navigation/index.ts +2 -0
  20. package/corpus/core/src/client/org/OrgSwitcher.tsx +14 -32
  21. package/corpus/core/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
  22. package/corpus/core/src/client/settings/SettingsPanel.tsx +10 -0
  23. package/corpus/core/src/deploy/build.ts +3 -0
  24. package/corpus/core/src/extensions/theme.ts +1 -1
  25. package/corpus/core/src/localization/default-messages.ts +2 -0
  26. package/corpus/core/src/server/analytics.ts +154 -25
  27. package/corpus/core/src/server/core-routes-plugin.ts +10 -1
  28. package/corpus/core/src/server/framework-request-handler.ts +17 -26
  29. package/corpus/core/src/styles/agent-native.css +13 -0
  30. package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +3 -0
  31. package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +113 -51
  32. package/corpus/core/src/templates/chat/app/global.css +1 -1
  33. package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +2 -2
  34. package/corpus/core/src/templates/chat/netlify.toml +1 -0
  35. package/corpus/core/src/templates/default/app/global.css +1 -1
  36. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
  37. package/corpus/core/src/tracking/error-capture.ts +151 -0
  38. package/corpus/core/src/tracking/index.ts +5 -0
  39. package/corpus/core/src/vite/client.ts +6 -0
  40. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +27 -43
  41. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +19 -8
  42. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +2 -2
  43. package/corpus/templates/analytics/AGENTS.md +20 -8
  44. package/corpus/templates/analytics/actions/get-explorer-dashboard.ts +3 -0
  45. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +140 -46
  46. package/corpus/templates/analytics/actions/migrate-analytics-artifacts.ts +48 -0
  47. package/corpus/templates/analytics/actions/save-analysis.ts +2 -3
  48. package/corpus/templates/analytics/actions/view-screen.ts +1 -1
  49. package/corpus/templates/analytics/app/components/dashboard/CumulativeNetChart.tsx +1 -1
  50. package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +1 -4
  51. package/corpus/templates/analytics/app/components/dashboard/DashboardMetadata.tsx +77 -0
  52. package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +7 -1
  53. package/corpus/templates/analytics/app/components/dashboard/DataTable.tsx +1 -1
  54. package/corpus/templates/analytics/app/components/dashboard/DateRangePicker.tsx +2 -2
  55. package/corpus/templates/analytics/app/components/dashboard/MetricCard.tsx +1 -1
  56. package/corpus/templates/analytics/app/components/dashboard/RecentActivity.tsx +1 -1
  57. package/corpus/templates/analytics/app/components/dashboard/RevenueChart.tsx +1 -1
  58. package/corpus/templates/analytics/app/components/dashboard/RevenueComparisonChart.tsx +1 -1
  59. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +41 -9
  60. package/corpus/templates/analytics/app/components/dashboard/StatsCard.tsx +1 -1
  61. package/corpus/templates/analytics/app/components/dashboard/TimeSeriesChart.tsx +1 -1
  62. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +2 -0
  63. package/corpus/templates/analytics/app/components/layout/Layout.tsx +28 -14
  64. package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
  65. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +255 -626
  66. package/corpus/templates/analytics/app/global.css +31 -1
  67. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +2 -2
  68. package/corpus/templates/analytics/app/i18n-data.ts +80 -0
  69. package/corpus/templates/analytics/app/lib/dashboard-report-capture.ts +42 -0
  70. package/corpus/templates/analytics/app/pages/Agents.tsx +49 -2
  71. package/corpus/templates/analytics/app/pages/adhoc/_shared/KpiChart.tsx +1 -1
  72. package/corpus/templates/analytics/app/pages/adhoc/explorer/components/ChartTypePicker.tsx +1 -1
  73. package/corpus/templates/analytics/app/pages/adhoc/explorer/components/DateRangePicker.tsx +1 -1
  74. package/corpus/templates/analytics/app/pages/adhoc/explorer/components/EventRow.tsx +1 -1
  75. package/corpus/templates/analytics/app/pages/adhoc/explorer/components/SqlPreview.tsx +2 -2
  76. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +54 -11
  77. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +3 -3
  78. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +2 -2
  79. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +1 -1
  80. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +4 -54
  81. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +178 -69
  82. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +2 -2
  83. package/corpus/templates/analytics/app/root.tsx +28 -0
  84. package/corpus/templates/analytics/app/routes/analyses._index.tsx +3 -2
  85. package/corpus/templates/analytics/app/routes/extensions._index.tsx +2 -2
  86. package/corpus/templates/analytics/changelog/2026-07-23-analytics-now-groups-saved-analyses-and-embedded-extensions-.md +6 -0
  87. package/corpus/templates/analytics/changelog/2026-07-23-dashboard-menus-show-who-created-and-last-updated-each-dashb.md +6 -0
  88. package/corpus/templates/analytics/changelog/2026-07-23-dashboard-usage-now-loads-reliably-for-organizations-with-ma.md +6 -0
  89. package/corpus/templates/analytics/changelog/2026-07-23-long-dashboard-building-requests-now-continue-without-stoppi.md +6 -0
  90. package/corpus/templates/analytics/changelog/2026-07-24-analytics-charts-now-explain-slow-loads-and-offer-a-direct-r.md +6 -0
  91. package/corpus/templates/analytics/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  92. package/corpus/templates/analytics/changelog/2026-07-24-daily-dashboard-emails-now-load-signed-reports-more-reliably.md +6 -0
  93. package/corpus/templates/analytics/changelog/2026-07-24-manage-agent-is-clearly-marked-as-a-link-to-its-dedicated-pa.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  95. package/corpus/templates/analytics/netlify.toml +4 -0
  96. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +1 -1
  97. package/corpus/templates/analytics/server/db/schema.ts +9 -0
  98. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +21 -0
  99. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -1
  100. package/corpus/templates/analytics/server/lib/agent-readable-resource-context.ts +1 -0
  101. package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +11 -0
  102. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +54 -0
  103. package/corpus/templates/analytics/server/lib/dashboard-report.ts +235 -26
  104. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +4 -1
  105. package/corpus/templates/analytics/server/lib/migrate-analytics-artifacts.ts +1062 -0
  106. package/corpus/templates/analytics/server/plugins/agent-chat.ts +6 -52
  107. package/corpus/templates/analytics/server/plugins/core-routes.ts +1 -1
  108. package/corpus/templates/analytics/server/plugins/db.ts +19 -0
  109. package/corpus/templates/analytics/shared/dashboard-report-timeouts.ts +1 -1
  110. package/corpus/templates/assets/actions/generate-image-batch.ts +36 -1
  111. package/corpus/templates/assets/actions/generate-image.ts +28 -1
  112. package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +376 -0
  113. package/corpus/templates/assets/app/components/create/RecentDraftsSection.tsx +14 -4
  114. package/corpus/templates/assets/app/components/layout/Layout.tsx +5 -0
  115. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +164 -82
  116. package/corpus/templates/assets/app/global.css +1 -1
  117. package/corpus/templates/assets/app/i18n-data.ts +10 -0
  118. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +99 -10
  119. package/corpus/templates/assets/app/routes/extensions._index.tsx +2 -2
  120. package/corpus/templates/assets/app/routes/library.tsx +21 -198
  121. package/corpus/templates/assets/changelog/2026-07-21-unified-asset-preview-click-any-asset-to-open-one-preview-wi.md +6 -0
  122. package/corpus/templates/assets/changelog/2026-07-23-assets-image-generation-now-recovers-after-a-completed-tool-.md +6 -0
  123. package/corpus/templates/assets/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  124. package/corpus/templates/assets/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  125. package/corpus/templates/assets/netlify.toml +1 -0
  126. package/corpus/templates/brain/app/components/layout/Layout.tsx +3 -0
  127. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +114 -51
  128. package/corpus/templates/brain/app/global.css +1 -1
  129. package/corpus/templates/brain/app/routes/extensions._index.tsx +2 -2
  130. package/corpus/templates/brain/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  131. package/corpus/templates/brain/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  132. package/corpus/templates/brain/netlify.toml +1 -0
  133. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +110 -57
  134. package/corpus/templates/calendar/app/global.css +1 -1
  135. package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +2 -16
  136. package/corpus/templates/calendar/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  137. package/corpus/templates/calendar/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  138. package/corpus/templates/calendar/netlify.toml +1 -0
  139. package/corpus/templates/chat/app/components/layout/Layout.tsx +3 -0
  140. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +113 -51
  141. package/corpus/templates/chat/app/global.css +1 -1
  142. package/corpus/templates/chat/app/routes/extensions._index.tsx +2 -2
  143. package/corpus/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  144. package/corpus/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  145. package/corpus/templates/chat/netlify.toml +1 -0
  146. package/corpus/templates/clips/app/components/library/library-layout.tsx +117 -37
  147. package/corpus/templates/clips/app/components/library/organization-switcher.tsx +2 -2
  148. package/corpus/templates/clips/app/components/player/video-player.tsx +16 -1
  149. package/corpus/templates/clips/app/global.css +1 -1
  150. package/corpus/templates/clips/app/hooks/use-view-tracking.ts +55 -12
  151. package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +2 -16
  152. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +6 -5
  153. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +7 -7
  154. package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -5
  155. package/corpus/templates/clips/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  156. package/corpus/templates/clips/changelog/2026-07-23-meeting-recording-meters-and-dismissed-prompts.md +6 -0
  157. package/corpus/templates/clips/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  158. package/corpus/templates/clips/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  159. package/corpus/templates/clips/desktop/src/hooks/useMicMeter.ts +1 -1
  160. package/corpus/templates/clips/desktop/src/lib/meeting-notification-dismissal.ts +2 -0
  161. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +1 -3
  162. package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +86 -0
  163. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +24 -0
  164. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +5 -69
  165. package/corpus/templates/clips/desktop/src/styles.css +35 -3
  166. package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +13 -44
  167. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +119 -17
  168. package/corpus/templates/clips/netlify.toml +1 -0
  169. package/corpus/templates/clips/server/plugins/db.ts +113 -68
  170. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +69 -49
  171. package/corpus/templates/content/app/global.css +1 -1
  172. package/corpus/templates/content/app/routes/_app.extensions._index.tsx +2 -2
  173. package/corpus/templates/content/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  174. package/corpus/templates/content/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  175. package/corpus/templates/content/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  176. package/corpus/templates/content/netlify.toml +1 -0
  177. package/corpus/templates/design/app/components/layout/Sidebar.tsx +115 -42
  178. package/corpus/templates/design/app/entry.client.tsx +14 -1
  179. package/corpus/templates/design/app/global.css +1 -1
  180. package/corpus/templates/design/app/routes/extensions._index.tsx +2 -2
  181. package/corpus/templates/design/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  182. package/corpus/templates/design/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  183. package/corpus/templates/design/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  184. package/corpus/templates/design/netlify.toml +1 -0
  185. package/corpus/templates/dispatch/app/dispatch-extensions.tsx +1 -1
  186. package/corpus/templates/dispatch/app/global.css +1 -1
  187. package/corpus/templates/dispatch/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  188. package/corpus/templates/dispatch/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  189. package/corpus/templates/dispatch/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  190. package/corpus/templates/dispatch/netlify.toml +1 -0
  191. package/corpus/templates/forms/app/components/layout/Layout.tsx +3 -0
  192. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +113 -82
  193. package/corpus/templates/forms/app/global.css +1 -1
  194. package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +2 -2
  195. package/corpus/templates/forms/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  196. package/corpus/templates/forms/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  197. package/corpus/templates/forms/changelog/2026-07-24-forms-sidebar-actions-now-keep-search-language-feedback-and-.md +6 -0
  198. package/corpus/templates/forms/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  199. package/corpus/templates/forms/netlify.toml +1 -0
  200. package/corpus/templates/macros/app/components/DailyProgress.tsx +5 -5
  201. package/corpus/templates/macros/app/components/ExerciseCard.tsx +2 -2
  202. package/corpus/templates/macros/app/components/MealCard.tsx +2 -2
  203. package/corpus/templates/macros/app/components/WeightCard.tsx +2 -2
  204. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +92 -34
  205. package/corpus/templates/macros/app/components/ui/button.tsx +1 -2
  206. package/corpus/templates/macros/app/components/ui/card.tsx +1 -1
  207. package/corpus/templates/macros/app/global.css +1 -1
  208. package/corpus/templates/macros/app/routes/_index.tsx +1 -1
  209. package/corpus/templates/macros/app/routes/analytics.tsx +4 -7
  210. package/corpus/templates/macros/app/routes/extensions._index.tsx +2 -2
  211. package/corpus/templates/macros/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  212. package/corpus/templates/macros/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  213. package/corpus/templates/macros/netlify.toml +1 -0
  214. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +125 -46
  215. package/corpus/templates/mail/app/global.css +1 -1
  216. package/corpus/templates/mail/app/routes/extensions._index.tsx +2 -2
  217. package/corpus/templates/mail/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  218. package/corpus/templates/mail/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  219. package/corpus/templates/mail/netlify.toml +1 -0
  220. package/corpus/templates/plan/app/components/layout/Layout.tsx +3 -0
  221. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +128 -65
  222. package/corpus/templates/plan/app/global.css +1 -1
  223. package/corpus/templates/plan/app/routes/extensions._index.tsx +2 -2
  224. package/corpus/templates/plan/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  225. package/corpus/templates/plan/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  226. package/corpus/templates/plan/netlify.toml +1 -0
  227. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +116 -36
  228. package/corpus/templates/slides/app/global.css +1 -1
  229. package/corpus/templates/slides/app/routes/extensions._index.tsx +2 -2
  230. package/corpus/templates/slides/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  231. package/corpus/templates/slides/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  232. package/corpus/templates/slides/netlify.toml +1 -0
  233. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +37 -6
  234. package/corpus/templates/tasks/app/global.css +1 -1
  235. package/corpus/templates/tasks/app/routes/extensions._index.tsx +2 -2
  236. package/corpus/templates/tasks/app/routes/settings.tsx +31 -0
  237. package/corpus/templates/tasks/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  238. package/corpus/templates/tasks/netlify.toml +1 -0
  239. package/corpus/toolkit/CHANGELOG.md +8 -0
  240. package/corpus/toolkit/README.md +8 -1
  241. package/corpus/toolkit/agent-native.eject.json +1 -1
  242. package/corpus/toolkit/package.json +1 -1
  243. package/corpus/toolkit/src/app-shell/index.ts +1 -0
  244. package/corpus/toolkit/src/app-shell/sidebar-footer-actions.tsx +48 -0
  245. package/corpus/toolkit/src/chat-history.css +52 -1
  246. package/corpus/toolkit/src/design-system/default-adapter.tsx +1 -1
  247. package/corpus/toolkit/src/ui/button.tsx +1 -2
  248. package/corpus/toolkit/src/ui/card.tsx +1 -1
  249. package/corpus/toolkit/src/ui/table.tsx +4 -11
  250. package/dist/agent/production-agent.d.ts.map +1 -1
  251. package/dist/agent/production-agent.js +4 -0
  252. package/dist/agent/production-agent.js.map +1 -1
  253. package/dist/agent/run-manager.d.ts +9 -0
  254. package/dist/agent/run-manager.d.ts.map +1 -1
  255. package/dist/agent/run-manager.js +25 -10
  256. package/dist/agent/run-manager.js.map +1 -1
  257. package/dist/agent/types.d.ts +2 -2
  258. package/dist/agent/types.d.ts.map +1 -1
  259. package/dist/agent/types.js.map +1 -1
  260. package/dist/cli/context-xray-local.js +1 -1
  261. package/dist/cli/context-xray-local.js.map +1 -1
  262. package/dist/cli/index.js +56 -17
  263. package/dist/cli/index.js.map +1 -1
  264. package/dist/cli/skills.d.ts.map +1 -1
  265. package/dist/cli/skills.js +5 -0
  266. package/dist/cli/skills.js.map +1 -1
  267. package/dist/cli/telemetry.d.ts +7 -0
  268. package/dist/cli/telemetry.d.ts.map +1 -1
  269. package/dist/cli/telemetry.js +91 -1
  270. package/dist/cli/telemetry.js.map +1 -1
  271. package/dist/client/AgentPanel.d.ts +7 -1
  272. package/dist/client/AgentPanel.d.ts.map +1 -1
  273. package/dist/client/AgentPanel.js +2 -2
  274. package/dist/client/AgentPanel.js.map +1 -1
  275. package/dist/client/CommandMenu.d.ts +2 -0
  276. package/dist/client/CommandMenu.d.ts.map +1 -1
  277. package/dist/client/CommandMenu.js +12 -1
  278. package/dist/client/CommandMenu.js.map +1 -1
  279. package/dist/client/agent-page/AgentTabsPage.d.ts +4 -0
  280. package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
  281. package/dist/client/agent-page/AgentTabsPage.js +8 -4
  282. package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
  283. package/dist/client/analytics.d.ts.map +1 -1
  284. package/dist/client/analytics.js +7 -0
  285. package/dist/client/analytics.js.map +1 -1
  286. package/dist/client/error-capture.d.ts.map +1 -1
  287. package/dist/client/error-capture.js +8 -1
  288. package/dist/client/error-capture.js.map +1 -1
  289. package/dist/client/extensions/ExtensionsListPage.d.ts +5 -1
  290. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  291. package/dist/client/extensions/ExtensionsListPage.js +6 -4
  292. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  293. package/dist/client/extensions/agent-native-extension-runtime.js +1 -1
  294. package/dist/client/extensions/agent-native-extension-runtime.js.map +1 -1
  295. package/dist/client/navigation/index.d.ts +1 -1
  296. package/dist/client/navigation/index.d.ts.map +1 -1
  297. package/dist/client/navigation/index.js +1 -1
  298. package/dist/client/navigation/index.js.map +1 -1
  299. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  300. package/dist/client/org/OrgSwitcher.js +9 -13
  301. package/dist/client/org/OrgSwitcher.js.map +1 -1
  302. package/dist/client/settings/ExtensionsSettingsContent.d.ts +2 -0
  303. package/dist/client/settings/ExtensionsSettingsContent.d.ts.map +1 -0
  304. package/dist/client/settings/ExtensionsSettingsContent.js +10 -0
  305. package/dist/client/settings/ExtensionsSettingsContent.js.map +1 -0
  306. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  307. package/dist/client/settings/SettingsPanel.js +10 -1
  308. package/dist/client/settings/SettingsPanel.js.map +1 -1
  309. package/dist/deploy/build.js +1 -0
  310. package/dist/deploy/build.js.map +1 -1
  311. package/dist/extensions/theme.js +1 -1
  312. package/dist/extensions/theme.js.map +1 -1
  313. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  314. package/dist/localization/default-messages.d.ts +2 -0
  315. package/dist/localization/default-messages.d.ts.map +1 -1
  316. package/dist/localization/default-messages.js +2 -0
  317. package/dist/localization/default-messages.js.map +1 -1
  318. package/dist/observability/routes.d.ts +3 -3
  319. package/dist/progress/routes.d.ts +1 -1
  320. package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
  321. package/dist/provider-api/actions/provider-api.d.ts +9 -9
  322. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  323. package/dist/resources/handlers.d.ts +1 -1
  324. package/dist/server/analytics.d.ts +9 -4
  325. package/dist/server/analytics.d.ts.map +1 -1
  326. package/dist/server/analytics.js +111 -22
  327. package/dist/server/analytics.js.map +1 -1
  328. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  329. package/dist/server/core-routes-plugin.js +8 -1
  330. package/dist/server/core-routes-plugin.js.map +1 -1
  331. package/dist/server/framework-request-handler.d.ts.map +1 -1
  332. package/dist/server/framework-request-handler.js +17 -27
  333. package/dist/server/framework-request-handler.js.map +1 -1
  334. package/dist/server/realtime-token.d.ts +1 -1
  335. package/dist/styles/agent-native.css +13 -0
  336. package/dist/templates/chat/app/components/layout/Layout.tsx +3 -0
  337. package/dist/templates/chat/app/components/layout/Sidebar.tsx +113 -51
  338. package/dist/templates/chat/app/global.css +1 -1
  339. package/dist/templates/chat/app/routes/extensions._index.tsx +2 -2
  340. package/dist/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  341. package/dist/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  342. package/dist/templates/chat/netlify.toml +1 -0
  343. package/dist/templates/default/app/global.css +1 -1
  344. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
  345. package/dist/tracking/error-capture.d.ts +14 -0
  346. package/dist/tracking/error-capture.d.ts.map +1 -0
  347. package/dist/tracking/error-capture.js +113 -0
  348. package/dist/tracking/error-capture.js.map +1 -0
  349. package/dist/tracking/index.d.ts +1 -0
  350. package/dist/tracking/index.d.ts.map +1 -1
  351. package/dist/tracking/index.js +1 -0
  352. package/dist/tracking/index.js.map +1 -1
  353. package/dist/vite/client.d.ts.map +1 -1
  354. package/dist/vite/client.js +2 -0
  355. package/dist/vite/client.js.map +1 -1
  356. package/docs/content/extensions.mdx +23 -4
  357. package/package.json +2 -2
  358. package/src/agent/production-agent.ts +4 -0
  359. package/src/agent/run-manager.ts +36 -10
  360. package/src/agent/types.ts +2 -0
  361. package/src/cli/context-xray-local.ts +1 -1
  362. package/src/cli/index.ts +63 -18
  363. package/src/cli/skills.ts +5 -0
  364. package/src/cli/telemetry.ts +118 -1
  365. package/src/client/AgentPanel.tsx +10 -0
  366. package/src/client/CommandMenu.tsx +13 -1
  367. package/src/client/agent-page/AgentTabsPage.tsx +39 -4
  368. package/src/client/analytics.ts +13 -0
  369. package/src/client/error-capture.ts +6 -1
  370. package/src/client/extensions/ExtensionsListPage.tsx +28 -8
  371. package/src/client/extensions/agent-native-extension-runtime.ts +1 -1
  372. package/src/client/navigation/index.ts +2 -0
  373. package/src/client/org/OrgSwitcher.tsx +14 -32
  374. package/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
  375. package/src/client/settings/SettingsPanel.tsx +10 -0
  376. package/src/deploy/build.ts +3 -0
  377. package/src/extensions/theme.ts +1 -1
  378. package/src/localization/default-messages.ts +2 -0
  379. package/src/server/analytics.ts +154 -25
  380. package/src/server/core-routes-plugin.ts +10 -1
  381. package/src/server/framework-request-handler.ts +17 -26
  382. package/src/styles/agent-native.css +13 -0
  383. package/src/templates/chat/app/components/layout/Layout.tsx +3 -0
  384. package/src/templates/chat/app/components/layout/Sidebar.tsx +113 -51
  385. package/src/templates/chat/app/global.css +1 -1
  386. package/src/templates/chat/app/routes/extensions._index.tsx +2 -2
  387. package/src/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
  388. package/src/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
  389. package/src/templates/chat/netlify.toml +1 -0
  390. package/src/templates/default/app/global.css +1 -1
  391. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
  392. package/src/tracking/error-capture.ts +151 -0
  393. package/src/tracking/index.ts +5 -0
  394. package/src/vite/client.ts +6 -0
  395. package/corpus/templates/analytics/app/components/layout/NewAnalysisDialog.tsx +0 -165
  396. package/corpus/templates/analytics/app/pages/analyses/AnalysesList.tsx +0 -175
@@ -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 savedViewRows = await db
156
- .select({
157
- dashboardId: schema.dashboardViews.dashboardId,
158
- count: sql<number>`count(*)`,
159
- lastSavedViewAt: sql<
160
- string | null
161
- >`max(${schema.dashboardViews.createdAt})`,
162
- })
163
- .from(schema.dashboardViews)
164
- .groupBy(schema.dashboardViews.dashboardId);
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 analyticsUserIdentity = sql<
183
- string | null
184
- >`coalesce(nullif(${schema.analyticsEvents.userKey}, ''), nullif(${schema.analyticsEvents.userId}, ''), nullif(${schema.analyticsEvents.anonymousId}, ''), nullif(${schema.analyticsEvents.sessionId}, ''))`;
185
- const eventRows = await db
186
- .select({
187
- path: schema.analyticsEvents.path,
188
- url: schema.analyticsEvents.url,
189
- eventName: schema.analyticsEvents.eventName,
190
- count: sql<number>`count(*)`,
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
- "Save an ad-hoc analysis as a reusable artifact. Do not call this for ordinary in-chat analysis or deep-dive answers unless the user explicitly asks to save/create a reusable analysis, or this turn is re-running an existing saved analysis. Stores the analysis question, instructions for re-running, data sources used, and compact results. " +
117
- "This creates a reusable analysis that anyone can re-run later to get updated results. " +
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
  ],
@@ -52,7 +52,7 @@ export function CumulativeNetChart({
52
52
  const color = isPositive ? "#10b981" : "#ef4444";
53
53
 
54
54
  return (
55
- <Card className="bg-card border-border/50">
55
+ <Card className="bg-card">
56
56
  <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
57
57
  <CardTitle className="text-base">{title}</CardTitle>
58
58
  </CardHeader>
@@ -108,10 +108,7 @@ export function DashboardHistoryPanel({
108
108
  ) : (
109
109
  <div className="space-y-1">
110
110
  {revisions.map((revision) => (
111
- <div
112
- key={revision.id}
113
- className="rounded-lg border border-border bg-card p-3"
114
- >
111
+ <div key={revision.id} className="rounded-lg bg-card p-3">
115
112
  <div className="flex items-start justify-between gap-3">
116
113
  <div className="min-w-0">
117
114
  <p className="truncate text-xs font-medium">
@@ -0,0 +1,77 @@
1
+ import { useFormatters, useT } from "@agent-native/core/client/i18n";
2
+ import { IconCalendar, IconClock, IconUser } from "@tabler/icons-react";
3
+
4
+ interface DashboardMetadataProps {
5
+ createdAt: string | null;
6
+ createdBy: string | null;
7
+ updatedAt: string | null;
8
+ updatedBy: string | null;
9
+ }
10
+
11
+ function MetadataRow({
12
+ icon: Icon,
13
+ label,
14
+ value,
15
+ }: {
16
+ icon: typeof IconCalendar;
17
+ label: string;
18
+ value: string;
19
+ }) {
20
+ return (
21
+ <div className="flex items-start gap-1.5">
22
+ <Icon className="mt-0.5 h-3 w-3 shrink-0" />
23
+ <span className="shrink-0">{label}</span>
24
+ <span className="min-w-0 truncate text-foreground/80">{value}</span>
25
+ </div>
26
+ );
27
+ }
28
+
29
+ export function DashboardMetadata({
30
+ createdAt,
31
+ createdBy,
32
+ updatedAt,
33
+ updatedBy,
34
+ }: DashboardMetadataProps) {
35
+ const t = useT();
36
+ const { formatDate } = useFormatters();
37
+
38
+ function formatMetadataDate(value: string | null): string {
39
+ if (!value) return t("agents.notTracked");
40
+ try {
41
+ return formatDate(value, {
42
+ year: "numeric",
43
+ month: "short",
44
+ day: "numeric",
45
+ hour: "numeric",
46
+ minute: "2-digit",
47
+ });
48
+ } catch {
49
+ return value;
50
+ }
51
+ }
52
+
53
+ return (
54
+ <div className="flex flex-col gap-1.5 text-xs text-muted-foreground">
55
+ <MetadataRow
56
+ icon={IconCalendar}
57
+ label={t("agents.dashboardMetadataCreated")}
58
+ value={formatMetadataDate(createdAt)}
59
+ />
60
+ <MetadataRow
61
+ icon={IconUser}
62
+ label={t("agents.dashboardMetadataCreatedBy")}
63
+ value={createdBy || t("agents.notTracked")}
64
+ />
65
+ <MetadataRow
66
+ icon={IconClock}
67
+ label={t("agents.dashboardMetadataUpdated")}
68
+ value={formatMetadataDate(updatedAt)}
69
+ />
70
+ <MetadataRow
71
+ icon={IconUser}
72
+ label={t("agents.dashboardMetadataUpdatedBy")}
73
+ value={updatedBy || t("agents.notTracked")}
74
+ />
75
+ </div>
76
+ );
77
+ }
@@ -8,6 +8,12 @@ export function DashboardPanelSkeleton({
8
8
  ...props
9
9
  }: ComponentProps<typeof Skeleton>) {
10
10
  return (
11
- <Skeleton {...props} className={cn("bg-muted-foreground/20", className)} />
11
+ <Skeleton
12
+ {...props}
13
+ className={cn(
14
+ "dashboard-panel-skeleton bg-muted-foreground/18",
15
+ className,
16
+ )}
17
+ />
12
18
  );
13
19
  }
@@ -217,7 +217,7 @@ export function DataTable({
217
217
  if (!title) return content;
218
218
 
219
219
  return (
220
- <Card className="bg-card border-border/50">
220
+ <Card className="bg-card">
221
221
  <CardHeader>
222
222
  <CardTitle className="text-base">{title}</CardTitle>
223
223
  </CardHeader>
@@ -27,7 +27,7 @@ export function dateRangeToInterval(range: DateRange): number {
27
27
 
28
28
  export function DateRangePicker({ value, onChange }: DateRangePickerProps) {
29
29
  return (
30
- <div className="flex items-center gap-1 rounded-lg border border-border p-1">
30
+ <div className="flex items-center gap-1 rounded-lg bg-card p-1">
31
31
  {options.map((opt) => (
32
32
  <Button
33
33
  key={opt.value}
@@ -35,7 +35,7 @@ export function DateRangePicker({ value, onChange }: DateRangePickerProps) {
35
35
  size="sm"
36
36
  className={cn(
37
37
  "h-7 px-3 text-xs",
38
- value === opt.value && "bg-secondary text-secondary-foreground",
38
+ value === opt.value && "bg-accent text-accent-foreground",
39
39
  )}
40
40
  onClick={() => onChange(opt.value)}
41
41
  >
@@ -19,7 +19,7 @@ export function MetricCard({
19
19
  error,
20
20
  }: MetricCardProps) {
21
21
  return (
22
- <Card className="bg-card border-border/50">
22
+ <Card className="bg-card">
23
23
  <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
24
24
  <CardTitle className="text-sm font-medium text-muted-foreground">
25
25
  {title}
@@ -51,7 +51,7 @@ export function RecentActivity() {
51
51
  const t = useT();
52
52
 
53
53
  return (
54
- <Card className="col-span-full lg:col-span-3 bg-card border-border/50">
54
+ <Card className="col-span-full lg:col-span-3 bg-card">
55
55
  <CardHeader>
56
56
  <CardTitle>{t("dashboard.recentSales")}</CardTitle>
57
57
  <CardDescription>
@@ -30,7 +30,7 @@ export function RevenueChart() {
30
30
  const t = useT();
31
31
 
32
32
  return (
33
- <Card className="col-span-full lg:col-span-4 bg-card border-border/50">
33
+ <Card className="col-span-full lg:col-span-4 bg-card">
34
34
  <CardHeader>
35
35
  <CardTitle>{t("dashboard.revenueOverTime")}</CardTitle>
36
36
  </CardHeader>
@@ -76,7 +76,7 @@ export function RevenueComparisonChart({
76
76
  }));
77
77
 
78
78
  return (
79
- <Card className="bg-card border-border/50">
79
+ <Card className="bg-card">
80
80
  <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
81
81
  <CardTitle className="text-base">{title}</CardTitle>
82
82
  </CardHeader>
@@ -12,6 +12,7 @@ import {
12
12
  IconChevronRight,
13
13
  IconAlertTriangle,
14
14
  IconInfoCircle,
15
+ IconRefresh,
15
16
  IconTrendingUp,
16
17
  IconTrendingDown,
17
18
  } from "@tabler/icons-react";
@@ -174,6 +175,27 @@ const PARTIAL_DAY_KEY_PREFIX = "__sql_chart_partial_day";
174
175
  const TABLE_PANEL_MIN_HEIGHT_CLASS = "min-h-[386px]";
175
176
  const TABLE_PANEL_SKELETON_ROWS = 10;
176
177
 
178
+ export function formatSqlChartError(error: unknown): string {
179
+ const message =
180
+ error instanceof Error
181
+ ? error.message
182
+ : typeof error === "string"
183
+ ? error
184
+ : String(error ?? "");
185
+ const readableMessage = message
186
+ .replace(/<[^>]*>/g, " ")
187
+ .replace(/\s+/g, " ")
188
+ .trim();
189
+
190
+ if (/inactivity timeout|too much time has passed/i.test(readableMessage)) {
191
+ return "This chart took too long to load. Try again.";
192
+ }
193
+ if (/internal server error/i.test(readableMessage)) {
194
+ return "This chart could not be loaded. Try again.";
195
+ }
196
+ return readableMessage || "This chart could not be loaded. Try again.";
197
+ }
198
+
177
199
  function formatYValue(
178
200
  value: number,
179
201
  formatter?: "number" | "currency" | "percent",
@@ -1108,6 +1130,7 @@ export function SqlChart({
1108
1130
  isLoading,
1109
1131
  isFetching,
1110
1132
  error: queryError,
1133
+ refetch,
1111
1134
  } = useSqlQuery(
1112
1135
  ["sql-chart", panel.id, sql, panel.source],
1113
1136
  sql,
@@ -1117,14 +1140,11 @@ export function SqlChart({
1117
1140
  );
1118
1141
 
1119
1142
  const rawRows = result?.rows ?? [];
1120
- const queryErrorMessage =
1121
- queryError instanceof Error
1122
- ? queryError.message
1123
- : queryError
1124
- ? String(queryError)
1125
- : undefined;
1126
1143
  const error =
1127
- rawRows.length === 0 ? (result?.error ?? queryErrorMessage) : undefined;
1144
+ rawRows.length === 0
1145
+ ? (result?.error ??
1146
+ (queryError ? formatSqlChartError(queryError) : undefined))
1147
+ : undefined;
1128
1148
 
1129
1149
  const { rows: queryRows, forcedYKeys } = useMemo(() => {
1130
1150
  if (panel.config?.pivot && rawRows.length) {
@@ -1209,9 +1229,21 @@ export function SqlChart({
1209
1229
  if (error) {
1210
1230
  return (
1211
1231
  <div
1212
- className={`flex flex-1 items-center justify-center px-4 ${placeholderPadY} ${placeholderMinH}`}
1232
+ className={`flex flex-1 flex-col items-center justify-center gap-3 px-4 ${placeholderPadY} ${placeholderMinH}`}
1233
+ role="alert"
1213
1234
  >
1214
- <p className="text-sm text-red-400 text-center break-all">{error}</p>
1235
+ <p className="text-center text-sm text-red-400 break-all">
1236
+ {formatSqlChartError(error)}
1237
+ </p>
1238
+ <Button
1239
+ type="button"
1240
+ variant="secondary"
1241
+ size="sm"
1242
+ onClick={() => void refetch()}
1243
+ >
1244
+ <IconRefresh className="mr-2 h-3.5 w-3.5" />
1245
+ {t("sqlDashboard.refresh")}
1246
+ </Button>
1215
1247
  </div>
1216
1248
  );
1217
1249
  }
@@ -20,7 +20,7 @@ export function StatsCard({
20
20
  trend,
21
21
  }: StatsCardProps) {
22
22
  return (
23
- <Card className="bg-card border-border/50 shadow-sm">
23
+ <Card className="bg-card shadow-sm">
24
24
  <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
25
25
  <CardTitle className="text-sm font-medium text-muted-foreground">
26
26
  {title}
@@ -49,7 +49,7 @@ export function TimeSeriesChart({
49
49
  };
50
50
 
51
51
  return (
52
- <Card className="bg-card border-border/50">
52
+ <Card className="bg-card">
53
53
  <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
54
54
  <CardTitle className="text-base">{title}</CardTitle>
55
55
  </CardHeader>
@@ -381,9 +381,11 @@ export function CommandPalette() {
381
381
  const openHandler = () => setOpen(true);
382
382
  document.addEventListener("keydown", handler);
383
383
  window.addEventListener("analytics:open-command-palette", openHandler);
384
+ window.addEventListener("agent-native:open-command-menu", openHandler);
384
385
  return () => {
385
386
  document.removeEventListener("keydown", handler);
386
387
  window.removeEventListener("analytics:open-command-palette", openHandler);
388
+ window.removeEventListener("agent-native:open-command-menu", openHandler);
387
389
  };
388
390
  }, []);
389
391