@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
@@ -289,7 +289,7 @@ When the agent creates a draft email, it appears in the UI. When you click "Send
289
289
 
290
290
  The reason tools like Claude Code feel so powerful isn't the model — it's the **customization layer**: per-project instructions, skills, memory, sub-agents, connected services. You can shape the agent to your codebase, your preferences, your team.
291
291
 
292
- Agent-native gives every user that same customization layer — without ever leaving the app. Each app comes with a personal **workspace** where you (or anyone on your team) can:
292
+ Agent-native gives every user that same customization layer — without ever leaving the app. Each app comes with personal **agent resources** that you (or anyone on your team) can use to:
293
293
 
294
294
  - Edit team-wide rules everyone's agent reads
295
295
  - Let the agent remember preferences automatically as you correct it
@@ -298,9 +298,9 @@ Agent-native gives every user that same customization layer — without ever lea
298
298
  - Schedule jobs to run on a cron (e.g. "every Monday morning, summarize last week")
299
299
  - Connect external services (Gmail, Stripe, Slack, internal APIs) via per-user MCP servers
300
300
 
301
- The twist: it's all stored in the database, not the filesystem. There's no dev environment to spin up, no container per user. Every user gets their own full workspace — personal memory, personal connections, personal skills — for essentially free, because it's all rows in a table. That's what makes Claude-Code-level flexibility viable inside a real multi-tenant SaaS product.
301
+ The twist: it's all stored in the database, not the filesystem. There's no dev environment to spin up, no container per user. Every user gets their own full set of agent resources — personal memory, personal connections, personal skills — for essentially free, because it's all rows in a table. That's what makes Claude-Code-level flexibility viable inside a real multi-tenant SaaS product.
302
302
 
303
- See [Agent Resources](/docs/workspace) for the full concept.
303
+ See [Agent Resources](/docs/agent-resources) for the full concept.
304
304
 
305
305
  ## What makes it different {#what-makes-it-different}
306
306
 
@@ -396,7 +396,7 @@ One action, many surfaces: the agent calls it as a tool, the UI calls it as a ty
396
396
  - [**Agent Surfaces**](/docs/agent-surfaces) — choose chat, native inline UI, full app pages, embedded sidecar, automation, or external agent access
397
397
  - [**Key Concepts**](/docs/key-concepts) — the architecture: SQL, actions, polling sync, context awareness, portability
398
398
  - [**Templates**](/docs/cloneable-saas) — templates as complete products you own
399
- - [**Agent Resources**](/docs/workspace) — the per-user customization layer (skills, memory, instructions, MCP) backed by SQL, not files
399
+ - [**Agent Resources**](/docs/agent-resources) — the per-user customization layer (skills, memory, instructions, MCP) backed by SQL, not files
400
400
  - [**Dispatch**](/docs/dispatch) — the workspace control plane: secrets vault, Slack/email inbox, cross-app delegation
401
401
  - [**Extensions**](/docs/extensions) — sandboxed mini-apps the agent creates instantly without code changes
402
402
  - [**Drop-in Agent**](/docs/drop-in-agent) — mount `<AgentPanel>` into any React app
@@ -7,7 +7,7 @@ description: "Branching, CODEOWNERS, PR review, and how Dispatch handles runtime
7
7
 
8
8
  <Callout tone="info">
9
9
 
10
- **Which workspace doc?** This page covers **governance** — who reviews, approves, and owns what across many apps in one repo. For the agent customization layer (Agent Resources: `AGENTS.md`, memory, skills, custom agents) see [Agent Resources](/docs/workspace); for the deployment shape (one monorepo, many apps) see [Multi-App Workspaces](/docs/multi-app-workspace).
10
+ **Which workspace doc?** This page covers **governance** — who reviews, approves, and owns what across many apps in one repo. For the agent customization layer (Agent Resources: `AGENTS.md`, memory, skills, custom agents) see [Agent Resources](/docs/agent-resources); for the deployment shape (one monorepo, many apps) see [Multi-App Workspaces](/docs/multi-app-workspace).
11
11
 
12
12
  </Callout>
13
13
 
@@ -211,7 +211,7 @@ The [Dispatch](/docs/dispatch) app is the workspace's runtime control plane. It
211
211
 
212
212
  Dispatch manages: vault secrets, reusable workspace connections, workspace resources (skills, instructions, agent profiles, MCP servers), approvals, and audit logs. For public app route configuration (`workspaceApp.audience` / `publicPaths` / `protectedPaths`), see [Multi-App Workspaces — Public app routes](/docs/multi-app-workspace#deployment).
213
213
 
214
- For the resource model and canonical paths, see [Agent Resources — Global resources](/docs/workspace#global-resources).
214
+ For the resource model and canonical paths, see [Agent Resources — Global resources](/docs/agent-resources#global-resources).
215
215
 
216
216
  ## Setup Checklist
217
217
 
@@ -232,7 +232,7 @@ For a new workspace, after running `npx @agent-native/core@latest create`:
232
232
  - [ ] Register reusable workspace connections for shared provider accounts, then
233
233
  grant apps such as Brain, Analytics, Mail, or Dispatch only when they need
234
234
  that account
235
- - [ ] Add workspace-wide skills, guardrail instructions, and brand/company reference resources via the Resources page. See [Agent Resources](/docs/workspace#global-resources) for the full resource-model table and the recommended starter pack.
235
+ - [ ] Add workspace-wide skills, guardrail instructions, and brand/company reference resources via the Resources page. See [Agent Resources](/docs/agent-resources#global-resources) for the full resource-model table and the recommended starter pack.
236
236
  - [ ] Configure the approval policy and approver emails
237
237
  - [ ] Set up SendGrid (`SENDGRID_API_KEY`, `SENDGRID_FROM_EMAIL`) for admin notifications
238
238
  - [ ] Connect Slack or Telegram for workspace messaging
@@ -240,7 +240,7 @@ For a new workspace, after running `npx @agent-native/core@latest create`:
240
240
 
241
241
  ## What's next {#whats-next}
242
242
 
243
- - [**Agent Resources**](/docs/workspace) — the customization layer this page governs (skills, memory, agents, MCP servers)
243
+ - [**Agent Resources**](/docs/agent-resources) — the customization layer this page governs (skills, memory, agents, MCP servers)
244
244
  - [**Multi-App Workspaces**](/docs/multi-app-workspace) — the deployment shape: one monorepo, many apps
245
245
  - [**Dispatch**](/docs/dispatch) — the runtime control plane referenced throughout this page
246
246
  - [**Sharing**](/docs/sharing) — access control for individual resources, complementing repo-level CODEOWNERS
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.115.4",
3
+ "version": "0.117.0",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -68,6 +68,9 @@
68
68
  "./server/agent-discovery": "./dist/server/agent-discovery.js",
69
69
  "./server/request-context": "./dist/server/request-context.js",
70
70
  "./server/design-token-utils": "./dist/server/design-token-utils.js",
71
+ "./server/poll": "./dist/server/poll.js",
72
+ "./server/sse": "./dist/server/sse.js",
73
+ "./server/short-lived-token": "./dist/server/short-lived-token.js",
71
74
  "./integrations": "./dist/integrations/index.js",
72
75
  "./integrations/runtime": "./dist/integrations/runtime.js",
73
76
  "./ingestion": "./dist/ingestion/index.js",
@@ -3986,8 +3986,16 @@ export async function runAgentLoop(opts: {
3986
3986
  }
3987
3987
  }
3988
3988
  if (!assistantContent) {
3989
- // No content — done
3990
- break;
3989
+ if (!terminalStopReason) {
3990
+ // A stream that disappears without a terminal stop is an interrupted
3991
+ // chunk, not a successful empty answer. Let the continuation path
3992
+ // recover it instead of persisting a tool-only completed turn.
3993
+ send({ type: "auto_continue", reason: "stream_ended" });
3994
+ return usage;
3995
+ }
3996
+ // Route a clean terminal stop with no normalized content through the
3997
+ // empty-final retry/fallback below.
3998
+ assistantContent = [];
3991
3999
  }
3992
4000
 
3993
4001
  if (toolCallErrors.size > 0) {
@@ -4022,7 +4030,9 @@ export async function runAgentLoop(opts: {
4022
4030
  : part,
4023
4031
  );
4024
4032
 
4025
- messages.push({ role: "assistant", content: assistantContentForHistory });
4033
+ if (assistantContentForHistory.length > 0) {
4034
+ messages.push({ role: "assistant", content: assistantContentForHistory });
4035
+ }
4026
4036
 
4027
4037
  const toolCallParts = assistantContent.filter(
4028
4038
  (p): p is import("./engine/types.js").EngineToolCallPart =>
@@ -4,7 +4,7 @@
4
4
  * itself via `scripts/guard-*.mjs` (see
5
5
  * `advisor-plans/reports/005-doctor-design.md` for the full design and
6
6
  * `advisor-plans/015-doctor-v1-implementation.md` for the implementation
7
- * plan). v1 ships 8 of those guards, ported to work against a single
7
+ * plan). v1 ships 9 of those guards, ported to work against a single
8
8
  * generated app root instead of this monorepo's multi-template layout —
9
9
  * see `../guards/index.ts`.
10
10
  *
@@ -28,6 +28,7 @@ import {
28
28
  scanDrizzlePush,
29
29
  scanEnvCredentials,
30
30
  scanEnvMutation,
31
+ scanExplicitCollabAccess,
31
32
  scanLocalhostFallback,
32
33
  scanUnscopedCredentials,
33
34
  scanUnscopedQueries,
@@ -47,6 +48,7 @@ export type GuardName =
47
48
  | "db-tool-scoping"
48
49
  | "no-env-mutation"
49
50
  | "no-localhost-fallback"
51
+ | "explicit-collab-access"
50
52
  | "migration-manifest";
51
53
 
52
54
  export const ALL_GUARD_NAMES: GuardName[] = [
@@ -57,6 +59,7 @@ export const ALL_GUARD_NAMES: GuardName[] = [
57
59
  "db-tool-scoping",
58
60
  "no-env-mutation",
59
61
  "no-localhost-fallback",
62
+ "explicit-collab-access",
60
63
  "migration-manifest",
61
64
  ];
62
65
 
@@ -150,6 +153,8 @@ function runGuard(
150
153
  return scanEnvMutation({ root });
151
154
  case "no-localhost-fallback":
152
155
  return scanLocalhostFallback({ root, extraExemptPaths: [] });
156
+ case "explicit-collab-access":
157
+ return scanExplicitCollabAccess({ root });
153
158
  case "migration-manifest": {
154
159
  const imports = scanDeprecatedImports({
155
160
  root,
@@ -66,7 +66,7 @@ import {
66
66
  normalizeTooltipText,
67
67
  } from "./components/ui/tooltip.js";
68
68
  import { ErrorReportActions } from "./ErrorReportActions.js";
69
- import { FeedbackButton } from "./FeedbackButton.js";
69
+ import { FeedbackButton, resolveFeedbackUrl } from "./FeedbackButton.js";
70
70
  import { RunsTrayMenuItem } from "./progress/RunsTray.js";
71
71
  import { ShareButton } from "./sharing/ShareButton.js";
72
72
  // Lazy-load the full assistant-ui chat stack (tiptap composer + react-markdown +
@@ -773,6 +773,7 @@ function AgentPanelInner({
773
773
  ...assistantChatProps
774
774
  }: AgentPanelProps) {
775
775
  const t = useT();
776
+ const feedbackEnabled = resolveFeedbackUrl() !== null;
776
777
  const navigate = useNavigate();
777
778
  const mounted = useClientOnly();
778
779
  const keyPrefix = storageKey ? `:${storageKey}` : "";
@@ -1218,23 +1219,25 @@ function AgentPanelInner({
1218
1219
  />
1219
1220
  );
1220
1221
  })()}
1221
- <FeedbackButton
1222
- variant="icon"
1223
- side="bottom"
1224
- align="end"
1225
- chatSessionId={activeChatSessionId}
1226
- chatStorageKey={storageKey}
1227
- open={feedbackOpen}
1228
- onOpenChange={setFeedbackOpen}
1229
- trigger={
1230
- <button
1231
- type="button"
1232
- tabIndex={-1}
1233
- aria-hidden="true"
1234
- className="pointer-events-none absolute end-0 top-full h-px w-px opacity-0"
1235
- />
1236
- }
1237
- />
1222
+ {feedbackEnabled ? (
1223
+ <FeedbackButton
1224
+ variant="icon"
1225
+ side="bottom"
1226
+ align="end"
1227
+ chatSessionId={activeChatSessionId}
1228
+ chatStorageKey={storageKey}
1229
+ open={feedbackOpen}
1230
+ onOpenChange={setFeedbackOpen}
1231
+ trigger={
1232
+ <button
1233
+ type="button"
1234
+ tabIndex={-1}
1235
+ aria-hidden="true"
1236
+ className="pointer-events-none absolute end-0 top-full h-px w-px opacity-0"
1237
+ />
1238
+ }
1239
+ />
1240
+ ) : null}
1238
1241
  {mode === "chat" && (
1239
1242
  <IconTooltip content={t("agentPanel.newChat")}>
1240
1243
  <button
@@ -1355,17 +1358,19 @@ function AgentPanelInner({
1355
1358
  {t("agentPanel.settings")}
1356
1359
  </DropdownMenuItem>
1357
1360
  )}
1358
- <DropdownMenuItem
1359
- onSelect={() => {
1360
- // Defer past the closing DropdownMenu's focus-restore/dismiss-layer
1361
- // teardown, otherwise it can immediately dismiss the Popover we're
1362
- // opening in the same tick (Radix nested-overlay race).
1363
- setTimeout(() => setFeedbackOpen(true), 0);
1364
- }}
1365
- >
1366
- <IconMessageDots size={14} className="shrink-0" />
1367
- {t("agentPanel.feedback")}
1368
- </DropdownMenuItem>
1361
+ {feedbackEnabled ? (
1362
+ <DropdownMenuItem
1363
+ onSelect={() => {
1364
+ // Defer past the closing DropdownMenu's focus-restore/dismiss-layer
1365
+ // teardown, otherwise it can immediately dismiss the Popover we're
1366
+ // opening in the same tick (Radix nested-overlay race).
1367
+ setTimeout(() => setFeedbackOpen(true), 0);
1368
+ }}
1369
+ >
1370
+ <IconMessageDots size={14} className="shrink-0" />
1371
+ {t("agentPanel.feedback")}
1372
+ </DropdownMenuItem>
1373
+ ) : null}
1369
1374
  {onToggleFullscreen && (
1370
1375
  <DropdownMenuItem onSelect={onToggleFullscreen}>
1371
1376
  {isFullscreen ? (
@@ -1464,6 +1469,7 @@ function AgentPanelInner({
1464
1469
  closeOtherCliTabs,
1465
1470
  closeTabHint,
1466
1471
  feedbackOpen,
1472
+ feedbackEnabled,
1467
1473
  getChatThreadShareUrl,
1468
1474
  headerMenuOpen,
1469
1475
  isFullscreen,
@@ -1541,24 +1547,42 @@ function AgentPanelInner({
1541
1547
  [getChatThreadShareUrl, t],
1542
1548
  );
1543
1549
 
1544
- // Ref callback: scroll the active tab into view in the overflow container.
1545
- // Uses getBoundingClientRect for reliable positioning regardless of offsetParent.
1546
- const activeTabRefCb = useCallback((el: HTMLDivElement | null) => {
1547
- if (!el) return;
1550
+ const activeTabResizeObserverRef = useRef<ResizeObserver | null>(null);
1551
+ const scrollActiveTabIntoView = useCallback((el: HTMLDivElement) => {
1548
1552
  const container = el.parentElement;
1549
1553
  if (!container) return;
1550
- // Use rAF so layout is settled after React commit
1551
1554
  requestAnimationFrame(() => {
1552
- const containerRect = container.getBoundingClientRect();
1553
- const tabRect = el.getBoundingClientRect();
1554
- if (tabRect.left < containerRect.left) {
1555
- container.scrollLeft += tabRect.left - containerRect.left;
1556
- } else if (tabRect.right > containerRect.right) {
1557
- container.scrollLeft += tabRect.right - containerRect.right;
1558
- }
1555
+ const delta = getActiveTabScrollDelta(
1556
+ container.getBoundingClientRect(),
1557
+ el.getBoundingClientRect(),
1558
+ );
1559
+ if (delta !== 0) container.scrollLeft += delta;
1559
1560
  });
1560
1561
  }, []);
1561
1562
 
1563
+ // The sidebar stays mounted while closed and animates its width on open, so
1564
+ // the active tab ref alone can run before the overflow container is usable.
1565
+ const activeTabRefCb = useCallback(
1566
+ (el: HTMLDivElement | null) => {
1567
+ activeTabResizeObserverRef.current?.disconnect();
1568
+ activeTabResizeObserverRef.current = null;
1569
+ if (!el) return;
1570
+ const container = el.parentElement;
1571
+ if (!container) return;
1572
+
1573
+ const observer =
1574
+ typeof ResizeObserver === "undefined"
1575
+ ? null
1576
+ : new ResizeObserver(() => scrollActiveTabIntoView(el));
1577
+ observer?.observe(container);
1578
+ activeTabResizeObserverRef.current = observer;
1579
+ scrollActiveTabIntoView(el);
1580
+ },
1581
+ [scrollActiveTabIntoView],
1582
+ );
1583
+
1584
+ useEffect(() => () => activeTabResizeObserverRef.current?.disconnect(), []);
1585
+
1562
1586
  const renderChatHeader = useCallback(
1563
1587
  ({
1564
1588
  tabs,
@@ -2108,6 +2132,20 @@ const SIDEBAR_FULLSCREEN_Z_INDEX = 90;
2108
2132
  /** Shared max width of the centered fullscreen chat column and composer. */
2109
2133
  const FULLSCREEN_CHAT_COLUMN_MAX_PX = 684;
2110
2134
 
2135
+ export function getActiveTabScrollDelta(
2136
+ containerRect: Pick<DOMRect, "left" | "right">,
2137
+ tabRect: Pick<DOMRect, "left" | "right">,
2138
+ margin = 24,
2139
+ ): number {
2140
+ if (tabRect.left < containerRect.left + margin) {
2141
+ return tabRect.left - containerRect.left - margin;
2142
+ }
2143
+ if (tabRect.right > containerRect.right - margin) {
2144
+ return tabRect.right - containerRect.right + margin;
2145
+ }
2146
+ return 0;
2147
+ }
2148
+
2111
2149
  function ResizeHandle({
2112
2150
  position,
2113
2151
  onDrag,
@@ -173,6 +173,11 @@ import {
173
173
  useGuidedQuestionFlow,
174
174
  } from "./guided-questions.js";
175
175
  import { useT } from "./i18n.js";
176
+ import {
177
+ addMcpConnectionCompleteListener,
178
+ consumeMcpConnectionResume,
179
+ type McpConnectionResumeRequest,
180
+ } from "./resources/mcp-connection-resume.js";
176
181
  import { McpConnectionSuggestion } from "./resources/McpConnectionSuggestion.js";
177
182
  import {
178
183
  AgentAutoContinueSignal,
@@ -1513,20 +1518,24 @@ export function resolveAssistantChatRunningStatusLabel({
1513
1518
  return "Thinking";
1514
1519
  }
1515
1520
 
1516
- function contentHasVisibleReasoning(content: unknown): boolean {
1521
+ function contentHasVisibleTailReasoning(content: unknown): boolean {
1517
1522
  if (!Array.isArray(content)) return false;
1518
- return content.some((part) => {
1519
- if (!part || typeof part !== "object") return false;
1523
+ for (let index = content.length - 1; index >= 0; index -= 1) {
1524
+ const part = content[index];
1525
+ if (!part || typeof part !== "object") continue;
1520
1526
  const candidate = part as { type?: unknown; text?: unknown };
1521
- return (
1522
- candidate.type === "reasoning" &&
1523
- typeof candidate.text === "string" &&
1524
- candidate.text.trim().length > 0
1525
- );
1526
- });
1527
+ if (
1528
+ (candidate.type === "text" || candidate.type === "reasoning") &&
1529
+ (typeof candidate.text !== "string" || candidate.text.trim().length === 0)
1530
+ ) {
1531
+ continue;
1532
+ }
1533
+ return candidate.type === "reasoning";
1534
+ }
1535
+ return false;
1527
1536
  }
1528
1537
 
1529
- function contentHasUnresolvedToolCall(
1538
+ function contentHasToolCall(
1530
1539
  content: unknown,
1531
1540
  toolName?: string | null,
1532
1541
  ): boolean {
@@ -1540,7 +1549,6 @@ function contentHasUnresolvedToolCall(
1540
1549
  };
1541
1550
  return (
1542
1551
  candidate.type === "tool-call" &&
1543
- candidate.result === undefined &&
1544
1552
  (!toolName || candidate.toolName === toolName)
1545
1553
  );
1546
1554
  });
@@ -1565,17 +1573,19 @@ export function shouldShowGlobalRunningStatus({
1565
1573
  latestMessage && typeof latestMessage === "object"
1566
1574
  ? (latestMessage as { role?: unknown; content?: unknown })
1567
1575
  : null;
1568
- const latestMessageHasReasoning =
1576
+ const latestMessageHasTailReasoning =
1569
1577
  message?.role === "assistant" &&
1570
- contentHasVisibleReasoning(message.content);
1571
- const latestMessageHasUnresolvedTool =
1572
- message?.role === "assistant" &&
1573
- contentHasUnresolvedToolCall(message.content);
1578
+ contentHasVisibleTailReasoning(message.content);
1579
+ const latestMessageHasTool =
1580
+ message?.role === "assistant" && contentHasToolCall(message.content);
1581
+ const reconnectHasTool = contentHasToolCall(reconnectContent);
1582
+ const reconnectHasTailReasoning =
1583
+ contentHasVisibleTailReasoning(reconnectContent);
1574
1584
  const matchingActivityToolIsVisible = Boolean(
1575
1585
  runningActivityTool &&
1576
1586
  ((message?.role === "assistant" &&
1577
- contentHasUnresolvedToolCall(message.content, runningActivityTool)) ||
1578
- contentHasUnresolvedToolCall(reconnectContent, runningActivityTool)),
1587
+ contentHasToolCall(message.content, runningActivityTool)) ||
1588
+ contentHasToolCall(reconnectContent, runningActivityTool)),
1579
1589
  );
1580
1590
 
1581
1591
  // A pending card for the same tool is already the running indicator.
@@ -1584,11 +1594,7 @@ export function shouldShowGlobalRunningStatus({
1584
1594
  if (runningActivityLabel && matchingActivityToolIsVisible) {
1585
1595
  return false;
1586
1596
  }
1587
- if (
1588
- !runningActivityLabel &&
1589
- (latestMessageHasUnresolvedTool ||
1590
- contentHasUnresolvedToolCall(reconnectContent))
1591
- ) {
1597
+ if (!runningActivityLabel && (latestMessageHasTool || reconnectHasTool)) {
1592
1598
  return false;
1593
1599
  }
1594
1600
  // The reasoning cell already owns the generic Thinking state. Activity
@@ -1596,14 +1602,20 @@ export function shouldShowGlobalRunningStatus({
1596
1602
  // rendering both makes a second Thinking row flash beneath the thought.
1597
1603
  if (
1598
1604
  runningActivityLabel === "Thinking" &&
1599
- (latestMessageHasReasoning || contentHasVisibleReasoning(reconnectContent))
1605
+ (latestMessageHasTool ||
1606
+ reconnectHasTool ||
1607
+ latestMessageHasTailReasoning ||
1608
+ reconnectHasTailReasoning)
1600
1609
  ) {
1601
1610
  return false;
1602
1611
  }
1603
1612
  if (runningActivityLabel) return true;
1604
1613
 
1605
1614
  return (
1606
- !latestMessageHasReasoning && !contentHasVisibleReasoning(reconnectContent)
1615
+ !latestMessageHasTool &&
1616
+ !reconnectHasTool &&
1617
+ !latestMessageHasTailReasoning &&
1618
+ !reconnectHasTailReasoning
1607
1619
  );
1608
1620
  }
1609
1621
 
@@ -4676,6 +4688,40 @@ const AssistantChatInner = forwardRef<
4676
4688
  ],
4677
4689
  );
4678
4690
 
4691
+ const mcpResumeTimerRef = useRef<number | null>(null);
4692
+ const scheduleMcpConnectionResume = useCallback(
4693
+ (request: McpConnectionResumeRequest) => {
4694
+ if (mcpResumeTimerRef.current !== null) {
4695
+ window.clearTimeout(mcpResumeTimerRef.current);
4696
+ }
4697
+ mcpResumeTimerRef.current = window.setTimeout(() => {
4698
+ mcpResumeTimerRef.current = null;
4699
+ void addToQueue(request.message);
4700
+ }, 0);
4701
+ },
4702
+ [addToQueue],
4703
+ );
4704
+
4705
+ useEffect(() => {
4706
+ const pending = consumeMcpConnectionResume();
4707
+ if (pending) scheduleMcpConnectionResume(pending);
4708
+
4709
+ return addMcpConnectionCompleteListener(() => {
4710
+ const completed = consumeMcpConnectionResume();
4711
+ if (completed) scheduleMcpConnectionResume(completed);
4712
+ });
4713
+ }, [scheduleMcpConnectionResume]);
4714
+
4715
+ useEffect(
4716
+ () => () => {
4717
+ if (mcpResumeTimerRef.current !== null) {
4718
+ window.clearTimeout(mcpResumeTimerRef.current);
4719
+ mcpResumeTimerRef.current = null;
4720
+ }
4721
+ },
4722
+ [],
4723
+ );
4724
+
4679
4725
  useEffect(() => {
4680
4726
  if (!pendingReconnectRecovery) return;
4681
4727
  const recovery = pendingReconnectRecovery;
@@ -17,9 +17,6 @@ import { useOptionalLocale } from "./i18n.js";
17
17
  import { useSession } from "./use-session.js";
18
18
  import { cn } from "./utils.js";
19
19
 
20
- const DEFAULT_FEEDBACK_URL =
21
- "https://forms.agent-native.com/f/agent-native-feedback/_16ewV";
22
-
23
20
  function isSyntheticAgentNativeAnonymousEmail(
24
21
  value: string | null | undefined,
25
22
  ): boolean {
@@ -234,7 +231,8 @@ export interface FeedbackButtonProps {
234
231
  */
235
232
  variant?: "sidebar" | "icon" | "outlined";
236
233
  label?: string;
237
- url?: string;
234
+ /** Defaults to VITE_AGENT_NATIVE_FEEDBACK_URL. Missing, blank, or null hides the control. */
235
+ url?: string | null;
238
236
  className?: string;
239
237
  /** Which side the popover opens on. Defaults match the variant. */
240
238
  side?: "top" | "bottom" | "left" | "right";
@@ -267,10 +265,38 @@ const honeypotStyle: CSSProperties = {
267
265
  overflow: "hidden",
268
266
  };
269
267
 
270
- export function FeedbackButton({
268
+ function clientEnv(): Record<string, string | boolean | undefined> | undefined {
269
+ const importMetaEnv = (
270
+ import.meta as unknown as {
271
+ env?: Record<string, string | boolean | undefined>;
272
+ }
273
+ ).env;
274
+ const processEnv = (
275
+ globalThis as typeof globalThis & {
276
+ process?: { env?: Record<string, string | boolean | undefined> };
277
+ }
278
+ ).process?.env;
279
+
280
+ if (importMetaEnv && processEnv) return { ...processEnv, ...importMetaEnv };
281
+ return importMetaEnv ?? processEnv;
282
+ }
283
+
284
+ export function resolveFeedbackUrl(url?: string | null): string | null {
285
+ const value =
286
+ url === undefined ? clientEnv()?.VITE_AGENT_NATIVE_FEEDBACK_URL : url;
287
+ return typeof value === "string" && value.trim() ? value.trim() : null;
288
+ }
289
+
290
+ export function FeedbackButton(props: FeedbackButtonProps) {
291
+ const url = resolveFeedbackUrl(props.url);
292
+ if (!url) return null;
293
+ return <FeedbackPopoverButton {...props} url={url} />;
294
+ }
295
+
296
+ function FeedbackPopoverButton({
271
297
  variant = "sidebar",
272
298
  label,
273
- url = DEFAULT_FEEDBACK_URL,
299
+ url,
274
300
  className,
275
301
  side,
276
302
  align = "end",
@@ -281,7 +307,7 @@ export function FeedbackButton({
281
307
  open: controlledOpen,
282
308
  onOpenChange,
283
309
  trigger: customTrigger,
284
- }: FeedbackButtonProps) {
310
+ }: Omit<FeedbackButtonProps, "url"> & { url: string }) {
285
311
  const target = parseTarget(url);
286
312
  const { session } = useSession();
287
313
  const localeContext = useOptionalLocale();
@@ -53,7 +53,6 @@ import {
53
53
  TooltipTrigger,
54
54
  } from "./components/ui/tooltip.js";
55
55
  import { isTrustedFrameMessage } from "./frame.js";
56
- import { KeepTabOpenNotice } from "./KeepTabOpenNotice.js";
57
56
  import { RunStuckBanner } from "./RunStuckBanner.js";
58
57
  import { callAction } from "./use-action.js";
59
58
  import { useChangeVersion } from "./use-change-version.js";
@@ -703,7 +702,7 @@ export type MultiTabAssistantChatProps = Omit<
703
702
  showTabBar?: boolean;
704
703
  /** Optional custom single-row header renderer */
705
704
  renderHeader?: (props: MultiTabAssistantChatHeaderProps) => React.ReactNode;
706
- /** Optional overlay actions renderer for the active tab */
705
+ /** Optional page-level top-bar actions renderer for the active tab. */
707
706
  renderOverlay?: (props: MultiTabAssistantChatHeaderProps) => React.ReactNode;
708
707
  /** Hide the chat content while keeping the header visible. Used when CLI/resources mode is active. */
709
708
  contentHidden?: boolean;
@@ -2442,7 +2441,11 @@ export function MultiTabAssistantChat({
2442
2441
 
2443
2442
  {/* Chat content with optional overlay */}
2444
2443
  <div
2445
- className="relative flex-1 flex flex-col min-h-0"
2444
+ className={cn(
2445
+ "relative flex-1 flex flex-col min-h-0",
2446
+ renderOverlay && "pt-14",
2447
+ )}
2448
+ data-agent-page-chat-topbar={renderOverlay ? "" : undefined}
2446
2449
  data-agent-page-chat-scrolled={
2447
2450
  renderOverlay && pageOverlayScrolled ? "" : undefined
2448
2451
  }
@@ -2494,11 +2497,6 @@ export function MultiTabAssistantChat({
2494
2497
  contentHidden || tabId !== activeThreadId ? "none" : "flex",
2495
2498
  }}
2496
2499
  >
2497
- <KeepTabOpenNotice
2498
- threadId={tabId}
2499
- enabled={tabId === activeThreadId}
2500
- apiUrl={apiUrl}
2501
- />
2502
2500
  <RunStuckBanner
2503
2501
  threadId={tabId}
2504
2502
  enabled={tabId === activeThreadId}
@@ -23,6 +23,7 @@ import { agentNativePath } from "./api-path.js";
23
23
  import { formatChatErrorText, normalizeChatError } from "./error-format.js";
24
24
  import {
25
25
  AgentAutoContinueSignal,
26
+ appendMissingFinalResponseWarning,
26
27
  type AgentActivityTrailEntry,
27
28
  type AgentAutoContinueErrorInfo,
28
29
  type ContentPart,
@@ -2321,14 +2322,22 @@ export function createAgentChatAdapter(
2321
2322
 
2322
2323
  if (status === "completed") {
2323
2324
  // The turn finished server-side; the events we managed to fold are
2324
- // the durable transcript. Finalize with them.
2325
+ // the durable transcript. Never turn a terminal tool-only chunk
2326
+ // into a blank successful message when no explicit `done` event
2327
+ // passed through the normal SSE finalizer.
2325
2328
  settleInterruptedToolCalls(content, undefined, {
2326
2329
  includeActivity: true,
2327
2330
  });
2331
+ const runWarning = appendMissingFinalResponseWarning(content);
2328
2332
  yield {
2329
2333
  content: [...content],
2330
2334
  status: { type: "complete" as const, reason: "stop" as const },
2331
- metadata: { custom: { ...(runId ? { runId } : {}) } },
2335
+ metadata: {
2336
+ custom: {
2337
+ ...(runId ? { runId } : {}),
2338
+ ...(runWarning ? { runWarning } : {}),
2339
+ },
2340
+ },
2332
2341
  } as ChatModelRunResult;
2333
2342
  clearActiveRun();
2334
2343
  return;