@agent-native/core 0.115.4 → 0.116.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 (408) hide show
  1. package/agent-native.eject.json +1 -0
  2. package/corpus/README.md +3 -3
  3. package/corpus/core/CHANGELOG.md +28 -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 +1 -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/chat/message-components.tsx +43 -16
  36. package/corpus/core/src/client/chat/tool-call-display.tsx +30 -18
  37. package/corpus/core/src/client/chat/tool-render-registry.tsx +2 -0
  38. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +19 -2
  39. package/corpus/core/src/client/resources/ResourceTree.tsx +7 -10
  40. package/corpus/core/src/client/resources/ResourcesPanel.tsx +33 -70
  41. package/corpus/core/src/client/resources/mcp-connection-resume.ts +107 -0
  42. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +65 -12
  43. package/corpus/core/src/client/resources/mcp-integration-logos.ts +4 -0
  44. package/corpus/core/src/client/sse-event-processor.ts +50 -14
  45. package/corpus/core/src/client/use-db-sync.ts +16 -6
  46. package/corpus/core/src/connections/catalog.ts +7 -1
  47. package/corpus/core/src/eject/remote-mcp-presets.ts +37 -5
  48. package/corpus/core/src/guards/explicit-collab-access.ts +229 -0
  49. package/corpus/core/src/guards/index.ts +1 -0
  50. package/corpus/core/src/localization/default-messages.ts +54 -5
  51. package/corpus/core/src/mcp/connect-route.ts +34 -51
  52. package/corpus/core/src/provider-api/index.ts +1 -1
  53. package/corpus/core/src/server/collab-plugin.ts +137 -18
  54. package/corpus/core/src/server/index.ts +2 -0
  55. package/corpus/core/src/styles/agent-native.css +40 -0
  56. package/corpus/core/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  57. package/corpus/core/src/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
  58. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  59. package/corpus/core/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  60. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  61. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
  62. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  63. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
  64. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  65. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
  66. package/corpus/templates/analytics/AGENTS.md +7 -2
  67. package/corpus/templates/analytics/actions/export-dashboard-panel-to-google-sheet.ts +144 -0
  68. package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -88
  69. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +34 -37
  70. package/corpus/templates/analytics/app/global.css +0 -4
  71. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +2 -7
  72. package/corpus/templates/analytics/app/i18n-data.ts +107 -0
  73. package/corpus/templates/analytics/app/lib/data-source-status.ts +9 -0
  74. package/corpus/templates/analytics/app/lib/sql-query.ts +1 -2
  75. package/corpus/templates/analytics/app/pages/Ask.tsx +2 -7
  76. package/corpus/templates/analytics/app/pages/DataSources.tsx +48 -0
  77. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +59 -0
  78. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -0
  79. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-panel-window.ts +3 -1
  80. package/corpus/templates/analytics/changelog/2026-07-22-clear-background-chat-progress.md +6 -0
  81. package/corpus/templates/analytics/changelog/2026-07-22-daily-dashboard-email-query-batches.md +6 -0
  82. package/corpus/templates/analytics/changelog/2026-07-22-export-table-panels-directly-to-google-sheets.md +6 -0
  83. package/corpus/templates/analytics/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  84. package/corpus/templates/analytics/changelog/2026-07-22-recent-chats-can-expand-in-the-sidebar.md +6 -0
  85. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +8 -8
  86. package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +31 -0
  87. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +3 -5
  88. package/corpus/templates/analytics/server/lib/dashboard-report.ts +12 -0
  89. package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +3 -5
  90. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +150 -21
  91. package/corpus/templates/analytics/server/lib/google-sheets-export.ts +188 -0
  92. package/corpus/templates/analytics/server/lib/provider-api.ts +7 -2
  93. package/corpus/templates/analytics/server/plugins/collab.ts +6 -3
  94. package/corpus/templates/analytics/shared/sql-query-limits.ts +1 -0
  95. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  96. package/corpus/templates/assets/.agents/skills/real-time-collab/SKILL.md +35 -13
  97. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
  98. package/corpus/templates/assets/app/components/layout/Layout.tsx +1 -1
  99. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +54 -62
  100. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -6
  101. package/corpus/templates/assets/app/routes/_index.tsx +8 -5
  102. package/corpus/templates/assets/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  103. package/corpus/templates/assets/changelog/2026-07-22-recent-chats-expand-from-a-compact-list.md +6 -0
  104. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  105. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
  106. package/corpus/templates/brain/actions/rotate-source-ingest-token.ts +77 -0
  107. package/corpus/templates/brain/app/components/layout/Layout.tsx +5 -1
  108. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +38 -51
  109. package/corpus/templates/brain/app/hooks/use-navigation-state.ts +2 -9
  110. package/corpus/templates/brain/app/i18n-data.ts +120 -0
  111. package/corpus/templates/brain/app/routes/sources.tsx +156 -5
  112. package/corpus/templates/brain/changelog/2026-07-22-chat-runs-always-end-with-an-answer.md +6 -0
  113. package/corpus/templates/brain/changelog/2026-07-22-clear-background-chat-progress.md +6 -0
  114. package/corpus/templates/brain/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  115. package/corpus/templates/brain/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  116. package/corpus/templates/brain/changelog/2026-07-22-long-chat-titles-stay-inside-the-sidebar.md +6 -0
  117. package/corpus/templates/brain/changelog/2026-07-22-new-clips-and-webhook-sources-now-show-their-secure-connecti.md +6 -0
  118. package/corpus/templates/brain/jobs/emit-netlify-brain-queue-cron.ts +125 -0
  119. package/corpus/templates/brain/netlify.toml +5 -1
  120. package/corpus/templates/brain/scripts/configure-prod-clips-source.ts +50 -0
  121. package/corpus/templates/brain/server/lib/capture-sanitization.ts +64 -6
  122. package/corpus/templates/brain/server/plugins/agent-chat.ts +4 -0
  123. package/corpus/templates/brain/server/plugins/brain-jobs.ts +1 -0
  124. package/corpus/templates/brain/server/routes/api/brain/queue/run.post.ts +55 -0
  125. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  126. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
  127. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  128. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  129. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -0
  130. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +43 -67
  131. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +2 -7
  132. package/corpus/templates/chat/app/routes/_index.tsx +8 -5
  133. package/corpus/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  134. package/corpus/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  135. package/corpus/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  136. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  137. package/corpus/templates/clips/AGENTS.md +9 -1
  138. package/corpus/templates/clips/actions/export-to-brain.ts +82 -6
  139. package/corpus/templates/clips/actions/request-transcript.ts +25 -14
  140. package/corpus/templates/clips/changelog/2026-07-22-clips-transcripts-now-retry-brain-export.md +5 -0
  141. package/corpus/templates/clips/changelog/2026-07-22-german-umlauts-and-other-non-ascii-characters-now-paste-corr.md +6 -0
  142. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +26 -3
  143. package/corpus/templates/clips/jobs/emit-netlify-brain-export-cron.ts +118 -0
  144. package/corpus/templates/clips/netlify.toml +4 -1
  145. package/corpus/templates/clips/scripts/configure-prod-brain-export.ts +92 -0
  146. package/corpus/templates/clips/server/jobs/brain-export.ts +182 -0
  147. package/corpus/templates/clips/server/lib/brain-export-state.ts +42 -0
  148. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +5 -1
  149. package/corpus/templates/clips/server/plugins/calendar-jobs.ts +2 -0
  150. package/corpus/templates/clips/server/register-secrets.ts +42 -0
  151. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +10 -1
  152. package/corpus/templates/clips/server/routes/api/clips/brain-export/run.post.ts +45 -0
  153. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  154. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
  155. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +1 -1
  156. package/corpus/templates/content/server/plugins/collab.ts +1 -1
  157. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  158. package/corpus/templates/crm/actions/_crm-data-program-actions.ts +15 -0
  159. package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +2 -0
  160. package/corpus/templates/crm/actions/run.ts +2 -6
  161. package/corpus/templates/crm/actions/update-crm-record.ts +4 -2
  162. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +6 -0
  163. package/corpus/templates/crm/changelog/2026-07-22-crm-field-validation-now-explains-which-fields-cannot-be-edi.md +6 -0
  164. package/corpus/templates/crm/changelog/2026-07-22-fixed-hubspot-contact-syncs-missing-records-updated-after-th.md +6 -0
  165. package/corpus/templates/crm/changelog/2026-07-22-fixed-pipeline-dashboard-panels-so-their-opportunity-data-lo.md +6 -0
  166. package/corpus/templates/crm/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  167. package/corpus/templates/crm/server/crm/hubspot-adapter.ts +4 -1
  168. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  169. package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
  170. package/corpus/templates/design/server/plugins/collab.ts +11 -8
  171. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  172. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  173. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
  174. package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -0
  175. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +1 -1
  176. package/corpus/templates/forms/app/hooks/use-navigation-state.ts +2 -9
  177. package/corpus/templates/forms/app/root.tsx +1 -6
  178. package/corpus/templates/forms/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  179. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  180. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  181. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
  182. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
  183. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  184. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
  185. package/corpus/templates/plan/app/components/layout/Layout.tsx +5 -1
  186. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +57 -72
  187. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +2 -9
  188. package/corpus/templates/plan/app/lib/create-plan-routing.ts +2 -2
  189. package/corpus/templates/plan/app/pages/PlanChatPage.tsx +0 -1
  190. package/corpus/templates/plan/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  191. package/corpus/templates/plan/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  192. package/corpus/templates/plan/changelog/2026-07-22-recent-chats-and-sidebar-controls-are-more-compact.md +6 -0
  193. package/corpus/templates/plan/server/plugins/collab.ts +5 -2
  194. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  195. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +1 -1
  196. package/corpus/templates/slides/server/plugins/collab.ts +11 -8
  197. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  198. package/corpus/templates/tasks/.agents/skills/real-time-sync/SKILL.md +1 -1
  199. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +5 -22
  200. package/corpus/templates/tasks/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  201. package/corpus/toolkit/CHANGELOG.md +7 -0
  202. package/corpus/toolkit/README.md +12 -3
  203. package/corpus/toolkit/package.json +1 -1
  204. package/corpus/toolkit/src/chat-history/ChatHistoryRail.tsx +89 -0
  205. package/corpus/toolkit/src/chat-history/index.ts +5 -0
  206. package/corpus/toolkit/src/chat-history.css +59 -0
  207. package/corpus/toolkit/src/composer/RealtimeVoiceMode.tsx +106 -36
  208. package/corpus/toolkit/src/composer/VoiceButton.tsx +49 -0
  209. package/corpus/toolkit/src/composer/realtime-voice-audio-level.ts +2 -1
  210. package/corpus/toolkit/src/composer/useRealtimeVoiceMode.tsx +5 -3
  211. package/corpus/toolkit/src/styles.css +35 -0
  212. package/dist/agent/production-agent.d.ts.map +1 -1
  213. package/dist/agent/production-agent.js +13 -3
  214. package/dist/agent/production-agent.js.map +1 -1
  215. package/dist/cli/doctor.d.ts +1 -1
  216. package/dist/cli/doctor.d.ts.map +1 -1
  217. package/dist/cli/doctor.js +5 -2
  218. package/dist/cli/doctor.js.map +1 -1
  219. package/dist/client/AgentPanel.d.ts +1 -0
  220. package/dist/client/AgentPanel.d.ts.map +1 -1
  221. package/dist/client/AgentPanel.js +38 -18
  222. package/dist/client/AgentPanel.js.map +1 -1
  223. package/dist/client/AssistantChat.d.ts.map +1 -1
  224. package/dist/client/AssistantChat.js +55 -20
  225. package/dist/client/AssistantChat.js.map +1 -1
  226. package/dist/client/FeedbackButton.d.ts +4 -2
  227. package/dist/client/FeedbackButton.d.ts.map +1 -1
  228. package/dist/client/FeedbackButton.js +18 -2
  229. package/dist/client/FeedbackButton.js.map +1 -1
  230. package/dist/client/MultiTabAssistantChat.d.ts +1 -1
  231. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  232. package/dist/client/MultiTabAssistantChat.js +2 -3
  233. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  234. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  235. package/dist/client/agent-chat-adapter.js +11 -3
  236. package/dist/client/agent-chat-adapter.js.map +1 -1
  237. package/dist/client/agent-page/AgentTabFrame.d.ts +3 -1
  238. package/dist/client/agent-page/AgentTabFrame.d.ts.map +1 -1
  239. package/dist/client/agent-page/AgentTabFrame.js +3 -2
  240. package/dist/client/agent-page/AgentTabFrame.js.map +1 -1
  241. package/dist/client/agent-page/AgentTabsPage.d.ts +2 -0
  242. package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
  243. package/dist/client/agent-page/AgentTabsPage.js +26 -15
  244. package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
  245. package/dist/client/chat/message-components.d.ts +6 -1
  246. package/dist/client/chat/message-components.d.ts.map +1 -1
  247. package/dist/client/chat/message-components.js +17 -11
  248. package/dist/client/chat/message-components.js.map +1 -1
  249. package/dist/client/chat/tool-call-display.d.ts +11 -1
  250. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  251. package/dist/client/chat/tool-call-display.js +16 -17
  252. package/dist/client/chat/tool-call-display.js.map +1 -1
  253. package/dist/client/chat/tool-render-registry.d.ts +2 -0
  254. package/dist/client/chat/tool-render-registry.d.ts.map +1 -1
  255. package/dist/client/chat/tool-render-registry.js.map +1 -1
  256. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
  257. package/dist/client/resources/McpConnectionSuggestion.js +15 -1
  258. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
  259. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  260. package/dist/client/resources/ResourceTree.js +3 -3
  261. package/dist/client/resources/ResourceTree.js.map +1 -1
  262. package/dist/client/resources/ResourcesPanel.d.ts +1 -0
  263. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  264. package/dist/client/resources/ResourcesPanel.js +34 -20
  265. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  266. package/dist/client/resources/mcp-connection-resume.d.ts +11 -0
  267. package/dist/client/resources/mcp-connection-resume.d.ts.map +1 -0
  268. package/dist/client/resources/mcp-connection-resume.js +95 -0
  269. package/dist/client/resources/mcp-connection-resume.js.map +1 -0
  270. package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
  271. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  272. package/dist/client/resources/mcp-integration-catalog.js +63 -8
  273. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  274. package/dist/client/resources/mcp-integration-logos.d.ts.map +1 -1
  275. package/dist/client/resources/mcp-integration-logos.js +4 -0
  276. package/dist/client/resources/mcp-integration-logos.js.map +1 -1
  277. package/dist/client/sse-event-processor.d.ts +5 -0
  278. package/dist/client/sse-event-processor.d.ts.map +1 -1
  279. package/dist/client/sse-event-processor.js +39 -13
  280. package/dist/client/sse-event-processor.js.map +1 -1
  281. package/dist/client/use-db-sync.d.ts +3 -2
  282. package/dist/client/use-db-sync.d.ts.map +1 -1
  283. package/dist/client/use-db-sync.js +17 -6
  284. package/dist/client/use-db-sync.js.map +1 -1
  285. package/dist/collab/routes.d.ts +1 -1
  286. package/dist/connections/catalog.d.ts +1 -1
  287. package/dist/connections/catalog.d.ts.map +1 -1
  288. package/dist/connections/catalog.js +7 -1
  289. package/dist/connections/catalog.js.map +1 -1
  290. package/dist/eject/remote-mcp-presets.d.ts.map +1 -1
  291. package/dist/eject/remote-mcp-presets.js +33 -3
  292. package/dist/eject/remote-mcp-presets.js.map +1 -1
  293. package/dist/guards/explicit-collab-access.d.ts +8 -0
  294. package/dist/guards/explicit-collab-access.d.ts.map +1 -0
  295. package/dist/guards/explicit-collab-access.js +214 -0
  296. package/dist/guards/explicit-collab-access.js.map +1 -0
  297. package/dist/guards/index.d.ts +1 -0
  298. package/dist/guards/index.d.ts.map +1 -1
  299. package/dist/guards/index.js +1 -0
  300. package/dist/guards/index.js.map +1 -1
  301. package/dist/localization/default-messages.d.ts +43 -0
  302. package/dist/localization/default-messages.d.ts.map +1 -1
  303. package/dist/localization/default-messages.js +48 -5
  304. package/dist/localization/default-messages.js.map +1 -1
  305. package/dist/mcp/connect-route.d.ts.map +1 -1
  306. package/dist/mcp/connect-route.js +34 -48
  307. package/dist/mcp/connect-route.js.map +1 -1
  308. package/dist/notifications/routes.d.ts +3 -3
  309. package/dist/observability/routes.d.ts +1 -1
  310. package/dist/progress/routes.d.ts +1 -1
  311. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  312. package/dist/provider-api/actions/provider-api.d.ts +7 -7
  313. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  314. package/dist/provider-api/index.js +1 -1
  315. package/dist/provider-api/index.js.map +1 -1
  316. package/dist/server/collab-plugin.d.ts +34 -3
  317. package/dist/server/collab-plugin.d.ts.map +1 -1
  318. package/dist/server/collab-plugin.js +65 -12
  319. package/dist/server/collab-plugin.js.map +1 -1
  320. package/dist/server/index.d.ts +1 -1
  321. package/dist/server/index.d.ts.map +1 -1
  322. package/dist/server/index.js.map +1 -1
  323. package/dist/styles/agent-native.css +40 -0
  324. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  325. package/dist/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  326. package/dist/templates/chat/app/components/layout/Layout.tsx +1 -0
  327. package/dist/templates/chat/app/components/layout/Sidebar.tsx +43 -67
  328. package/dist/templates/chat/app/hooks/use-navigation-state.ts +2 -7
  329. package/dist/templates/chat/app/routes/_index.tsx +8 -5
  330. package/dist/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  331. package/dist/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  332. package/dist/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  333. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  334. package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
  335. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  336. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  337. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  338. package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
  339. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  340. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
  341. package/docs/AGENTS.md +1 -1
  342. package/docs/content/agent-mentions.mdx +2 -2
  343. package/docs/content/{workspace.mdx → agent-resources.mdx} +1 -7
  344. package/docs/content/agent-teams.mdx +4 -4
  345. package/docs/content/dispatch.mdx +10 -10
  346. package/docs/content/drop-in-agent.mdx +4 -4
  347. package/docs/content/external-agents.mdx +1 -1
  348. package/docs/content/frames.mdx +1 -1
  349. package/docs/content/integrations.mdx +13 -2
  350. package/docs/content/key-concepts.mdx +2 -2
  351. package/docs/content/mcp-clients.mdx +7 -1
  352. package/docs/content/multi-app-workspace.mdx +3 -3
  353. package/docs/content/real-time-collaboration.mdx +33 -15
  354. package/docs/content/recurring-jobs.mdx +7 -7
  355. package/docs/content/skills-guide.mdx +4 -4
  356. package/docs/content/template-brain.mdx +1 -1
  357. package/docs/content/toolkit-collaboration.mdx +1 -1
  358. package/docs/content/using-your-agent.mdx +1 -1
  359. package/docs/content/what-is-agent-native.mdx +4 -4
  360. package/docs/content/workspace-management.mdx +4 -4
  361. package/package.json +3 -3
  362. package/src/agent/production-agent.ts +13 -3
  363. package/src/cli/doctor.ts +6 -1
  364. package/src/client/AgentPanel.tsx +79 -41
  365. package/src/client/AssistantChat.tsx +71 -25
  366. package/src/client/FeedbackButton.tsx +33 -7
  367. package/src/client/MultiTabAssistantChat.tsx +6 -8
  368. package/src/client/agent-chat-adapter.ts +11 -2
  369. package/src/client/agent-page/AgentTabFrame.tsx +22 -3
  370. package/src/client/agent-page/AgentTabsPage.tsx +34 -19
  371. package/src/client/chat/message-components.tsx +43 -16
  372. package/src/client/chat/tool-call-display.tsx +30 -18
  373. package/src/client/chat/tool-render-registry.tsx +2 -0
  374. package/src/client/resources/McpConnectionSuggestion.tsx +19 -2
  375. package/src/client/resources/ResourceTree.tsx +7 -10
  376. package/src/client/resources/ResourcesPanel.tsx +33 -70
  377. package/src/client/resources/mcp-connection-resume.ts +107 -0
  378. package/src/client/resources/mcp-integration-catalog.ts +65 -12
  379. package/src/client/resources/mcp-integration-logos.ts +4 -0
  380. package/src/client/sse-event-processor.ts +50 -14
  381. package/src/client/use-db-sync.ts +16 -6
  382. package/src/connections/catalog.ts +7 -1
  383. package/src/eject/remote-mcp-presets.ts +37 -5
  384. package/src/guards/explicit-collab-access.ts +229 -0
  385. package/src/guards/index.ts +1 -0
  386. package/src/localization/default-messages.ts +54 -5
  387. package/src/mcp/connect-route.ts +34 -51
  388. package/src/provider-api/index.ts +1 -1
  389. package/src/server/collab-plugin.ts +137 -18
  390. package/src/server/index.ts +2 -0
  391. package/src/styles/agent-native.css +40 -0
  392. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  393. package/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  394. package/src/templates/chat/app/components/layout/Layout.tsx +1 -0
  395. package/src/templates/chat/app/components/layout/Sidebar.tsx +43 -67
  396. package/src/templates/chat/app/hooks/use-navigation-state.ts +2 -7
  397. package/src/templates/chat/app/routes/_index.tsx +8 -5
  398. package/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  399. package/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  400. package/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  401. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  402. package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
  403. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  404. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  405. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  406. package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
  407. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  408. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
@@ -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
  });
@@ -629,6 +629,11 @@ const enUS = {
629
629
  refresh: "Refresh",
630
630
  refreshing: "Refreshing...",
631
631
  downloadCsv: "Download CSV",
632
+ exportToGoogleSheets: "Export to Google Sheets",
633
+ exportingToGoogleSheets: "Exporting to Google Sheets...",
634
+ googleSheetsExported: "Exported to Google Sheets",
635
+ openGoogleSheet: "Open sheet",
636
+ googleSheetsExportFailed: "Couldn't export to Google Sheets: {{message}}",
632
637
  viewSql: "View SQL",
633
638
  dragToReorder: "Drag to reorder",
634
639
  deleteSectionTitle: "Delete section?",
@@ -814,6 +819,11 @@ const enUS = {
814
819
  },
815
820
  dataSources: {
816
821
  uploadFile: "Upload file",
822
+ googleSheetsExport: "Google Sheets export",
823
+ googleSheetsExportDescription:
824
+ "Export dashboard reports to Google Sheets through a shared Google connection.",
825
+ connected: "Connected",
826
+ googleSheets: "Google Sheets",
817
827
  open: "Open",
818
828
  savedValueHint:
819
829
  "A value is already saved. Leave blank to keep it, or enter a new value to replace it.",
@@ -1274,6 +1284,11 @@ const analyticsSliceTranslations: {
1274
1284
  },
1275
1285
  dataSources: {
1276
1286
  uploadFile: "上传文件",
1287
+ googleSheetsExport: "Google Sheets 导出",
1288
+ googleSheetsExportDescription:
1289
+ "通过共享的 Google 连接将仪表板报告导出到 Google Sheets。",
1290
+ connected: "已连接",
1291
+ googleSheets: "Google Sheets",
1277
1292
  open: "打开",
1278
1293
  savedValueHint: "值已保存。留空以保留它,或输入新值以替换它。",
1279
1294
  githubOAuth: "GitHub OAuth",
@@ -1557,6 +1572,11 @@ const analyticsSliceTranslations: {
1557
1572
  },
1558
1573
  dataSources: {
1559
1574
  uploadFile: "Subir archivo",
1575
+ googleSheetsExport: "Exportación a Google Sheets",
1576
+ googleSheetsExportDescription:
1577
+ "Exporte informes del panel a Google Sheets mediante una conexión de Google compartida.",
1578
+ connected: "Conectado",
1579
+ googleSheets: "Google Sheets",
1560
1580
  open: "Abierto",
1561
1581
  savedValueHint:
1562
1582
  "Ya hay un valor guardado. Déjelo en blanco para conservarlo o ingrese un nuevo valor para reemplazarlo.",
@@ -1862,6 +1882,11 @@ const analyticsSliceTranslations: {
1862
1882
  },
1863
1883
  dataSources: {
1864
1884
  uploadFile: "Télécharger le fichier",
1885
+ googleSheetsExport: "Export Google Sheets",
1886
+ googleSheetsExportDescription:
1887
+ "Exportez les rapports du tableau de bord vers Google Sheets grâce à une connexion Google partagée.",
1888
+ connected: "Connecté",
1889
+ googleSheets: "Google Sheets",
1865
1890
  open: "Ouvrir",
1866
1891
  savedValueHint:
1867
1892
  "Une valeur est déjà enregistrée. Laissez vide pour le conserver ou saisissez une nouvelle valeur pour le remplacer.",
@@ -2163,6 +2188,11 @@ const analyticsSliceTranslations: {
2163
2188
  },
2164
2189
  dataSources: {
2165
2190
  uploadFile: "Datei hochladen",
2191
+ googleSheetsExport: "Google-Sheets-Export",
2192
+ googleSheetsExportDescription:
2193
+ "Exportieren Sie Dashboard-Berichte über eine gemeinsame Google-Verbindung nach Google Sheets.",
2194
+ connected: "Verbunden",
2195
+ googleSheets: "Google Sheets",
2166
2196
  open: "Offen",
2167
2197
  savedValueHint:
2168
2198
  "Ein Wert ist bereits gespeichert. Lassen Sie das Feld leer, um es beizubehalten, oder geben Sie einen neuen Wert ein, um es zu ersetzen.",
@@ -2463,6 +2493,11 @@ const analyticsSliceTranslations: {
2463
2493
  },
2464
2494
  dataSources: {
2465
2495
  uploadFile: "ファイルをアップロードする",
2496
+ googleSheetsExport: "Google スプレッドシートへのエクスポート",
2497
+ googleSheetsExportDescription:
2498
+ "共有 Google 接続を使用してダッシュボードレポートを Google スプレッドシートにエクスポートします。",
2499
+ connected: "接続済み",
2500
+ googleSheets: "Google Sheets",
2466
2501
  open: "開ける",
2467
2502
  savedValueHint:
2468
2503
  "値はすでに保存されています。空白のままにして保持するか、新しい値を入力して置き換えます。",
@@ -2758,6 +2793,11 @@ const analyticsSliceTranslations: {
2758
2793
  },
2759
2794
  dataSources: {
2760
2795
  uploadFile: "파일 업로드",
2796
+ googleSheetsExport: "Google Sheets 내보내기",
2797
+ googleSheetsExportDescription:
2798
+ "공유 Google 연결을 통해 대시보드 보고서를 Google Sheets로 내보냅니다.",
2799
+ connected: "연결됨",
2800
+ googleSheets: "Google Sheets",
2761
2801
  open: "열려 있는",
2762
2802
  savedValueHint:
2763
2803
  "값이 이미 저장되어 있습니다. 유지하려면 비워두고, 바꾸려면 새 값을 입력하세요.",
@@ -3049,6 +3089,11 @@ const analyticsSliceTranslations: {
3049
3089
  },
3050
3090
  dataSources: {
3051
3091
  uploadFile: "Carregar arquivo",
3092
+ googleSheetsExport: "Exportação para o Google Sheets",
3093
+ googleSheetsExportDescription:
3094
+ "Exporte relatórios do painel para o Google Sheets por meio de uma conexão Google compartilhada.",
3095
+ connected: "Conectado",
3096
+ googleSheets: "Google Sheets",
3052
3097
  open: "Abrir",
3053
3098
  savedValueHint:
3054
3099
  "Um valor já está salvo. Deixe em branco para mantê-lo ou insira um novo valor para substituí-lo.",
@@ -3345,6 +3390,11 @@ const analyticsSliceTranslations: {
3345
3390
  },
3346
3391
  dataSources: {
3347
3392
  uploadFile: "फ़ाइल अपलोड करें",
3393
+ googleSheetsExport: "Google Sheets निर्यात",
3394
+ googleSheetsExportDescription:
3395
+ "साझा Google कनेक्शन के माध्यम से डैशबोर्ड रिपोर्ट को Google Sheets में निर्यात करें।",
3396
+ connected: "कनेक्टेड",
3397
+ googleSheets: "Google Sheets",
3348
3398
  open: "खुला",
3349
3399
  savedValueHint:
3350
3400
  "एक मान पहले से ही सहेजा गया है. इसे रखने के लिए खाली छोड़ दें, या इसे बदलने के लिए एक नया मान दर्ज करें।",
@@ -3632,6 +3682,11 @@ const analyticsSliceTranslations: {
3632
3682
  },
3633
3683
  dataSources: {
3634
3684
  uploadFile: "تحميل الملف",
3685
+ googleSheetsExport: "تصدير Google Sheets",
3686
+ googleSheetsExportDescription:
3687
+ "صدّر تقارير لوحة المعلومات إلى Google Sheets من خلال اتصال Google مشترك.",
3688
+ connected: "متصل",
3689
+ googleSheets: "Google Sheets",
3635
3690
  open: "يفتح",
3636
3691
  savedValueHint:
3637
3692
  "تم حفظ القيمة بالفعل. اتركه فارغًا للاحتفاظ به، أو أدخل قيمة جديدة لاستبداله.",
@@ -6059,6 +6114,11 @@ const translatedAnalyticsDebtTranslations = {
6059
6114
  discardChanges: "放弃更改",
6060
6115
  dismissDemoIntro: "关闭演示介绍",
6061
6116
  downloadCsv: "下载CSV",
6117
+ exportToGoogleSheets: "导出到 Google Sheets",
6118
+ exportingToGoogleSheets: "正在导出到 Google Sheets...",
6119
+ googleSheetsExported: "已导出到 Google Sheets",
6120
+ openGoogleSheet: "打开表格",
6121
+ googleSheetsExportFailed: "无法导出到 Google Sheets:{{message}}",
6062
6122
  dragToReorder: "拖动以重新排序",
6063
6123
  expandFilters: "展开过滤器",
6064
6124
  failedToFormatSql: "无法格式化 SQL",
@@ -6271,6 +6331,12 @@ const translatedAnalyticsDebtTranslations = {
6271
6331
  discardChanges: "Descartar cambios",
6272
6332
  dismissDemoIntro: "Descartar la introducción de la demostración",
6273
6333
  downloadCsv: "Descargar CSV",
6334
+ exportToGoogleSheets: "Exportar a Google Sheets",
6335
+ exportingToGoogleSheets: "Exportando a Google Sheets...",
6336
+ googleSheetsExported: "Exportado a Google Sheets",
6337
+ openGoogleSheet: "Abrir hoja",
6338
+ googleSheetsExportFailed:
6339
+ "No se pudo exportar a Google Sheets: {{message}}",
6274
6340
  dragToReorder: "Arrastra para reordenar",
6275
6341
  expandFilters: "Ampliar filtros",
6276
6342
  failedToFormatSql: "No se pudo formatear SQL",
@@ -6488,6 +6554,12 @@ const translatedAnalyticsDebtTranslations = {
6488
6554
  discardChanges: "Ignorer les modifications",
6489
6555
  dismissDemoIntro: "Ignorer l'intro de la démo",
6490
6556
  downloadCsv: "Télécharger CSV",
6557
+ exportToGoogleSheets: "Exporter vers Google Sheets",
6558
+ exportingToGoogleSheets: "Exportation vers Google Sheets...",
6559
+ googleSheetsExported: "Exporté vers Google Sheets",
6560
+ openGoogleSheet: "Ouvrir la feuille",
6561
+ googleSheetsExportFailed:
6562
+ "Impossible d’exporter vers Google Sheets : {{message}}",
6491
6563
  dragToReorder: "Faites glisser pour réorganiser",
6492
6564
  expandFilters: "Développer les filtres",
6493
6565
  failedToFormatSql: "Échec du formatage de SQL",
@@ -6706,6 +6778,12 @@ const translatedAnalyticsDebtTranslations = {
6706
6778
  discardChanges: "Änderungen verwerfen",
6707
6779
  dismissDemoIntro: "Demo-Intro schließen",
6708
6780
  downloadCsv: "Laden Sie CSV herunter",
6781
+ exportToGoogleSheets: "Nach Google Sheets exportieren",
6782
+ exportingToGoogleSheets: "Export nach Google Sheets...",
6783
+ googleSheetsExported: "Nach Google Sheets exportiert",
6784
+ openGoogleSheet: "Tabelle öffnen",
6785
+ googleSheetsExportFailed:
6786
+ "Export nach Google Sheets fehlgeschlagen: {{message}}",
6709
6787
  dragToReorder: "Zum Neuanordnen ziehen",
6710
6788
  expandFilters: "Filter erweitern",
6711
6789
  failedToFormatSql: "SQL konnte nicht formatiert werden",
@@ -6919,6 +6997,12 @@ const translatedAnalyticsDebtTranslations = {
6919
6997
  discardChanges: "変更を破棄する",
6920
6998
  dismissDemoIntro: "デモのイントロを閉じる",
6921
6999
  downloadCsv: "CSVをダウンロード",
7000
+ exportToGoogleSheets: "Google スプレッドシートにエクスポート",
7001
+ exportingToGoogleSheets: "Google スプレッドシートにエクスポート中...",
7002
+ googleSheetsExported: "Google スプレッドシートにエクスポートしました",
7003
+ openGoogleSheet: "シートを開く",
7004
+ googleSheetsExportFailed:
7005
+ "Google スプレッドシートへのエクスポートに失敗しました: {{message}}",
6922
7006
  dragToReorder: "ドラッグして並べ替えます",
6923
7007
  expandFilters: "フィルターを展開する",
6924
7008
  failedToFormatSql: "SQLのフォーマットに失敗しました",
@@ -7131,6 +7215,12 @@ const translatedAnalyticsDebtTranslations = {
7131
7215
  discardChanges: "변경사항 취소",
7132
7216
  dismissDemoIntro: "데모 소개 닫기",
7133
7217
  downloadCsv: "CSV 다운로드",
7218
+ exportToGoogleSheets: "Google Sheets로 내보내기",
7219
+ exportingToGoogleSheets: "Google Sheets로 내보내는 중...",
7220
+ googleSheetsExported: "Google Sheets로 내보냈습니다",
7221
+ openGoogleSheet: "시트 열기",
7222
+ googleSheetsExportFailed:
7223
+ "Google Sheets로 내보내지 못했습니다: {{message}}",
7134
7224
  dragToReorder: "드래그하여 재정렬하세요.",
7135
7225
  expandFilters: "필터 확장",
7136
7226
  failedToFormatSql: "SQL을 포맷하지 못했습니다.",
@@ -7347,6 +7437,12 @@ const translatedAnalyticsDebtTranslations = {
7347
7437
  discardChanges: "Descartar alterações",
7348
7438
  dismissDemoIntro: "Ignorar introdução da demonstração",
7349
7439
  downloadCsv: "Baixar CSV",
7440
+ exportToGoogleSheets: "Exportar para o Google Sheets",
7441
+ exportingToGoogleSheets: "Exportando para o Google Sheets...",
7442
+ googleSheetsExported: "Exportado para o Google Sheets",
7443
+ openGoogleSheet: "Abrir planilha",
7444
+ googleSheetsExportFailed:
7445
+ "Não foi possível exportar para o Google Sheets: {{message}}",
7350
7446
  dragToReorder: "Arraste para reordenar",
7351
7447
  expandFilters: "Expandir filtros",
7352
7448
  failedToFormatSql: "Falha ao formatar SQL",
@@ -7559,6 +7655,12 @@ const translatedAnalyticsDebtTranslations = {
7559
7655
  discardChanges: "परिवर्तन त्यागें",
7560
7656
  dismissDemoIntro: "डेमो परिचय ख़ारिज करें",
7561
7657
  downloadCsv: "CSV डाउनलोड करें",
7658
+ exportToGoogleSheets: "Google Sheets में निर्यात करें",
7659
+ exportingToGoogleSheets: "Google Sheets में निर्यात किया जा रहा है...",
7660
+ googleSheetsExported: "Google Sheets में निर्यात किया गया",
7661
+ openGoogleSheet: "शीट खोलें",
7662
+ googleSheetsExportFailed:
7663
+ "Google Sheets में निर्यात नहीं किया जा सका: {{message}}",
7562
7664
  dragToReorder: "पुनः व्यवस्थित करने के लिए खींचें",
7563
7665
  expandFilters: "फ़िल्टर का विस्तार करें",
7564
7666
  failedToFormatSql: "SQL को प्रारूपित करने में विफल",
@@ -7770,6 +7872,11 @@ const translatedAnalyticsDebtTranslations = {
7770
7872
  discardChanges: "تجاهل التغييرات",
7771
7873
  dismissDemoIntro: "رفض المقدمة التجريبية",
7772
7874
  downloadCsv: "تحميل CSV",
7875
+ exportToGoogleSheets: "تصدير إلى Google Sheets",
7876
+ exportingToGoogleSheets: "جارٍ التصدير إلى Google Sheets...",
7877
+ googleSheetsExported: "تم التصدير إلى Google Sheets",
7878
+ openGoogleSheet: "فتح الورقة",
7879
+ googleSheetsExportFailed: "تعذر التصدير إلى Google Sheets: {{message}}",
7773
7880
  dragToReorder: "اسحب لإعادة الترتيب",
7774
7881
  expandFilters: "قم بتوسيع عوامل التصفية",
7775
7882
  failedToFormatSql: "فشل تنسيق SQL",
@@ -74,6 +74,15 @@ const dataSourceWorkspaceProviderIds: Record<string, string> = {
74
74
  slack: "slack",
75
75
  };
76
76
 
77
+ export function getGoogleDriveConnection(
78
+ data: DataSourceStatusResponse | undefined,
79
+ ): WorkspaceConnectionProviderSummary | undefined {
80
+ return data?.workspaceConnections?.providers.find(
81
+ (provider) =>
82
+ provider.provider === "google_drive" || provider.id === "google_drive",
83
+ );
84
+ }
85
+
77
86
  const sharedConnectionLabels: Record<SharedConnectionStatusKind, string> = {
78
87
  ready: "Ready via workspace",
79
88
  needs_grant: "Needs grant",