@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
@@ -97,6 +97,7 @@ import {
97
97
  MCP_EMBED_CORS_ALLOW_HEADERS,
98
98
  shouldAllowMcpEmbedCredentials,
99
99
  } from "../shared/mcp-embed-headers.js";
100
+ import { captureException } from "../tracking/error-capture.js";
100
101
  import { track } from "../tracking/index.js";
101
102
  import { registerBuiltinProviders } from "../tracking/providers.js";
102
103
  import { validateTrackPayload } from "../tracking/route.js";
@@ -140,7 +141,7 @@ import {
140
141
  type BuilderRelayCredentials,
141
142
  type BuilderPreviewRelayState,
142
143
  } from "./builder-browser.js";
143
- import { captureError } from "./capture-error.js";
144
+ import { captureError, registerErrorCaptureProvider } from "./capture-error.js";
144
145
  import {
145
146
  getAllowedCorsOrigin,
146
147
  readCorsAllowedOrigins,
@@ -1197,6 +1198,14 @@ export function createCoreRoutesPlugin(
1197
1198
  // already registered the same key win.
1198
1199
  registerFrameworkSecrets();
1199
1200
  registerBuiltinProviders();
1201
+ registerErrorCaptureProvider("agent-native-analytics", (error, context) =>
1202
+ captureException(error, {
1203
+ ...context,
1204
+ handled: false,
1205
+ runtime: "node",
1206
+ source: "server",
1207
+ }),
1208
+ );
1200
1209
  registerBuiltinNotificationChannels();
1201
1210
 
1202
1211
  try {
@@ -602,33 +602,24 @@ function registerMiddleware(
602
602
  status,
603
603
  error: err,
604
604
  });
605
- // Forward 5xx to server-side Sentry — Nitro's own `error` hook may not
606
- // fire here because we convert the throw into a normal JSON response,
607
- // and a console.error alone is invisible in deployed environments.
608
- // 4xx are user-input errors (validation, auth) and aren't worth
609
- // alerting on. Lazy-loaded so the framework-request-handler module
610
- // doesn't pull @sentry/node into bundles that don't need it.
605
+ // Forward 5xx to the configured server error providers — Nitro's own
606
+ // `error` hook may not fire here because we convert the throw into a
607
+ // normal JSON response, and a console.error alone is invisible in
608
+ // deployed environments. 4xx are user-input errors (validation, auth)
609
+ // and aren't worth alerting on.
611
610
  if (status >= 500) {
612
- // Static `import` would create a cycle (sentry.ts imports auth.ts
613
- // which imports… eventually, framework-request-handler.ts).
614
- import("./sentry.js")
615
- .then(({ captureRouteError, isServerSentryEnabled }) => {
616
- if (!isServerSentryEnabled()) return;
617
- captureRouteError(err, {
618
- route: reqPath,
619
- method: event.method,
620
- userAgent: (() => {
621
- try {
622
- return event.headers?.get("user-agent") ?? undefined;
623
- } catch {
624
- return undefined;
625
- }
626
- })(),
627
- });
628
- })
629
- .catch(() => {
630
- // Sentry is observability — never let it break a response path.
631
- });
611
+ captureError(err, {
612
+ route: reqPath,
613
+ method: event.method,
614
+ tags: { status_code: String(status) },
615
+ userAgent: (() => {
616
+ try {
617
+ return event.headers?.get("user-agent") ?? undefined;
618
+ } catch {
619
+ return undefined;
620
+ }
621
+ })(),
622
+ });
632
623
  }
633
624
  try {
634
625
  setResponseStatus(event, status);
@@ -310,6 +310,10 @@
310
310
  opacity: 1;
311
311
  }
312
312
 
313
+ /* A named chat surface already morphs from its old geometry during a
314
+ full-page-chat handoff. Override only the initial style of that panel so it
315
+ does not slide in from the right underneath the morph. Keeping the normal
316
+ rules intact preserves ordinary sidebar open/close animation. */
313
317
  @starting-style {
314
318
  .agent-sidebar-panel[data-agent-sidebar-animation="desktop"][data-agent-sidebar-state="open"] {
315
319
  width: 0;
@@ -330,6 +334,15 @@
330
334
  .agent-sidebar-backdrop[data-agent-sidebar-animation="mobile"][data-agent-sidebar-state="open"] {
331
335
  opacity: 0;
332
336
  }
337
+
338
+ .agent-native-chat-view-transition.agent-sidebar-panel[data-agent-sidebar-animation="desktop"][data-agent-sidebar-chat-handoff="true"] {
339
+ width: var(--agent-sidebar-width);
340
+ }
341
+
342
+ .agent-native-chat-view-transition.agent-sidebar-panel[data-agent-sidebar-animation="desktop"][data-agent-sidebar-chat-handoff="true"]
343
+ > .agent-sidebar-panel-inner {
344
+ transform: translateX(0);
345
+ }
333
346
  }
334
347
 
335
348
  @media (prefers-reduced-motion: reduce) {
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AgentSidebar,
3
3
  focusAgentChat,
4
+ isAgentChatHomeHandoffActive,
4
5
  navigateWithAgentChatViewTransition,
5
6
  useAgentChatHomeHandoff,
6
7
  useAgentChatHomeHandoffLinks,
@@ -57,6 +58,7 @@ export function Layout({ children }: LayoutProps) {
57
58
  activePath: location.pathname,
58
59
  enabled: !isChatRoute,
59
60
  });
61
+ const chatHomeHandoffPending = isAgentChatHomeHandoffActive("chat");
60
62
  useAgentChatHomeHandoffLinks({
61
63
  storageKey: "chat",
62
64
  isChatPath: (pathname) => pathname === "/" || pathname.startsWith("/chat/"),
@@ -164,6 +166,7 @@ export function Layout({ children }: LayoutProps) {
164
166
  <AgentSidebar
165
167
  position="right"
166
168
  chatViewTransition
169
+ chatViewTransitionHandoff={chatHomeHandoffPending}
167
170
  storageKey="chat"
168
171
  browserTabId={TAB_ID}
169
172
  openOnChatRunning={chatHomeHandoffActive}
@@ -4,10 +4,11 @@ import {
4
4
  type ChatThreadSummary,
5
5
  } from "@agent-native/core/client/agent-chat";
6
6
  import { appPath } from "@agent-native/core/client/api-path";
7
- import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
8
- import { useT } from "@agent-native/core/client/i18n";
7
+ import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
8
+ import { openCommandMenu } from "@agent-native/core/client/navigation";
9
9
  import { OrgSwitcher } from "@agent-native/core/client/org";
10
10
  import { FeedbackButton } from "@agent-native/core/client/ui";
11
+ import { SidebarFooterActions } from "@agent-native/toolkit/app-shell";
11
12
  import {
12
13
  ChatHistoryRail,
13
14
  type ChatHistoryItem,
@@ -17,6 +18,7 @@ import {
17
18
  IconLayoutSidebarLeftCollapse,
18
19
  IconLayoutSidebarLeftExpand,
19
20
  IconMessageCircle,
21
+ IconSearch,
20
22
  IconSettings,
21
23
  } from "@tabler/icons-react";
22
24
  import { useEffect, useMemo } from "react";
@@ -38,6 +40,9 @@ const navItems = [
38
40
  href: "/",
39
41
  view: "chat",
40
42
  },
43
+ ];
44
+
45
+ const bottomNavItems = [
41
46
  {
42
47
  icon: IconHierarchy2,
43
48
  labelKey: "settings.agentTitle",
@@ -124,7 +129,7 @@ function chatThreadPath(threadId: string) {
124
129
  return `/chat/${encodeURIComponent(threadId)}`;
125
130
  }
126
131
 
127
- function ChatThreadsSection() {
132
+ function ChatThreadsSection({ open }: { open: boolean }) {
128
133
  const navigate = useNavigate();
129
134
  const location = useLocation();
130
135
  const t = useT();
@@ -228,36 +233,42 @@ function ChatThreadsSection() {
228
233
  }
229
234
 
230
235
  return (
231
- <div className="mt-2 ms-4">
232
- <ChatHistoryRail
233
- items={chatItems}
234
- activeId={displayedActiveThreadId}
235
- onSelect={(threadId) => openThread(threadId)}
236
- onNewChat={() => void handleNewChat()}
237
- railLabels={{
238
- newChat: t("chat.newChat"),
239
- showMore: t("chat.chats"),
240
- showLess: t("chat.chats"),
241
- }}
242
- renameMaxLength={160}
243
- onTogglePin={(threadId) => {
244
- const thread = visibleThreads.find((item) => item.id === threadId);
245
- if (thread) void pinThread(threadId, !thread.pinnedAt);
246
- }}
247
- onRename={handleRenameThread}
248
- onDelete={(threadId) => void handleArchiveThread(threadId)}
249
- labels={{
250
- options: (item) =>
251
- t("chat.optionsFor", { title: item.titleText ?? "" }),
252
- renameInput: (item) =>
253
- t("chat.renameThread", { title: item.titleText ?? "" }),
254
- rename: t("chat.renameChat"),
255
- pin: t("chat.pinChat"),
256
- unpin: t("chat.unpinChat"),
257
- delete: t("chat.archiveChat"),
258
- }}
259
- className="min-w-0"
260
- />
236
+ <div
237
+ className="an-chat-history-rail__collapse"
238
+ data-state={open ? "open" : "closed"}
239
+ aria-hidden={!open}
240
+ >
241
+ <div className="ms-4">
242
+ <ChatHistoryRail
243
+ items={chatItems}
244
+ activeId={displayedActiveThreadId}
245
+ onSelect={(threadId) => openThread(threadId)}
246
+ onNewChat={() => void handleNewChat()}
247
+ railLabels={{
248
+ newChat: t("chat.newChat"),
249
+ showMore: t("chat.chats"),
250
+ showLess: t("chat.chats"),
251
+ }}
252
+ renameMaxLength={160}
253
+ onTogglePin={(threadId) => {
254
+ const thread = visibleThreads.find((item) => item.id === threadId);
255
+ if (thread) void pinThread(threadId, !thread.pinnedAt);
256
+ }}
257
+ onRename={handleRenameThread}
258
+ onDelete={(threadId) => void handleArchiveThread(threadId)}
259
+ labels={{
260
+ options: (item) =>
261
+ t("chat.optionsFor", { title: item.titleText ?? "" }),
262
+ renameInput: (item) =>
263
+ t("chat.renameThread", { title: item.titleText ?? "" }),
264
+ rename: t("chat.renameChat"),
265
+ pin: t("chat.pinChat"),
266
+ unpin: t("chat.unpinChat"),
267
+ delete: t("chat.archiveChat"),
268
+ }}
269
+ className="min-w-0"
270
+ />
271
+ </div>
261
272
  </div>
262
273
  );
263
274
  }
@@ -279,14 +290,14 @@ export function Sidebar({
279
290
  cn(
280
291
  "flex items-center text-sm transition-colors",
281
292
  collapsed
282
- ? "relative h-10 w-full justify-center rounded-none border-s-2 px-0"
293
+ ? "relative h-10 w-full justify-center rounded-none px-0"
283
294
  : "h-9 rounded-md gap-3 px-3",
284
295
  isActive
285
296
  ? collapsed
286
- ? "border-s-sidebar-accent-foreground/80 bg-sidebar-accent text-sidebar-accent-foreground"
297
+ ? "bg-sidebar-accent text-sidebar-accent-foreground"
287
298
  : "bg-sidebar-accent text-sidebar-accent-foreground"
288
299
  : collapsed
289
- ? "border-s-transparent text-sidebar-foreground/70 hover:bg-sidebar-accent/55 hover:text-sidebar-accent-foreground"
300
+ ? "text-sidebar-foreground/70 hover:bg-sidebar-accent/55 hover:text-sidebar-accent-foreground"
290
301
  : "text-sidebar-foreground hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground",
291
302
  );
292
303
  const collapseButton = collapsible ? (
@@ -315,6 +326,31 @@ export function Sidebar({
315
326
  </TooltipContent>
316
327
  </Tooltip>
317
328
  ) : null;
329
+ const searchButton = (
330
+ <Tooltip>
331
+ <TooltipTrigger asChild>
332
+ <button
333
+ type="button"
334
+ onClick={openCommandMenu}
335
+ aria-label={t("root.commandSearch")}
336
+ className="flex size-8 items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
337
+ >
338
+ <IconSearch className="size-4" />
339
+ </button>
340
+ </TooltipTrigger>
341
+ <TooltipContent side="right">{t("root.commandSearch")}</TooltipContent>
342
+ </Tooltip>
343
+ );
344
+ const translateButton = (
345
+ <LanguagePicker variant="ghost-icon" label={t("settings.languageLabel")} />
346
+ );
347
+ const feedbackButton = (
348
+ <FeedbackButton
349
+ variant={collapsed ? "icon" : "sidebar"}
350
+ side="right"
351
+ className={collapsed ? "h-8 w-8" : "min-w-0"}
352
+ />
353
+ );
318
354
 
319
355
  return (
320
356
  <aside
@@ -409,8 +445,8 @@ export function Sidebar({
409
445
  ) : (
410
446
  link
411
447
  )}
412
- {!collapsed && item.view === "chat" && isChatRoute ? (
413
- <ChatThreadsSection />
448
+ {!collapsed && item.view === "chat" ? (
449
+ <ChatThreadsSection open={isChatRoute} />
414
450
  ) : null}
415
451
  </div>
416
452
  );
@@ -419,11 +455,38 @@ export function Sidebar({
419
455
  </nav>
420
456
 
421
457
  <div className={cn("mt-auto shrink-0", collapsed && "py-2")}>
422
- {!collapsed ? (
423
- <div className="px-2 py-1">
424
- <ExtensionsSidebarSection />
425
- </div>
426
- ) : null}
458
+ <nav
459
+ className={cn(
460
+ "grid",
461
+ collapsed ? "gap-0 px-1 py-1" : "gap-1 px-2 py-1",
462
+ )}
463
+ >
464
+ {bottomNavItems.map((item) => {
465
+ const Icon = item.icon;
466
+ const isActive = location.pathname.startsWith(item.href);
467
+ const link = (
468
+ <Link
469
+ to={item.href}
470
+ className={navClass({ isActive })}
471
+ aria-current={isActive ? "page" : undefined}
472
+ aria-label={collapsed ? t(item.labelKey) : undefined}
473
+ >
474
+ <Icon className="size-4 shrink-0" />
475
+ <span className={collapsed ? "sr-only" : "truncate"}>
476
+ {t(item.labelKey)}
477
+ </span>
478
+ </Link>
479
+ );
480
+ return collapsed ? (
481
+ <Tooltip key={item.href}>
482
+ <TooltipTrigger asChild>{link}</TooltipTrigger>
483
+ <TooltipContent side="right">{t(item.labelKey)}</TooltipContent>
484
+ </Tooltip>
485
+ ) : (
486
+ <div key={item.href}>{link}</div>
487
+ );
488
+ })}
489
+ </nav>
427
490
 
428
491
  <div className={cn(collapsed ? "px-1 py-1" : "px-3 py-2")}>
429
492
  <OrgSwitcher
@@ -436,14 +499,13 @@ export function Sidebar({
436
499
  />
437
500
  </div>
438
501
 
439
- {!collapsed ? (
440
- <div className="flex items-center justify-end gap-1 px-3 py-2">
441
- <FeedbackButton className="min-w-0 flex-1" side="right" />
442
- {collapseButton}
443
- </div>
444
- ) : collapseButton ? (
445
- <div className="flex justify-center px-1 py-1">{collapseButton}</div>
446
- ) : null}
502
+ <SidebarFooterActions
503
+ collapsed={collapsed}
504
+ feedback={feedbackButton}
505
+ translate={translateButton}
506
+ search={searchButton}
507
+ collapse={collapseButton}
508
+ />
447
509
  </div>
448
510
  </aside>
449
511
  );
@@ -22,7 +22,7 @@
22
22
  --muted-foreground: 0 0% 45%;
23
23
  --accent: 0 0% 95%;
24
24
  --accent-foreground: 0 0% 15%;
25
- --destructive: 0 84% 60%;
25
+ --destructive: 0 91% 71%;
26
26
  --destructive-foreground: 0 0% 98%;
27
27
  --border: 0 0% 90%;
28
28
  --input: 0 0% 90%;
@@ -1,4 +1,4 @@
1
- import { ExtensionsListPage } from "@agent-native/core/client/extensions";
1
+ import { Navigate } from "react-router";
2
2
 
3
3
  import { APP_TITLE } from "@/lib/app-config";
4
4
 
@@ -7,5 +7,5 @@ export function meta() {
7
7
  }
8
8
 
9
9
  export default function ExtensionsRoute() {
10
- return <ExtensionsListPage />;
10
+ return <Navigate to="/settings#extensions" replace />;
11
11
  }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Secondary controls and dashboard surfaces now use quieter borderless styling.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-24
4
+ ---
5
+
6
+ Sidebar utility controls now follow a consistent footer order.
@@ -6,5 +6,6 @@ functions = "templates/chat/.netlify/functions-internal"
6
6
 
7
7
  [build.environment]
8
8
  GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
9
+ GTM_CONTAINER_ID = "GTM-N3WSTXZ"
9
10
  NITRO_PRESET = "netlify"
10
11
  NPM_CONFIG_PRODUCTION = "false"
@@ -52,7 +52,7 @@
52
52
  --muted-foreground: 0 0% 60%;
53
53
  --accent: 0 0% 18%;
54
54
  --accent-foreground: 0 0% 90%;
55
- --destructive: 0 84% 60%;
55
+ --destructive: 0 91% 71%;
56
56
  --destructive-foreground: 0 0% 98%;
57
57
  --border: 0 0% 24%;
58
58
  --input: 0 0% 24%;
@@ -76,6 +76,22 @@ Full source-code customization is a core Agent Native capability. Extensions
76
76
  are the fast, sandboxed, no-deploy layer—not the limit of what the app can
77
77
  become.
78
78
 
79
+ Use this decision rule when either path could solve the request:
80
+
81
+ - Start with an extension for a self-contained, relatively one-off widget,
82
+ custom visualization or interaction, dashboard tile, standalone utility, or
83
+ add-on in an existing slot.
84
+ - Use app code for a core template feature, native UI/layout/routes/business
85
+ logic, a new slot, or behavior that should be reused broadly across dashboards
86
+ or users.
87
+ - If the same extension keeps getting rebuilt, promote it into app code as one
88
+ reusable native feature instead of maintaining copies.
89
+
90
+ As a rule of thumb, if an extension can solve the problem, generally start
91
+ there. An isolated custom dashboard visualization belongs in an extension; a
92
+ new chart type that should be available across dashboards belongs in the
93
+ template code.
94
+
79
95
  **When a user asks to "make an extension", "create an extension", or "build
80
96
  a ... extension" (or the older phrasings "make a tool" / "create a tool"):**
81
97
 
@@ -0,0 +1,151 @@
1
+ import { trackingIdentityProperties } from "../observability/tracking-identity.js";
2
+ import type { CaptureErrorContext } from "../server/capture-error.js";
3
+ import { track } from "./registry.js";
4
+
5
+ export type TrackingExceptionLevel =
6
+ | "fatal"
7
+ | "error"
8
+ | "warning"
9
+ | "info"
10
+ | "debug";
11
+
12
+ export interface TrackingExceptionContext extends CaptureErrorContext {
13
+ /** Whether the caller handled the error. Server error hooks default false. */
14
+ handled?: boolean;
15
+ level?: TrackingExceptionLevel;
16
+ release?: string;
17
+ environment?: string;
18
+ runtime?: "node" | "cli";
19
+ source?: "server" | "cli";
20
+ }
21
+
22
+ const MAX_MESSAGE_LENGTH = 1000;
23
+ const MAX_STACK_LENGTH = 8000;
24
+ const MAX_TAGS = 30;
25
+ const MAX_EXTRA_KEYS = 30;
26
+ const MAX_EXTRA_VALUE_LENGTH = 1000;
27
+ const SECRET_RE = /\b(?:bearer|basic)\s+[^\s]+/gi;
28
+ const SECRET_KEY_RE =
29
+ /(?:authorization|cookie|set[-_]?cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)/i;
30
+
31
+ function redact(value: string): string {
32
+ return value
33
+ .replace(SECRET_RE, (match) => `${match.split(/\s+/, 1)[0]} <redacted>`)
34
+ .replace(
35
+ /([A-Za-z0-9_$.-]*(?:authorization|cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)[A-Za-z0-9_$.-]*\s*[:=]\s*)([^\s,;}]+)/gi,
36
+ "$1<redacted>",
37
+ );
38
+ }
39
+
40
+ function boundedText(value: unknown, max: number): string {
41
+ const text = typeof value === "string" ? value : String(value ?? "");
42
+ const safe = redact(text);
43
+ return safe.length > max ? safe.slice(0, max) : safe;
44
+ }
45
+
46
+ function safeValue(value: unknown, depth = 2): unknown {
47
+ if (
48
+ value == null ||
49
+ typeof value === "boolean" ||
50
+ typeof value === "number"
51
+ ) {
52
+ return value;
53
+ }
54
+ if (typeof value === "string")
55
+ return boundedText(value, MAX_EXTRA_VALUE_LENGTH);
56
+ if (depth <= 0) return boundedText(value, MAX_EXTRA_VALUE_LENGTH);
57
+ if (Array.isArray(value)) {
58
+ return value.slice(0, 20).map((item) => safeValue(item, depth - 1));
59
+ }
60
+ if (typeof value === "object") {
61
+ const out: Record<string, unknown> = {};
62
+ for (const [key, child] of Object.entries(value)) {
63
+ if (Object.keys(out).length >= MAX_EXTRA_KEYS) break;
64
+ const safeKey = boundedText(key, 100);
65
+ out[safeKey] = SECRET_KEY_RE.test(safeKey)
66
+ ? "<redacted>"
67
+ : safeValue(child, depth - 1);
68
+ }
69
+ return out;
70
+ }
71
+ return boundedText(value, MAX_EXTRA_VALUE_LENGTH);
72
+ }
73
+
74
+ function exceptionParts(error: unknown): {
75
+ type: string;
76
+ message: string;
77
+ stack?: string;
78
+ } {
79
+ if (error instanceof Error) {
80
+ return {
81
+ type: boundedText(error.name || "Error", 200),
82
+ message: boundedText(
83
+ error.message || error.name || "Error",
84
+ MAX_MESSAGE_LENGTH,
85
+ ),
86
+ ...(error.stack
87
+ ? { stack: boundedText(error.stack, MAX_STACK_LENGTH) }
88
+ : {}),
89
+ };
90
+ }
91
+ return {
92
+ type: "Error",
93
+ message: boundedText(error, MAX_MESSAGE_LENGTH),
94
+ };
95
+ }
96
+
97
+ function safeTags(
98
+ tags: Record<string, string | undefined> | undefined,
99
+ ): Record<string, string> {
100
+ const out: Record<string, string> = {};
101
+ for (const [key, value] of Object.entries(tags ?? {})) {
102
+ if (Object.keys(out).length >= MAX_TAGS || value == null) break;
103
+ const safeKey = boundedText(key, 100);
104
+ out[safeKey] = SECRET_KEY_RE.test(safeKey)
105
+ ? "<redacted>"
106
+ : boundedText(value, 200);
107
+ }
108
+ return out;
109
+ }
110
+
111
+ /** Emit a bounded, redacted Node/CLI exception through first-party tracking. */
112
+ export function captureException(
113
+ error: unknown,
114
+ context: TrackingExceptionContext = {},
115
+ ): void {
116
+ try {
117
+ const parts = exceptionParts(error);
118
+ const tags = safeTags({
119
+ ...context.tags,
120
+ ...(context.route ? { route: context.route } : {}),
121
+ ...(context.method ? { method: context.method } : {}),
122
+ ...(context.userAgent ? { userAgent: context.userAgent } : {}),
123
+ });
124
+ const extra = safeValue({
125
+ ...context.extra,
126
+ ...(context.contexts ? { contexts: context.contexts } : {}),
127
+ });
128
+ track("$exception", {
129
+ ...trackingIdentityProperties(),
130
+ exceptionType: parts.type,
131
+ exceptionMessage: parts.message,
132
+ ...(parts.stack ? { exceptionStack: parts.stack } : {}),
133
+ handled: context.handled ?? true,
134
+ level: context.level ?? "error",
135
+ occurredAt: new Date().toISOString(),
136
+ runtime: context.runtime ?? "node",
137
+ source: context.source ?? "server",
138
+ ...(context.route ? { url: boundedText(context.route, 500) } : {}),
139
+ ...(context.release
140
+ ? { release: boundedText(context.release, 200) }
141
+ : {}),
142
+ ...(context.environment
143
+ ? { environment: boundedText(context.environment, 100) }
144
+ : {}),
145
+ ...(Object.keys(tags).length ? { exceptionTags: tags } : {}),
146
+ ...(extra && typeof extra === "object" ? { exceptionExtra: extra } : {}),
147
+ });
148
+ } catch {
149
+ // Error reporting must never mask the original failure.
150
+ }
151
+ }
@@ -7,4 +7,9 @@ export {
7
7
  listTrackingProviders,
8
8
  } from "./registry.js";
9
9
  export { registerBuiltinProviders } from "./providers.js";
10
+ export {
11
+ captureException,
12
+ type TrackingExceptionContext,
13
+ type TrackingExceptionLevel,
14
+ } from "./error-capture.js";
10
15
  export type { TrackingProvider, TrackingEvent } from "./types.js";
@@ -3066,6 +3066,12 @@ function createAgentNativeConfig(
3066
3066
  "process.env.AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID": JSON.stringify(
3067
3067
  process.env.GA_MEASUREMENT_ID?.trim() || "",
3068
3068
  ),
3069
+ __AGENT_NATIVE_BUILD_GTM_CONTAINER_ID__: JSON.stringify(
3070
+ process.env.GTM_CONTAINER_ID?.trim() || "",
3071
+ ),
3072
+ "process.env.AGENT_NATIVE_BUILD_GTM_CONTAINER_ID": JSON.stringify(
3073
+ process.env.GTM_CONTAINER_ID?.trim() || "",
3074
+ ),
3069
3075
  // Framework route warmup controls how SSR `.data` routes are fetched:
3070
3076
  // ordinary fetches keep them CDN-cacheable, while native prefetch headers
3071
3077
  // can be refused before the CDN/origin sees the request. Keep this value