@agent-native/core 0.115.4 → 0.117.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (487) hide show
  1. package/agent-native.eject.json +1 -0
  2. package/corpus/README.md +3 -3
  3. package/corpus/core/CHANGELOG.md +43 -0
  4. package/corpus/core/agent-native.eject.json +1 -0
  5. package/corpus/core/docs/AGENTS.md +1 -1
  6. package/corpus/core/docs/content/agent-mentions.mdx +2 -2
  7. package/corpus/core/docs/content/{workspace.mdx → agent-resources.mdx} +1 -7
  8. package/corpus/core/docs/content/agent-teams.mdx +4 -4
  9. package/corpus/core/docs/content/dispatch.mdx +10 -10
  10. package/corpus/core/docs/content/drop-in-agent.mdx +4 -4
  11. package/corpus/core/docs/content/external-agents.mdx +1 -1
  12. package/corpus/core/docs/content/frames.mdx +1 -1
  13. package/corpus/core/docs/content/integrations.mdx +13 -2
  14. package/corpus/core/docs/content/key-concepts.mdx +2 -2
  15. package/corpus/core/docs/content/mcp-clients.mdx +7 -1
  16. package/corpus/core/docs/content/multi-app-workspace.mdx +3 -3
  17. package/corpus/core/docs/content/real-time-collaboration.mdx +33 -15
  18. package/corpus/core/docs/content/recurring-jobs.mdx +7 -7
  19. package/corpus/core/docs/content/skills-guide.mdx +4 -4
  20. package/corpus/core/docs/content/template-brain.mdx +1 -1
  21. package/corpus/core/docs/content/toolkit-collaboration.mdx +1 -1
  22. package/corpus/core/docs/content/using-your-agent.mdx +1 -1
  23. package/corpus/core/docs/content/what-is-agent-native.mdx +4 -4
  24. package/corpus/core/docs/content/workspace-management.mdx +4 -4
  25. package/corpus/core/package.json +4 -1
  26. package/corpus/core/src/agent/production-agent.ts +13 -3
  27. package/corpus/core/src/cli/doctor.ts +6 -1
  28. package/corpus/core/src/client/AgentPanel.tsx +79 -41
  29. package/corpus/core/src/client/AssistantChat.tsx +71 -25
  30. package/corpus/core/src/client/FeedbackButton.tsx +33 -7
  31. package/corpus/core/src/client/MultiTabAssistantChat.tsx +6 -8
  32. package/corpus/core/src/client/agent-chat-adapter.ts +11 -2
  33. package/corpus/core/src/client/agent-page/AgentTabFrame.tsx +22 -3
  34. package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +34 -19
  35. package/corpus/core/src/client/analytics.ts +7 -0
  36. package/corpus/core/src/client/chat/message-components.tsx +43 -16
  37. package/corpus/core/src/client/chat/tool-call-display.tsx +30 -18
  38. package/corpus/core/src/client/chat/tool-render-registry.tsx +2 -0
  39. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +19 -2
  40. package/corpus/core/src/client/resources/ResourceTree.tsx +7 -10
  41. package/corpus/core/src/client/resources/ResourcesPanel.tsx +33 -70
  42. package/corpus/core/src/client/resources/mcp-connection-resume.ts +107 -0
  43. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +65 -12
  44. package/corpus/core/src/client/resources/mcp-integration-logos.ts +4 -0
  45. package/corpus/core/src/client/sse-event-processor.ts +50 -14
  46. package/corpus/core/src/client/use-db-sync.ts +370 -21
  47. package/corpus/core/src/collab/client.ts +26 -2
  48. package/corpus/core/src/connections/catalog.ts +7 -1
  49. package/corpus/core/src/db/ddl-guard.ts +49 -10
  50. package/corpus/core/src/deploy/build.ts +25 -2
  51. package/corpus/core/src/eject/remote-mcp-presets.ts +37 -5
  52. package/corpus/core/src/guards/explicit-collab-access.ts +229 -0
  53. package/corpus/core/src/guards/index.ts +1 -0
  54. package/corpus/core/src/localization/default-messages.ts +54 -5
  55. package/corpus/core/src/mcp/connect-route.ts +34 -51
  56. package/corpus/core/src/provider-api/index.ts +1 -1
  57. package/corpus/core/src/realtime-protocol.ts +92 -0
  58. package/corpus/core/src/server/collab-plugin.ts +137 -18
  59. package/corpus/core/src/server/core-routes-plugin.ts +7 -0
  60. package/corpus/core/src/server/index.ts +2 -0
  61. package/corpus/core/src/server/poll-events.ts +29 -8
  62. package/corpus/core/src/server/poll.ts +1123 -865
  63. package/corpus/core/src/server/realtime-token.ts +106 -0
  64. package/corpus/core/src/server/sentry-config.ts +40 -0
  65. package/corpus/core/src/server/short-lived-token.ts +156 -0
  66. package/corpus/core/src/server/sse.ts +15 -0
  67. package/corpus/core/src/server/ssr-handler.ts +9 -3
  68. package/corpus/core/src/styles/agent-native.css +40 -0
  69. package/corpus/core/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  70. package/corpus/core/src/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
  71. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  72. package/corpus/core/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  73. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  74. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
  75. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  76. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
  77. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  78. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
  79. package/corpus/templates/analytics/AGENTS.md +7 -2
  80. package/corpus/templates/analytics/actions/export-dashboard-panel-to-google-sheet.ts +144 -0
  81. package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -88
  82. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +34 -37
  83. package/corpus/templates/analytics/app/global.css +0 -4
  84. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +2 -7
  85. package/corpus/templates/analytics/app/i18n-data.ts +107 -0
  86. package/corpus/templates/analytics/app/lib/data-source-status.ts +9 -0
  87. package/corpus/templates/analytics/app/lib/sql-query.ts +1 -2
  88. package/corpus/templates/analytics/app/pages/Ask.tsx +2 -7
  89. package/corpus/templates/analytics/app/pages/DataSources.tsx +48 -0
  90. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +59 -0
  91. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -0
  92. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-panel-window.ts +3 -1
  93. package/corpus/templates/analytics/changelog/2026-07-22-clear-background-chat-progress.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-22-daily-dashboard-email-query-batches.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-07-22-export-table-panels-directly-to-google-sheets.md +6 -0
  96. package/corpus/templates/analytics/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  97. package/corpus/templates/analytics/changelog/2026-07-22-recent-chats-can-expand-in-the-sidebar.md +6 -0
  98. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +8 -8
  99. package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +31 -0
  100. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +3 -5
  101. package/corpus/templates/analytics/server/lib/dashboard-report.ts +12 -0
  102. package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +3 -5
  103. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +150 -21
  104. package/corpus/templates/analytics/server/lib/google-sheets-export.ts +188 -0
  105. package/corpus/templates/analytics/server/lib/provider-api.ts +7 -2
  106. package/corpus/templates/analytics/server/plugins/collab.ts +6 -3
  107. package/corpus/templates/analytics/shared/sql-query-limits.ts +1 -0
  108. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  109. package/corpus/templates/assets/.agents/skills/real-time-collab/SKILL.md +35 -13
  110. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
  111. package/corpus/templates/assets/app/components/layout/Layout.tsx +1 -1
  112. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +54 -62
  113. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -6
  114. package/corpus/templates/assets/app/routes/_index.tsx +8 -5
  115. package/corpus/templates/assets/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  116. package/corpus/templates/assets/changelog/2026-07-22-recent-chats-expand-from-a-compact-list.md +6 -0
  117. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  118. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
  119. package/corpus/templates/brain/actions/rotate-source-ingest-token.ts +77 -0
  120. package/corpus/templates/brain/app/components/layout/Layout.tsx +5 -1
  121. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +38 -51
  122. package/corpus/templates/brain/app/hooks/use-navigation-state.ts +2 -9
  123. package/corpus/templates/brain/app/i18n-data.ts +120 -0
  124. package/corpus/templates/brain/app/routes/sources.tsx +156 -5
  125. package/corpus/templates/brain/changelog/2026-07-22-chat-runs-always-end-with-an-answer.md +6 -0
  126. package/corpus/templates/brain/changelog/2026-07-22-clear-background-chat-progress.md +6 -0
  127. package/corpus/templates/brain/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  128. package/corpus/templates/brain/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  129. package/corpus/templates/brain/changelog/2026-07-22-long-chat-titles-stay-inside-the-sidebar.md +6 -0
  130. package/corpus/templates/brain/changelog/2026-07-22-new-clips-and-webhook-sources-now-show-their-secure-connecti.md +6 -0
  131. package/corpus/templates/brain/jobs/emit-netlify-brain-queue-cron.ts +125 -0
  132. package/corpus/templates/brain/netlify.toml +5 -1
  133. package/corpus/templates/brain/scripts/configure-prod-clips-source.ts +50 -0
  134. package/corpus/templates/brain/server/lib/capture-sanitization.ts +64 -6
  135. package/corpus/templates/brain/server/plugins/agent-chat.ts +4 -0
  136. package/corpus/templates/brain/server/plugins/brain-jobs.ts +1 -0
  137. package/corpus/templates/brain/server/routes/api/brain/queue/run.post.ts +55 -0
  138. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  139. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
  140. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  141. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  142. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -0
  143. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +43 -67
  144. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +2 -7
  145. package/corpus/templates/chat/app/routes/_index.tsx +8 -5
  146. package/corpus/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  147. package/corpus/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  148. package/corpus/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  149. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  150. package/corpus/templates/clips/AGENTS.md +9 -1
  151. package/corpus/templates/clips/actions/export-to-brain.ts +82 -6
  152. package/corpus/templates/clips/actions/request-transcript.ts +25 -14
  153. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +12 -0
  154. package/corpus/templates/clips/app/i18n/en-US.ts +1 -0
  155. package/corpus/templates/clips/changelog/2026-07-22-clips-transcripts-now-retry-brain-export.md +5 -0
  156. package/corpus/templates/clips/changelog/2026-07-22-german-umlauts-and-other-non-ascii-characters-now-paste-corr.md +6 -0
  157. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +26 -3
  158. package/corpus/templates/clips/jobs/emit-netlify-brain-export-cron.ts +118 -0
  159. package/corpus/templates/clips/netlify.toml +4 -1
  160. package/corpus/templates/clips/scripts/configure-prod-brain-export.ts +92 -0
  161. package/corpus/templates/clips/server/jobs/brain-export.ts +182 -0
  162. package/corpus/templates/clips/server/lib/brain-export-state.ts +42 -0
  163. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +5 -1
  164. package/corpus/templates/clips/server/plugins/calendar-jobs.ts +2 -0
  165. package/corpus/templates/clips/server/register-secrets.ts +42 -0
  166. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +10 -1
  167. package/corpus/templates/clips/server/routes/api/clips/brain-export/run.post.ts +45 -0
  168. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  169. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
  170. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +566 -299
  171. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +14 -0
  172. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +1 -1
  173. package/corpus/templates/content/app/i18n-data.ts +90 -0
  174. package/corpus/templates/content/server/plugins/collab.ts +1 -1
  175. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  176. package/corpus/templates/crm/actions/_crm-data-program-actions.ts +15 -0
  177. package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +2 -0
  178. package/corpus/templates/crm/actions/run.ts +2 -6
  179. package/corpus/templates/crm/actions/update-crm-record.ts +4 -2
  180. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +6 -0
  181. package/corpus/templates/crm/changelog/2026-07-22-crm-field-validation-now-explains-which-fields-cannot-be-edi.md +6 -0
  182. package/corpus/templates/crm/changelog/2026-07-22-fixed-hubspot-contact-syncs-missing-records-updated-after-th.md +6 -0
  183. package/corpus/templates/crm/changelog/2026-07-22-fixed-pipeline-dashboard-panels-so-their-opportunity-data-lo.md +6 -0
  184. package/corpus/templates/crm/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  185. package/corpus/templates/crm/server/crm/hubspot-adapter.ts +4 -1
  186. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  187. package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
  188. package/corpus/templates/design/server/plugins/collab.ts +11 -8
  189. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  190. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  191. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
  192. package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -0
  193. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +1 -1
  194. package/corpus/templates/forms/app/hooks/use-navigation-state.ts +2 -9
  195. package/corpus/templates/forms/app/root.tsx +1 -6
  196. package/corpus/templates/forms/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  197. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  198. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  199. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
  200. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
  201. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  202. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
  203. package/corpus/templates/plan/app/components/layout/Layout.tsx +5 -1
  204. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +57 -72
  205. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +2 -9
  206. package/corpus/templates/plan/app/lib/create-plan-routing.ts +2 -2
  207. package/corpus/templates/plan/app/pages/PlanChatPage.tsx +0 -1
  208. package/corpus/templates/plan/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  209. package/corpus/templates/plan/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  210. package/corpus/templates/plan/changelog/2026-07-22-recent-chats-and-sidebar-controls-are-more-compact.md +6 -0
  211. package/corpus/templates/plan/server/plugins/collab.ts +5 -2
  212. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  213. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +1 -1
  214. package/corpus/templates/slides/server/plugins/collab.ts +11 -8
  215. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  216. package/corpus/templates/tasks/.agents/skills/real-time-sync/SKILL.md +1 -1
  217. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +5 -22
  218. package/corpus/templates/tasks/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  219. package/corpus/toolkit/CHANGELOG.md +7 -0
  220. package/corpus/toolkit/README.md +12 -3
  221. package/corpus/toolkit/package.json +1 -1
  222. package/corpus/toolkit/src/chat-history/ChatHistoryRail.tsx +89 -0
  223. package/corpus/toolkit/src/chat-history/index.ts +5 -0
  224. package/corpus/toolkit/src/chat-history.css +59 -0
  225. package/corpus/toolkit/src/composer/RealtimeVoiceMode.tsx +106 -36
  226. package/corpus/toolkit/src/composer/VoiceButton.tsx +49 -0
  227. package/corpus/toolkit/src/composer/realtime-voice-audio-level.ts +2 -1
  228. package/corpus/toolkit/src/composer/useRealtimeVoiceMode.tsx +5 -3
  229. package/corpus/toolkit/src/styles.css +35 -0
  230. package/dist/agent/production-agent.d.ts.map +1 -1
  231. package/dist/agent/production-agent.js +13 -3
  232. package/dist/agent/production-agent.js.map +1 -1
  233. package/dist/cli/doctor.d.ts +1 -1
  234. package/dist/cli/doctor.d.ts.map +1 -1
  235. package/dist/cli/doctor.js +5 -2
  236. package/dist/cli/doctor.js.map +1 -1
  237. package/dist/client/AgentPanel.d.ts +1 -0
  238. package/dist/client/AgentPanel.d.ts.map +1 -1
  239. package/dist/client/AgentPanel.js +38 -18
  240. package/dist/client/AgentPanel.js.map +1 -1
  241. package/dist/client/AssistantChat.d.ts.map +1 -1
  242. package/dist/client/AssistantChat.js +55 -20
  243. package/dist/client/AssistantChat.js.map +1 -1
  244. package/dist/client/FeedbackButton.d.ts +4 -2
  245. package/dist/client/FeedbackButton.d.ts.map +1 -1
  246. package/dist/client/FeedbackButton.js +18 -2
  247. package/dist/client/FeedbackButton.js.map +1 -1
  248. package/dist/client/MultiTabAssistantChat.d.ts +1 -1
  249. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  250. package/dist/client/MultiTabAssistantChat.js +2 -3
  251. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  252. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  253. package/dist/client/agent-chat-adapter.js +11 -3
  254. package/dist/client/agent-chat-adapter.js.map +1 -1
  255. package/dist/client/agent-page/AgentTabFrame.d.ts +3 -1
  256. package/dist/client/agent-page/AgentTabFrame.d.ts.map +1 -1
  257. package/dist/client/agent-page/AgentTabFrame.js +3 -2
  258. package/dist/client/agent-page/AgentTabFrame.js.map +1 -1
  259. package/dist/client/agent-page/AgentTabsPage.d.ts +2 -0
  260. package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
  261. package/dist/client/agent-page/AgentTabsPage.js +26 -15
  262. package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
  263. package/dist/client/analytics.d.ts +10 -0
  264. package/dist/client/analytics.d.ts.map +1 -1
  265. package/dist/client/analytics.js.map +1 -1
  266. package/dist/client/chat/message-components.d.ts +6 -1
  267. package/dist/client/chat/message-components.d.ts.map +1 -1
  268. package/dist/client/chat/message-components.js +17 -11
  269. package/dist/client/chat/message-components.js.map +1 -1
  270. package/dist/client/chat/tool-call-display.d.ts +11 -1
  271. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  272. package/dist/client/chat/tool-call-display.js +16 -17
  273. package/dist/client/chat/tool-call-display.js.map +1 -1
  274. package/dist/client/chat/tool-render-registry.d.ts +2 -0
  275. package/dist/client/chat/tool-render-registry.d.ts.map +1 -1
  276. package/dist/client/chat/tool-render-registry.js.map +1 -1
  277. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
  278. package/dist/client/resources/McpConnectionSuggestion.js +15 -1
  279. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
  280. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  281. package/dist/client/resources/ResourceTree.js +3 -3
  282. package/dist/client/resources/ResourceTree.js.map +1 -1
  283. package/dist/client/resources/ResourcesPanel.d.ts +1 -0
  284. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  285. package/dist/client/resources/ResourcesPanel.js +34 -20
  286. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  287. package/dist/client/resources/mcp-connection-resume.d.ts +11 -0
  288. package/dist/client/resources/mcp-connection-resume.d.ts.map +1 -0
  289. package/dist/client/resources/mcp-connection-resume.js +95 -0
  290. package/dist/client/resources/mcp-connection-resume.js.map +1 -0
  291. package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
  292. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  293. package/dist/client/resources/mcp-integration-catalog.js +63 -8
  294. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  295. package/dist/client/resources/mcp-integration-logos.d.ts.map +1 -1
  296. package/dist/client/resources/mcp-integration-logos.js +4 -0
  297. package/dist/client/resources/mcp-integration-logos.js.map +1 -1
  298. package/dist/client/sse-event-processor.d.ts +5 -0
  299. package/dist/client/sse-event-processor.d.ts.map +1 -1
  300. package/dist/client/sse-event-processor.js +39 -13
  301. package/dist/client/sse-event-processor.js.map +1 -1
  302. package/dist/client/use-db-sync.d.ts +4 -3
  303. package/dist/client/use-db-sync.d.ts.map +1 -1
  304. package/dist/client/use-db-sync.js +332 -21
  305. package/dist/client/use-db-sync.js.map +1 -1
  306. package/dist/collab/client.d.ts.map +1 -1
  307. package/dist/collab/client.js +26 -2
  308. package/dist/collab/client.js.map +1 -1
  309. package/dist/collab/routes.d.ts +1 -1
  310. package/dist/connections/catalog.d.ts +1 -1
  311. package/dist/connections/catalog.d.ts.map +1 -1
  312. package/dist/connections/catalog.js +7 -1
  313. package/dist/connections/catalog.js.map +1 -1
  314. package/dist/db/ddl-guard.d.ts +7 -2
  315. package/dist/db/ddl-guard.d.ts.map +1 -1
  316. package/dist/db/ddl-guard.js +21 -9
  317. package/dist/db/ddl-guard.js.map +1 -1
  318. package/dist/deploy/build.d.ts.map +1 -1
  319. package/dist/deploy/build.js +25 -2
  320. package/dist/deploy/build.js.map +1 -1
  321. package/dist/eject/remote-mcp-presets.d.ts.map +1 -1
  322. package/dist/eject/remote-mcp-presets.js +33 -3
  323. package/dist/eject/remote-mcp-presets.js.map +1 -1
  324. package/dist/guards/explicit-collab-access.d.ts +8 -0
  325. package/dist/guards/explicit-collab-access.d.ts.map +1 -0
  326. package/dist/guards/explicit-collab-access.js +214 -0
  327. package/dist/guards/explicit-collab-access.js.map +1 -0
  328. package/dist/guards/index.d.ts +1 -0
  329. package/dist/guards/index.d.ts.map +1 -1
  330. package/dist/guards/index.js +1 -0
  331. package/dist/guards/index.js.map +1 -1
  332. package/dist/localization/default-messages.d.ts +43 -0
  333. package/dist/localization/default-messages.d.ts.map +1 -1
  334. package/dist/localization/default-messages.js +48 -5
  335. package/dist/localization/default-messages.js.map +1 -1
  336. package/dist/mcp/connect-route.d.ts.map +1 -1
  337. package/dist/mcp/connect-route.js +34 -48
  338. package/dist/mcp/connect-route.js.map +1 -1
  339. package/dist/observability/routes.d.ts +5 -5
  340. package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
  341. package/dist/provider-api/actions/provider-api.d.ts +7 -7
  342. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  343. package/dist/provider-api/index.js +1 -1
  344. package/dist/provider-api/index.js.map +1 -1
  345. package/dist/realtime-protocol.d.ts +40 -0
  346. package/dist/realtime-protocol.d.ts.map +1 -0
  347. package/dist/realtime-protocol.js +69 -0
  348. package/dist/realtime-protocol.js.map +1 -0
  349. package/dist/resources/handlers.d.ts +1 -1
  350. package/dist/secrets/routes.d.ts +3 -3
  351. package/dist/server/collab-plugin.d.ts +34 -3
  352. package/dist/server/collab-plugin.d.ts.map +1 -1
  353. package/dist/server/collab-plugin.js +65 -12
  354. package/dist/server/collab-plugin.js.map +1 -1
  355. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  356. package/dist/server/core-routes-plugin.js +3 -0
  357. package/dist/server/core-routes-plugin.js.map +1 -1
  358. package/dist/server/index.d.ts +1 -1
  359. package/dist/server/index.d.ts.map +1 -1
  360. package/dist/server/index.js.map +1 -1
  361. package/dist/server/poll-events.d.ts +7 -1
  362. package/dist/server/poll-events.d.ts.map +1 -1
  363. package/dist/server/poll-events.js +24 -7
  364. package/dist/server/poll-events.js.map +1 -1
  365. package/dist/server/poll.d.ts +223 -42
  366. package/dist/server/poll.d.ts.map +1 -1
  367. package/dist/server/poll.js +849 -737
  368. package/dist/server/poll.js.map +1 -1
  369. package/dist/server/realtime-token.d.ts +34 -0
  370. package/dist/server/realtime-token.d.ts.map +1 -0
  371. package/dist/server/realtime-token.js +85 -0
  372. package/dist/server/realtime-token.js.map +1 -0
  373. package/dist/server/sentry-config.d.ts +12 -0
  374. package/dist/server/sentry-config.d.ts.map +1 -1
  375. package/dist/server/sentry-config.js +34 -0
  376. package/dist/server/sentry-config.js.map +1 -1
  377. package/dist/server/short-lived-token.d.ts +46 -0
  378. package/dist/server/short-lived-token.d.ts.map +1 -1
  379. package/dist/server/short-lived-token.js +104 -0
  380. package/dist/server/short-lived-token.js.map +1 -1
  381. package/dist/server/sse.d.ts +1 -1
  382. package/dist/server/sse.d.ts.map +1 -1
  383. package/dist/server/sse.js +4 -0
  384. package/dist/server/sse.js.map +1 -1
  385. package/dist/server/ssr-handler.d.ts.map +1 -1
  386. package/dist/server/ssr-handler.js +5 -3
  387. package/dist/server/ssr-handler.js.map +1 -1
  388. package/dist/server/transcribe-voice.d.ts +1 -1
  389. package/dist/styles/agent-native.css +40 -0
  390. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  391. package/dist/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  392. package/dist/templates/chat/app/components/layout/Layout.tsx +1 -0
  393. package/dist/templates/chat/app/components/layout/Sidebar.tsx +43 -67
  394. package/dist/templates/chat/app/hooks/use-navigation-state.ts +2 -7
  395. package/dist/templates/chat/app/routes/_index.tsx +8 -5
  396. package/dist/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  397. package/dist/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  398. package/dist/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  399. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  400. package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
  401. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  402. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  403. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  404. package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
  405. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  406. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
  407. package/docs/AGENTS.md +1 -1
  408. package/docs/content/agent-mentions.mdx +2 -2
  409. package/docs/content/{workspace.mdx → agent-resources.mdx} +1 -7
  410. package/docs/content/agent-teams.mdx +4 -4
  411. package/docs/content/dispatch.mdx +10 -10
  412. package/docs/content/drop-in-agent.mdx +4 -4
  413. package/docs/content/external-agents.mdx +1 -1
  414. package/docs/content/frames.mdx +1 -1
  415. package/docs/content/integrations.mdx +13 -2
  416. package/docs/content/key-concepts.mdx +2 -2
  417. package/docs/content/mcp-clients.mdx +7 -1
  418. package/docs/content/multi-app-workspace.mdx +3 -3
  419. package/docs/content/real-time-collaboration.mdx +33 -15
  420. package/docs/content/recurring-jobs.mdx +7 -7
  421. package/docs/content/skills-guide.mdx +4 -4
  422. package/docs/content/template-brain.mdx +1 -1
  423. package/docs/content/toolkit-collaboration.mdx +1 -1
  424. package/docs/content/using-your-agent.mdx +1 -1
  425. package/docs/content/what-is-agent-native.mdx +4 -4
  426. package/docs/content/workspace-management.mdx +4 -4
  427. package/package.json +6 -3
  428. package/src/agent/production-agent.ts +13 -3
  429. package/src/cli/doctor.ts +6 -1
  430. package/src/client/AgentPanel.tsx +79 -41
  431. package/src/client/AssistantChat.tsx +71 -25
  432. package/src/client/FeedbackButton.tsx +33 -7
  433. package/src/client/MultiTabAssistantChat.tsx +6 -8
  434. package/src/client/agent-chat-adapter.ts +11 -2
  435. package/src/client/agent-page/AgentTabFrame.tsx +22 -3
  436. package/src/client/agent-page/AgentTabsPage.tsx +34 -19
  437. package/src/client/analytics.ts +7 -0
  438. package/src/client/chat/message-components.tsx +43 -16
  439. package/src/client/chat/tool-call-display.tsx +30 -18
  440. package/src/client/chat/tool-render-registry.tsx +2 -0
  441. package/src/client/resources/McpConnectionSuggestion.tsx +19 -2
  442. package/src/client/resources/ResourceTree.tsx +7 -10
  443. package/src/client/resources/ResourcesPanel.tsx +33 -70
  444. package/src/client/resources/mcp-connection-resume.ts +107 -0
  445. package/src/client/resources/mcp-integration-catalog.ts +65 -12
  446. package/src/client/resources/mcp-integration-logos.ts +4 -0
  447. package/src/client/sse-event-processor.ts +50 -14
  448. package/src/client/use-db-sync.ts +370 -21
  449. package/src/collab/client.ts +26 -2
  450. package/src/connections/catalog.ts +7 -1
  451. package/src/db/ddl-guard.ts +49 -10
  452. package/src/deploy/build.ts +25 -2
  453. package/src/eject/remote-mcp-presets.ts +37 -5
  454. package/src/guards/explicit-collab-access.ts +229 -0
  455. package/src/guards/index.ts +1 -0
  456. package/src/localization/default-messages.ts +54 -5
  457. package/src/mcp/connect-route.ts +34 -51
  458. package/src/provider-api/index.ts +1 -1
  459. package/src/realtime-protocol.ts +92 -0
  460. package/src/server/collab-plugin.ts +137 -18
  461. package/src/server/core-routes-plugin.ts +7 -0
  462. package/src/server/index.ts +2 -0
  463. package/src/server/poll-events.ts +29 -8
  464. package/src/server/poll.ts +1123 -865
  465. package/src/server/realtime-token.ts +106 -0
  466. package/src/server/sentry-config.ts +40 -0
  467. package/src/server/short-lived-token.ts +156 -0
  468. package/src/server/sse.ts +15 -0
  469. package/src/server/ssr-handler.ts +9 -3
  470. package/src/styles/agent-native.css +40 -0
  471. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  472. package/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  473. package/src/templates/chat/app/components/layout/Layout.tsx +1 -0
  474. package/src/templates/chat/app/components/layout/Sidebar.tsx +43 -67
  475. package/src/templates/chat/app/hooks/use-navigation-state.ts +2 -7
  476. package/src/templates/chat/app/routes/_index.tsx +8 -5
  477. package/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  478. package/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  479. package/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  480. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  481. package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
  482. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  483. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  484. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  485. package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
  486. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  487. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
@@ -72,7 +72,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
72
72
  });
73
73
  ```
74
74
 
75
- `useDbSync` and every `subscribeSyncEvents` subscriber share one `EventSource` and one fallback poll loop per tab — this is how collaborative documents receive doc updates and cursor/awareness events.
75
+ `useDbSync` and every `subscribeSyncEvents` subscriber share one `EventSource` and one fallback poll loop per tab — this is how collaborative documents receive doc updates and cursor/awareness events. Hidden tabs keep that shared transport alive by default: SSE stays connected and active fallback polling relaxes to a 10-second floor (idle polling remains once per minute). Pass `pauseWhenHidden: true` only for a consumer that explicitly must stop all hidden-tab sync.
76
76
 
77
77
  ## Which sources to depend on
78
78
 
@@ -24,9 +24,10 @@ shared agent sidebar.
24
24
  - **Always show the mic alongside the send button.** Cursor replaces send
25
25
  with mic when the composer is empty; their users complain. We keep both
26
26
  visible — Lovable does the same.
27
- - **Ask before switching modes.** The mic opens a shadcn popover offering
28
- **Start voice mode** and **Keep dictating**; never silently replace the
29
- established dictation behavior.
27
+ - **Ask before switching modes.** The mic opens a compact shadcn popover with
28
+ **Real-time voice** as the primary action and **Dictate** as the secondary;
29
+ never silently replace the established dictation behavior. Users can choose
30
+ **Remember my preference** to skip the chooser on later clicks.
30
31
  - **Dictation is click-to-toggle, not push-to-talk.** More forgiving in a sidebar, avoids
31
32
  host-app hotkey clashes. Keyboard shortcut is `Cmd/Ctrl+Shift+M` and
32
33
  `Escape` cancels mid-recording.
@@ -100,6 +101,9 @@ action before requesting microphone permission.
100
101
  `application_state["realtime-voice-prefs"]`. Keep this separate from
101
102
  `voice-transcription-prefs`, which configures editable dictation rather than
102
103
  the speech-to-speech session.
104
+ - Store the optional remembered chooser selection at
105
+ `application_state["voice-input-preference"]`. Keep it separate from both
106
+ mode-specific preference objects.
103
107
  - Missing-key failures should open Settings focused on the user-scoped
104
108
  `OPENAI_API_KEY` field. Never send, log, or echo the key to the browser.
105
109
 
@@ -147,11 +151,11 @@ Default behavior:
147
151
 
148
152
  | File | Purpose |
149
153
  | --------------------------------------------------------------------- | --------------------------------------------------- |
150
- | `packages/core/src/client/composer/useVoiceDictation.ts` | Provider-routing hook (MediaRecorder / Web Speech) |
151
- | `packages/core/src/client/composer/VoiceButton.tsx` | Mic button + live amplitude + cancel overlay |
152
- | `packages/core/src/client/composer/RealtimeVoiceMode.tsx` | Opt-in popover + persistent speech orb |
153
- | `packages/core/src/client/composer/useRealtimeVoiceMode.tsx` | WebRTC lifecycle, provider events, and tool bridge |
154
- | `packages/core/src/client/composer/TiptapComposer.tsx` | Wires the hook, insertion, and keyboard shortcut |
154
+ | `packages/toolkit/src/composer/useVoiceDictation.ts` | Provider-routing hook (MediaRecorder / Web Speech) |
155
+ | `packages/toolkit/src/composer/VoiceButton.tsx` | Mic button + live amplitude + cancel overlay |
156
+ | `packages/toolkit/src/composer/RealtimeVoiceMode.tsx` | Opt-in popover + persistent speech orb |
157
+ | `packages/toolkit/src/composer/useRealtimeVoiceMode.tsx` | WebRTC lifecycle, provider events, and tool bridge |
158
+ | `packages/toolkit/src/composer/TiptapComposer.tsx` | Wires the hook, insertion, and keyboard shortcut |
155
159
  | `packages/core/src/client/settings/VoiceTranscriptionSection.tsx` | Live source + cleanup controls in sidebar settings |
156
160
  | `packages/core/src/client/transcription/BuilderTranscriptionCta.tsx` | CTA shown when Builder account isn't connected |
157
161
  | `packages/core/src/client/transcription/use-live-transcription.ts` | Web Speech live-transcription hook for recordings |
@@ -85,7 +85,10 @@ in the moment of agent use.
85
85
  approval, generative UI, progress, and screen-state exposure.
86
86
  - **Chat history kit**: presentational chat lists and recent-chat rails belong
87
87
  in Toolkit; Core keeps thread persistence, agent execution, transport, and
88
- page-to-sidebar handoff. Apps inject routing, labels, and domain actions.
88
+ page-to-sidebar handoff. Use Toolkit's `ChatHistoryRail` for the standard
89
+ five-item sidebar preview and a footer row with New chat followed by an
90
+ ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
91
+ actions.
89
92
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
90
93
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
91
94
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -72,7 +72,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
72
72
  });
73
73
  ```
74
74
 
75
- `useDbSync` and every `subscribeSyncEvents` subscriber share one `EventSource` and one fallback poll loop per tab — this is how collaborative documents receive doc updates and cursor/awareness events.
75
+ `useDbSync` and every `subscribeSyncEvents` subscriber share one `EventSource` and one fallback poll loop per tab — this is how collaborative documents receive doc updates and cursor/awareness events. Hidden tabs keep that shared transport alive by default: SSE stays connected and active fallback polling relaxes to a 10-second floor (idle polling remains once per minute). Pass `pauseWhenHidden: true` only for a consumer that explicitly must stop all hidden-tab sync.
76
76
 
77
77
  ## Which sources to depend on
78
78
 
@@ -228,11 +228,16 @@ membership id when its native update status reports `update-available`.
228
228
  `dashboard-report-subscriptions` actions. They send daily snapshots scoped to
229
229
  the exact user/org context that created the subscription with saved URL
230
230
  filters; do not hand-wire custom email routes around that action surface.
231
+ - Table panels can be exported with `export-dashboard-panel-to-google-sheet`.
232
+ The action re-runs the accessible panel query with the dashboard's current
233
+ filter variables, creates a new Sheet through the connected Google Drive
234
+ workspace connection, and returns its URL plus bounded export metadata.
231
235
  Report PNGs are Playwright captures of the real dashboard route in
232
236
  `reportScreenshot=1` mode, authenticated by a short-lived embed-session token
233
237
  and embedded inline in email as ordered CID images. Complete dashboards are
234
- captured sequentially in bounded panel windows; every window must match the
235
- panel ids snapshotted at the start, and a failed or mismatched window
238
+ captured sequentially in four-panel windows matching the browser's four-query
239
+ concurrency limit; every window must match the panel ids snapshotted at the
240
+ start, and a failed or mismatched window
236
241
  invalidates the entire image set so the scheduler can retry instead of
237
242
  sending a partial report. Capture is capped at 10 windows and 14 MiB of raw
238
243
  PNG data, and subscriptions are capped at five distinct recipients; use a
@@ -0,0 +1,144 @@
1
+ import { defineAction } from "@agent-native/core/action";
2
+ import { getCredentialContext } from "@agent-native/core/server/request-context";
3
+ import { z } from "zod";
4
+
5
+ import { interpolate } from "../app/pages/adhoc/sql-dashboard/interpolate";
6
+ import {
7
+ isDashboardPanelSource,
8
+ normalizeDashboardPanelQuery,
9
+ } from "../server/lib/dashboard-panel-query";
10
+ import { resolveAnalyticsPanelSource } from "../server/lib/dashboard-panel-source-resolver";
11
+ import { getDashboard } from "../server/lib/dashboards-store";
12
+ import { exportDashboardPanelToGoogleSheet } from "../server/lib/google-sheets-export";
13
+
14
+ type DashboardPanel = {
15
+ id?: unknown;
16
+ title?: unknown;
17
+ sql?: unknown;
18
+ source?: unknown;
19
+ chartType?: unknown;
20
+ };
21
+
22
+ const MAX_EXPORT_ROWS = 10_000;
23
+ const MAX_EXPORT_CELLS = 500_000;
24
+
25
+ function asPanels(config: Record<string, unknown>): DashboardPanel[] {
26
+ return Array.isArray(config.panels)
27
+ ? config.panels.filter(
28
+ (panel): panel is DashboardPanel =>
29
+ Boolean(panel) && typeof panel === "object" && !Array.isArray(panel),
30
+ )
31
+ : [];
32
+ }
33
+
34
+ function missingKeyMessage(result: unknown): string | null {
35
+ if (!result || typeof result !== "object" || Array.isArray(result)) {
36
+ return null;
37
+ }
38
+ const value = result as { error?: unknown; message?: unknown };
39
+ return value.error === "missing_api_key" && typeof value.message === "string"
40
+ ? value.message
41
+ : null;
42
+ }
43
+
44
+ export default defineAction({
45
+ description:
46
+ "Export one accessible Analytics SQL dashboard table panel's underlying query results to a newly created Google Sheet using the connected Google Drive account. Returns the Sheet URL, spreadsheet id, row count, and export metadata. Only chartType=table panels are supported.",
47
+ schema: z.object({
48
+ dashboardId: z.string().trim().min(1).describe("The SQL dashboard ID"),
49
+ panelId: z.string().trim().min(1).describe("The table panel ID"),
50
+ filters: z.record(z.string(), z.string()).optional().default({}),
51
+ }),
52
+ http: { method: "POST" },
53
+ needsApproval: true,
54
+ toolCallable: false,
55
+ run: async ({ dashboardId, panelId, filters }) => {
56
+ const context = getCredentialContext();
57
+ if (!context) {
58
+ throw new Error(
59
+ "No authenticated context for export-dashboard-panel-to-google-sheet.",
60
+ );
61
+ }
62
+
63
+ const dashboard = await getDashboard(dashboardId, {
64
+ email: context.userEmail,
65
+ orgId: context.orgId ?? null,
66
+ });
67
+ if (!dashboard || dashboard.kind !== "sql") {
68
+ throw Object.assign(new Error("Dashboard not found"), {
69
+ statusCode: 404,
70
+ });
71
+ }
72
+
73
+ const panel = asPanels(dashboard.config).find(
74
+ (candidate) => candidate.id === panelId,
75
+ );
76
+ if (!panel) {
77
+ throw Object.assign(new Error("Dashboard panel not found"), {
78
+ statusCode: 404,
79
+ });
80
+ }
81
+ if (panel.chartType !== "table") {
82
+ throw new Error("Only table dashboard panels can be exported.");
83
+ }
84
+ if (!isDashboardPanelSource(panel.source)) {
85
+ throw new Error("Dashboard panel has an unsupported data source.");
86
+ }
87
+ if (typeof panel.sql !== "string" && typeof panel.sql !== "object") {
88
+ throw new Error("Dashboard panel has no query to export.");
89
+ }
90
+
91
+ const rawQuery =
92
+ typeof panel.sql === "string"
93
+ ? interpolate(panel.sql, filters, { failClosedTimeVariables: true })
94
+ : panel.sql;
95
+ const query = normalizeDashboardPanelQuery(panel.source, rawQuery);
96
+ const result = await resolveAnalyticsPanelSource(
97
+ { source: panel.source, query },
98
+ context,
99
+ );
100
+ const missing = missingKeyMessage(result);
101
+ if (missing) throw new Error(missing);
102
+ if (
103
+ !result ||
104
+ typeof result !== "object" ||
105
+ Array.isArray(result) ||
106
+ !("rows" in result) ||
107
+ !Array.isArray(result.rows)
108
+ ) {
109
+ throw new Error("Dashboard panel query returned an invalid result.");
110
+ }
111
+ const queryResult = result;
112
+ const columnCount = Array.isArray(queryResult.schema)
113
+ ? queryResult.schema.length
114
+ : Object.keys(queryResult.rows[0] ?? {}).length;
115
+ if (queryResult.rows.length > MAX_EXPORT_ROWS) {
116
+ throw new Error(
117
+ `This panel returned more than ${MAX_EXPORT_ROWS.toLocaleString()} rows. Narrow the dashboard filters before exporting.`,
118
+ );
119
+ }
120
+ if (queryResult.rows.length * columnCount > MAX_EXPORT_CELLS) {
121
+ throw new Error(
122
+ "This panel result is too wide to export safely. Narrow the query or reduce its columns.",
123
+ );
124
+ }
125
+
126
+ return exportDashboardPanelToGoogleSheet({
127
+ dashboardId,
128
+ dashboardTitle:
129
+ typeof dashboard.title === "string" && dashboard.title.trim()
130
+ ? dashboard.title
131
+ : "Analytics dashboard",
132
+ panelId,
133
+ panelTitle:
134
+ typeof panel.title === "string" && panel.title.trim()
135
+ ? panel.title
136
+ : panelId,
137
+ source: panel.source,
138
+ rows: queryResult.rows,
139
+ schema: Array.isArray(queryResult.schema) ? queryResult.schema : [],
140
+ truncated: queryResult.truncated,
141
+ bytesProcessed: queryResult.bytesProcessed,
142
+ });
143
+ },
144
+ });
@@ -2,12 +2,11 @@ import {
2
2
  AgentSidebar,
3
3
  GuidedQuestionFlow,
4
4
  focusAgentChat,
5
- markAgentChatHomeHandoff,
6
5
  navigateWithAgentChatViewTransition,
7
6
  useAgentChatHomeHandoff,
7
+ useAgentChatHomeHandoffLinks,
8
8
  useGuidedQuestionFlow,
9
9
  } from "@agent-native/core/client/agent-chat";
10
- import { appBasePath } from "@agent-native/core/client/api-path";
11
10
  import { useT } from "@agent-native/core/client/i18n";
12
11
  import { InvitationBanner } from "@agent-native/core/client/org";
13
12
  import { CreativeContextComposerChip } from "@agent-native/creative-context/client";
@@ -17,7 +16,6 @@ import { useLocation, useNavigate } from "react-router";
17
16
  import { useNavigationState } from "@/hooks/use-navigation-state";
18
17
  import {
19
18
  ANALYTICS_CHAT_STORAGE_KEY,
20
- hasRecentAnalyticsChat,
21
19
  markAnalyticsChatActivity,
22
20
  } from "@/lib/chat-handoff";
23
21
  import { TAB_ID } from "@/lib/tab-id";
@@ -37,59 +35,6 @@ interface LayoutProps {
37
35
 
38
36
  const BARE_ROUTES = new Set(["/chart"]);
39
37
 
40
- function stripBasePath(path: string): string {
41
- const basePath = appBasePath();
42
- if (!basePath) return path;
43
- if (path === basePath) return "/";
44
- if (path.startsWith(`${basePath}/`)) return path.slice(basePath.length);
45
- if (path.startsWith(`${basePath}?`) || path.startsWith(`${basePath}#`)) {
46
- return `/${path.slice(basePath.length)}`;
47
- }
48
- return path;
49
- }
50
-
51
- function pathnameFromLocalPath(path: string): string {
52
- return path.split(/[?#]/, 1)[0] || "/";
53
- }
54
-
55
- function isFrameworkOrApiPath(pathname: string): boolean {
56
- return (
57
- pathname === "/_agent-native" ||
58
- pathname.startsWith("/_agent-native/") ||
59
- pathname === "/api" ||
60
- pathname.startsWith("/api/")
61
- );
62
- }
63
-
64
- function isStaticAssetPath(pathname: string): boolean {
65
- const lastSegment = pathname.split("/").pop() ?? "";
66
- return /\.[A-Za-z0-9]{1,12}$/.test(lastSegment);
67
- }
68
-
69
- function localPathFromAnchor(anchor: HTMLAnchorElement): string | null {
70
- if (!anchor.href) return null;
71
- try {
72
- const url = new URL(anchor.href);
73
- if (url.origin !== window.location.origin) return null;
74
- return stripBasePath(`${url.pathname}${url.search}${url.hash}`);
75
- } catch {
76
- return null;
77
- }
78
- }
79
-
80
- function shouldHandleAnchorClick(
81
- event: MouseEvent,
82
- anchor: HTMLAnchorElement,
83
- ): boolean {
84
- if (event.defaultPrevented || event.button !== 0) return false;
85
- if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
86
- return false;
87
- }
88
- if (anchor.target && anchor.target !== "_self") return false;
89
- if (anchor.hasAttribute("download")) return false;
90
- return true;
91
- }
92
-
93
38
  export function Layout({ children }: LayoutProps) {
94
39
  useNavigationState();
95
40
  const location = useLocation();
@@ -163,6 +108,12 @@ export function Layout({ children }: LayoutProps) {
163
108
  activePath: location.pathname,
164
109
  enabled: !isAskRoute && !reportScreenshot,
165
110
  });
111
+ useAgentChatHomeHandoffLinks({
112
+ storageKey: ANALYTICS_CHAT_STORAGE_KEY,
113
+ chatPath: "/ask",
114
+ enabled: !reportScreenshot,
115
+ requireActiveHandoff: false,
116
+ });
166
117
  useEffect(() => {
167
118
  function handleChatRunning(event: Event) {
168
119
  const detail = (event as CustomEvent).detail;
@@ -176,38 +127,6 @@ export function Layout({ children }: LayoutProps) {
176
127
  window.removeEventListener("agentNative.chatRunning", handleChatRunning);
177
128
  }, []);
178
129
 
179
- useEffect(() => {
180
- if (!isAskRoute) return;
181
-
182
- function handleClick(event: MouseEvent) {
183
- const target = event.target;
184
- if (!(target instanceof Element)) return;
185
- const anchor = target.closest("a[href]");
186
- if (!(anchor instanceof HTMLAnchorElement)) return;
187
- if (!shouldHandleAnchorClick(event, anchor)) return;
188
- if (anchor.closest(".agent-panel-root")) return;
189
-
190
- const path = localPathFromAnchor(anchor);
191
- const pathname = path ? pathnameFromLocalPath(path) : "";
192
- if (
193
- !path ||
194
- pathname === "/ask" ||
195
- isFrameworkOrApiPath(pathname) ||
196
- isStaticAssetPath(pathname) ||
197
- !hasRecentAnalyticsChat()
198
- ) {
199
- return;
200
- }
201
-
202
- event.preventDefault();
203
- markAgentChatHomeHandoff(ANALYTICS_CHAT_STORAGE_KEY);
204
- navigateWithAgentChatViewTransition(navigate, path);
205
- }
206
-
207
- document.addEventListener("click", handleClick, true);
208
- return () => document.removeEventListener("click", handleClick, true);
209
- }, [isAskRoute, navigate]);
210
-
211
130
  function openAskAgentFullscreen() {
212
131
  focusAgentChat();
213
132
  navigateWithAgentChatViewTransition(navigate, "/ask");
@@ -98,7 +98,7 @@ import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
98
98
  import { OrgSwitcher } from "@agent-native/core/client/org";
99
99
  import { FeedbackButton } from "@agent-native/core/client/ui";
100
100
  import {
101
- ChatHistoryList,
101
+ ChatHistoryRail,
102
102
  type ChatHistoryItem,
103
103
  } from "@agent-native/toolkit/chat-history";
104
104
 
@@ -1334,7 +1334,7 @@ function AnalyticsChatsSection({ isAskRoute }: { isAskRoute: boolean }) {
1334
1334
  threads
1335
1335
  .filter((thread) => thread.messageCount > 0 && !thread.archivedAt)
1336
1336
  .sort(compareThreads)
1337
- .slice(0, SIDEBAR_PREVIEW_COUNT),
1337
+ .slice(0, 15),
1338
1338
  [threads],
1339
1339
  );
1340
1340
  const chatItems = useMemo<ChatHistoryItem[]>(
@@ -1433,40 +1433,37 @@ function AnalyticsChatsSection({ isAskRoute }: { isAskRoute: boolean }) {
1433
1433
  />
1434
1434
  </div>
1435
1435
  ))}
1436
- {visibleThreads.length > 0 && (
1437
- <ChatHistoryList
1438
- items={chatItems}
1439
- activeId={displayedActiveThreadId}
1440
- onSelect={(threadId) => openThread(threadId)}
1441
- renameMaxLength={160}
1442
- onTogglePin={(threadId) => {
1443
- const thread = visibleThreads.find((item) => item.id === threadId);
1444
- if (thread) void pinThread(threadId, !thread.pinnedAt);
1445
- }}
1446
- onRename={handleRenameThread}
1447
- onDelete={(threadId) => void handleArchiveThread(threadId)}
1448
- labels={{
1449
- options: (item) =>
1450
- t("chat.optionsFor", { title: item.titleText ?? "" }),
1451
- renameInput: (item) =>
1452
- t("chat.renameThread", { title: item.titleText ?? "" }),
1453
- rename: t("chat.renameChat"),
1454
- pin: t("chat.pinChat"),
1455
- unpin: t("chat.unpinChat"),
1456
- delete: t("chat.archiveChat"),
1457
- }}
1458
- variant="rail"
1459
- className="min-w-0"
1460
- />
1461
- )}
1462
- <button
1463
- type="button"
1464
- onClick={() => void handleNewChat()}
1465
- className="flex w-full cursor-pointer items-center gap-2 rounded-lg px-3 py-1.5 text-xs text-muted-foreground/60 hover:bg-sidebar-accent/50 hover:text-primary"
1466
- >
1467
- <IconPlus className="h-3 w-3" />
1468
- {t("chat.newChat")}
1469
- </button>
1436
+ <ChatHistoryRail
1437
+ items={chatItems}
1438
+ activeId={displayedActiveThreadId}
1439
+ onSelect={(threadId) => openThread(threadId)}
1440
+ onNewChat={() => void handleNewChat()}
1441
+ railLabels={{
1442
+ newChat: t("chat.newChat"),
1443
+ showMore: t("sidebar.showMore", {
1444
+ count: Math.max(0, visibleThreads.length - SIDEBAR_PREVIEW_COUNT),
1445
+ }),
1446
+ showLess: t("sidebar.showLess"),
1447
+ }}
1448
+ renameMaxLength={160}
1449
+ onTogglePin={(threadId) => {
1450
+ const thread = visibleThreads.find((item) => item.id === threadId);
1451
+ if (thread) void pinThread(threadId, !thread.pinnedAt);
1452
+ }}
1453
+ onRename={handleRenameThread}
1454
+ onDelete={(threadId) => void handleArchiveThread(threadId)}
1455
+ labels={{
1456
+ options: (item) =>
1457
+ t("chat.optionsFor", { title: item.titleText ?? "" }),
1458
+ renameInput: (item) =>
1459
+ t("chat.renameThread", { title: item.titleText ?? "" }),
1460
+ rename: t("chat.renameChat"),
1461
+ pin: t("chat.pinChat"),
1462
+ unpin: t("chat.unpinChat"),
1463
+ delete: t("chat.archiveChat"),
1464
+ }}
1465
+ className="min-w-0"
1466
+ />
1470
1467
  </div>
1471
1468
  );
1472
1469
  }
@@ -2936,7 +2933,7 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
2936
2933
  <div className="space-y-2 pt-2">
2937
2934
  <OrgSwitcher />
2938
2935
  <TooltipProvider delayDuration={200}>
2939
- <div className="flex items-center gap-1">
2936
+ <div className="flex items-center justify-end gap-1">
2940
2937
  <DevDatabaseLink />
2941
2938
  <FeedbackButton className="min-w-0 flex-1" />
2942
2939
  <div className="flex shrink-0 items-center gap-0.5">
@@ -149,10 +149,6 @@
149
149
  background-color: hsl(var(--background)) !important;
150
150
  }
151
151
 
152
- .analytics-chat-panel .agent-thread-content {
153
- padding-top: 4.5rem;
154
- }
155
-
156
152
  .analytics-chat-panel
157
153
  [data-agent-page-chat-scrolled]
158
154
  [data-agent-page-chat-fade] {
@@ -2,10 +2,7 @@ import { markAgentChatHomeHandoff } from "@agent-native/core/client/agent-chat";
2
2
  import { useAgentRouteState } from "@agent-native/core/client/navigation";
3
3
  import { useLocation } from "react-router";
4
4
 
5
- import {
6
- ANALYTICS_CHAT_STORAGE_KEY,
7
- hasRecentAnalyticsChat,
8
- } from "@/lib/chat-handoff";
5
+ import { ANALYTICS_CHAT_STORAGE_KEY } from "@/lib/chat-handoff";
9
6
  import { rememberLastOpened } from "@/lib/last-opened";
10
7
  import { TAB_ID } from "@/lib/tab-id";
11
8
 
@@ -161,9 +158,7 @@ export function useNavigationState() {
161
158
  },
162
159
  onNavigate: (_command, path) => {
163
160
  if (location.pathname === "/ask" && pathnameFromPath(path) !== "/ask") {
164
- if (hasRecentAnalyticsChat()) {
165
- markAgentChatHomeHandoff(ANALYTICS_CHAT_STORAGE_KEY);
166
- }
161
+ markAgentChatHomeHandoff(ANALYTICS_CHAT_STORAGE_KEY);
167
162
  }
168
163
  },
169
164
  });