@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
@@ -46,8 +46,14 @@ const PLAIN_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
46
46
  export async function pgTableExists(
47
47
  table: string,
48
48
  injectedClient?: DbExec,
49
+ dialectIsPostgres?: boolean,
49
50
  ): Promise<boolean> {
50
- if (!isPostgres() || !PLAIN_IDENTIFIER.test(table)) return false;
51
+ // The dialect override travels with an injected client: a multi-app process
52
+ // (the hosted Realtime Gateway) probes a per-app Postgres DB even when its
53
+ // own process-global DB is absent or SQLite.
54
+ if (!(dialectIsPostgres ?? isPostgres()) || !PLAIN_IDENTIFIER.test(table)) {
55
+ return false;
56
+ }
51
57
  const client = injectedClient ?? getDbExec();
52
58
  try {
53
59
  const { rows } = await client.execute({
@@ -106,8 +112,14 @@ export async function pgColumnExists(
106
112
  export async function pgIndexExists(
107
113
  indexName: string,
108
114
  injectedClient?: DbExec,
115
+ dialectIsPostgres?: boolean,
109
116
  ): Promise<boolean> {
110
- if (!isPostgres() || !PLAIN_IDENTIFIER.test(indexName)) return false;
117
+ if (
118
+ !(dialectIsPostgres ?? isPostgres()) ||
119
+ !PLAIN_IDENTIFIER.test(indexName)
120
+ ) {
121
+ return false;
122
+ }
111
123
  const client = injectedClient ?? getDbExec();
112
124
  try {
113
125
  const { rows } = await client.execute({
@@ -158,10 +170,17 @@ export async function ensureSchemaObject(options: {
158
170
  lockTimeout?: string;
159
171
  /** Injectable client for tests. */
160
172
  injectedClient?: DbExec;
173
+ /** Dialect override for injected per-app clients; defaults to the global. */
174
+ dialectIsPostgres?: boolean;
161
175
  }): Promise<boolean> {
162
- const { probe, ddl, label, lockTimeout, injectedClient } = options;
176
+ const { probe, ddl, label, lockTimeout, injectedClient, dialectIsPostgres } =
177
+ options;
163
178
  if (await probe()) return false;
164
- const ran = await runGuardedDdl(ddl, { lockTimeout, injectedClient });
179
+ const ran = await runGuardedDdl(ddl, {
180
+ lockTimeout,
181
+ injectedClient,
182
+ dialectIsPostgres,
183
+ });
165
184
  if (ran) return true;
166
185
  // The DDL was swallowed by a lock-timeout. The object is virtually always
167
186
  // already correct by the time a contended boot retries (a concurrent
@@ -185,14 +204,20 @@ export async function ensureSchemaObject(options: {
185
204
  export async function ensureTableExists(
186
205
  table: string,
187
206
  createSql: string,
188
- options: { lockTimeout?: string; injectedClient?: DbExec } = {},
207
+ options: {
208
+ lockTimeout?: string;
209
+ injectedClient?: DbExec;
210
+ dialectIsPostgres?: boolean;
211
+ } = {},
189
212
  ): Promise<boolean> {
190
213
  return ensureSchemaObject({
191
- probe: () => pgTableExists(table, options.injectedClient),
214
+ probe: () =>
215
+ pgTableExists(table, options.injectedClient, options.dialectIsPostgres),
192
216
  ddl: createSql,
193
217
  label: `table ${table}`,
194
218
  lockTimeout: options.lockTimeout,
195
219
  injectedClient: options.injectedClient,
220
+ dialectIsPostgres: options.dialectIsPostgres,
196
221
  });
197
222
  }
198
223
 
@@ -222,14 +247,24 @@ export async function ensureColumnExists(
222
247
  export async function ensureIndexExists(
223
248
  indexName: string,
224
249
  createIndexSql: string,
225
- options: { lockTimeout?: string; injectedClient?: DbExec } = {},
250
+ options: {
251
+ lockTimeout?: string;
252
+ injectedClient?: DbExec;
253
+ dialectIsPostgres?: boolean;
254
+ } = {},
226
255
  ): Promise<boolean> {
227
256
  return ensureSchemaObject({
228
- probe: () => pgIndexExists(indexName, options.injectedClient),
257
+ probe: () =>
258
+ pgIndexExists(
259
+ indexName,
260
+ options.injectedClient,
261
+ options.dialectIsPostgres,
262
+ ),
229
263
  ddl: createIndexSql,
230
264
  label: `index ${indexName}`,
231
265
  lockTimeout: options.lockTimeout,
232
266
  injectedClient: options.injectedClient,
267
+ dialectIsPostgres: options.dialectIsPostgres,
233
268
  });
234
269
  }
235
270
 
@@ -263,10 +298,14 @@ export function isLockTimeoutError(err: unknown): boolean {
263
298
  */
264
299
  export async function runGuardedDdl(
265
300
  ddl: string,
266
- options: { lockTimeout?: string; injectedClient?: DbExec } = {},
301
+ options: {
302
+ lockTimeout?: string;
303
+ injectedClient?: DbExec;
304
+ dialectIsPostgres?: boolean;
305
+ } = {},
267
306
  ): Promise<boolean> {
268
307
  const client = options.injectedClient ?? getDbExec();
269
- if (!isPostgres()) {
308
+ if (!(options.dialectIsPostgres ?? isPostgres())) {
270
309
  await client.execute(ddl);
271
310
  return true;
272
311
  }
@@ -951,6 +951,26 @@ function getSentryClientConfigScript() {
951
951
  );
952
952
  }
953
953
 
954
+ function getRealtimeClientConfigScript() {
955
+ // MUST stay byte-for-byte consistent with resolveRealtimeClientConfig in
956
+ // server/sentry-config.ts (worker bundles a string copy; it can't import it).
957
+ // Fail closed: require BOTH hosted transport AND an explicit gateway URL — no
958
+ // production default, since this ships into the CDN-cached shell.
959
+ const env = globalThis.process?.env || {};
960
+ if (firstNonEmpty(env.AGENT_NATIVE_REALTIME_TRANSPORT) !== "hosted") {
961
+ return null;
962
+ }
963
+ const gatewayBaseUrl = firstNonEmpty(env.AGENT_NATIVE_REALTIME_GATEWAY_URL);
964
+ if (!gatewayBaseUrl) return null;
965
+ const config = { realtime: { transport: "hosted", gatewayBaseUrl } };
966
+ return (
967
+ '<script data-agent-native-realtime-config>' +
968
+ 'window.__AGENT_NATIVE_CONFIG__=Object.assign({},window.__AGENT_NATIVE_CONFIG__,' +
969
+ JSON.stringify(config) +
970
+ ");</script>"
971
+ );
972
+ }
973
+
954
974
  function injectHeadScript(html, script) {
955
975
  if (!script) return html;
956
976
  const headCloseIdx = html.indexOf("</head>");
@@ -1102,7 +1122,10 @@ function applyImmutableAssetCacheHeaders(response, request) {
1102
1122
  }
1103
1123
 
1104
1124
  async function rewriteMountedResponse(response, basePath, pathname, request) {
1105
- const sentryClientConfigScript = getSentryClientConfigScript();
1125
+ const clientConfigScript =
1126
+ [getSentryClientConfigScript(), getRealtimeClientConfigScript()]
1127
+ .filter(Boolean)
1128
+ .join("") || null;
1106
1129
  const headers = new Headers(response.headers);
1107
1130
  applyDefaultSsrCacheHeader(headers, response.status, pathname);
1108
1131
  applyDefaultSpeculationRulesHeader(headers, response.status, basePath);
@@ -1129,7 +1152,7 @@ async function rewriteMountedResponse(response, basePath, pathname, request) {
1129
1152
  prefixMountedHtml(html, basePath),
1130
1153
  defaultSocialImageUrl(request, basePath),
1131
1154
  ),
1132
- sentryClientConfigScript,
1155
+ clientConfigScript,
1133
1156
  ),
1134
1157
  {
1135
1158
  status: response.status,
@@ -18,17 +18,49 @@ import { createElement, type ComponentType, type ReactElement } from "react";
18
18
  export * from "@agent-native/core/client/resources/runtime";
19
19
 
20
20
  function preset(id: string): DefaultMcpIntegration {
21
- return {
22
- ...RUNTIME_DEFAULT_MCP_INTEGRATIONS.find(
23
- (integration) => integration.id === id,
24
- )!,
25
- };
21
+ const runtimePreset = RUNTIME_DEFAULT_MCP_INTEGRATIONS.find(
22
+ (integration) => integration.id === id,
23
+ );
24
+ if (runtimePreset) return { ...runtimePreset };
25
+
26
+ if (id === "granola") {
27
+ return {
28
+ id: "granola",
29
+ name: "Granola",
30
+ provider: "granola",
31
+ description: "Search meeting notes, transcripts, and action items.",
32
+ descriptionKey: "mcpIntegrations.catalog.granola.description",
33
+ useCase:
34
+ "meeting notes, recordings, transcripts, action items, follow-ups",
35
+ useCaseKey: "mcpIntegrations.catalog.granola.useCase",
36
+ url: "https://mcp.granola.ai/mcp",
37
+ authMode: "oauth",
38
+ connectionMode: "oauth",
39
+ availability: "ready",
40
+ verification: "preflight-only",
41
+ logoUrl: "",
42
+ docsUrl: "https://docs.granola.ai/help-center/sharing/integrations/mcp",
43
+ setupNoteKey: "mcpIntegrations.catalog.granola.setupNote",
44
+ keywords: [
45
+ "meetings",
46
+ "meeting notes",
47
+ "recordings",
48
+ "transcripts",
49
+ "action items",
50
+ "follow-ups",
51
+ "decisions",
52
+ ],
53
+ };
54
+ }
55
+
56
+ throw new Error(`MCP preset ${id} is missing from the runtime catalog.`);
26
57
  }
27
58
 
28
59
  export const DEFAULT_MCP_INTEGRATIONS: DefaultMcpIntegration[] = [
29
60
  preset("context7"),
30
61
  preset("sentry"),
31
62
  preset("notion"),
63
+ preset("granola"),
32
64
  preset("semgrep"),
33
65
  preset("linear"),
34
66
  preset("atlassian"),
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Require generated apps to choose how collaboration events are scoped.
3
+ * Legacy `resourceType` callers remain valid during the access-option
4
+ * migration; this guard only reports implicit createCollabPlugin configs.
5
+ */
6
+
7
+ import {
8
+ lineColForOffset,
9
+ readFileSafe,
10
+ relPosix,
11
+ walk,
12
+ } from "./scan-utils.js";
13
+ import type { GuardFinding, GuardResult, GuardScanOptions } from "./types.js";
14
+
15
+ const SOURCE_FILE = /\.(?:[cm]?[jt]s|[jt]sx)$/;
16
+ const CALL = /\bcreateCollabPlugin\s*\(/g;
17
+ const EXPLICIT_ACCESS_KEYS = new Set(["access", "resourceType"]);
18
+ const FINDING_MESSAGE =
19
+ 'createCollabPlugin must declare access explicitly. Use access: { mode: "resource", resourceType: "..." } for scoped resources or access: { mode: "all-authenticated" } when deployment-wide delivery is intentional. Legacy resourceType is also accepted during migration.';
20
+
21
+ function maskCommentsAndStrings(contents: string): string {
22
+ const masked = contents.split("");
23
+ for (let i = 0; i < contents.length; i++) {
24
+ const char = contents[i];
25
+ if (char === '"' || char === "'" || char === "`") {
26
+ const end = skipQuoted(contents, i);
27
+ for (let cursor = i; cursor < end; cursor++) {
28
+ if (masked[cursor] !== "\n") masked[cursor] = " ";
29
+ }
30
+ i = end - 1;
31
+ continue;
32
+ }
33
+ if (contents.startsWith("//", i)) {
34
+ const newline = contents.indexOf("\n", i + 2);
35
+ const end = newline === -1 ? contents.length : newline;
36
+ for (let cursor = i; cursor < end; cursor++) masked[cursor] = " ";
37
+ i = end - 1;
38
+ continue;
39
+ }
40
+ if (contents.startsWith("/*", i)) {
41
+ const commentEnd = contents.indexOf("*/", i + 2);
42
+ const end = commentEnd === -1 ? contents.length : commentEnd + 2;
43
+ for (let cursor = i; cursor < end; cursor++) {
44
+ if (masked[cursor] !== "\n") masked[cursor] = " ";
45
+ }
46
+ i = end - 1;
47
+ }
48
+ }
49
+ return masked.join("");
50
+ }
51
+
52
+ function skipQuoted(contents: string, start: number): number {
53
+ const quote = contents[start];
54
+ let escaped = false;
55
+ for (let i = start + 1; i < contents.length; i++) {
56
+ const char = contents[i];
57
+ if (escaped) {
58
+ escaped = false;
59
+ } else if (char === "\\") {
60
+ escaped = true;
61
+ } else if (char === quote) {
62
+ return i + 1;
63
+ }
64
+ }
65
+ return contents.length;
66
+ }
67
+
68
+ function skipTrivia(contents: string, start: number): number {
69
+ let i = start;
70
+ while (i < contents.length) {
71
+ if (/\s/.test(contents[i] ?? "")) {
72
+ i++;
73
+ continue;
74
+ }
75
+ if (contents.startsWith("//", i)) {
76
+ const newline = contents.indexOf("\n", i + 2);
77
+ i = newline === -1 ? contents.length : newline + 1;
78
+ continue;
79
+ }
80
+ if (contents.startsWith("/*", i)) {
81
+ const end = contents.indexOf("*/", i + 2);
82
+ i = end === -1 ? contents.length : end + 2;
83
+ continue;
84
+ }
85
+ break;
86
+ }
87
+ return i;
88
+ }
89
+
90
+ function findObjectEnd(contents: string, start: number): number | null {
91
+ let depth = 0;
92
+ for (let i = start; i < contents.length; i++) {
93
+ const char = contents[i];
94
+ if (char === '"' || char === "'" || char === "`") {
95
+ i = skipQuoted(contents, i) - 1;
96
+ continue;
97
+ }
98
+ if (contents.startsWith("//", i)) {
99
+ const newline = contents.indexOf("\n", i + 2);
100
+ i = newline === -1 ? contents.length : newline;
101
+ continue;
102
+ }
103
+ if (contents.startsWith("/*", i)) {
104
+ const end = contents.indexOf("*/", i + 2);
105
+ i = end === -1 ? contents.length : end + 1;
106
+ continue;
107
+ }
108
+ if (char === "{") depth++;
109
+ if (char === "}" && --depth === 0) return i;
110
+ }
111
+ return null;
112
+ }
113
+
114
+ function hasExplicitAccessProperty(
115
+ contents: string,
116
+ objectStart: number,
117
+ objectEnd: number,
118
+ ): boolean {
119
+ let braceDepth = 0;
120
+ let bracketDepth = 0;
121
+ let parenDepth = 0;
122
+ let expectingProperty = true;
123
+
124
+ for (let i = objectStart + 1; i < objectEnd; i++) {
125
+ i = skipTrivia(contents, i);
126
+ if (i >= objectEnd) break;
127
+ const char = contents[i];
128
+
129
+ if (expectingProperty && (char === '"' || char === "'")) {
130
+ const tokenEnd = skipQuoted(contents, i);
131
+ const key = contents.slice(i + 1, tokenEnd - 1);
132
+ const afterKey = skipTrivia(contents, tokenEnd);
133
+ if (EXPLICIT_ACCESS_KEYS.has(key) && contents[afterKey] === ":") {
134
+ return true;
135
+ }
136
+ i = tokenEnd - 1;
137
+ expectingProperty = false;
138
+ continue;
139
+ }
140
+
141
+ if (expectingProperty && /[A-Za-z_$]/.test(char ?? "")) {
142
+ let tokenEnd = i + 1;
143
+ while (/[A-Za-z0-9_$]/.test(contents[tokenEnd] ?? "")) tokenEnd++;
144
+ const key = contents.slice(i, tokenEnd);
145
+ const afterKey = skipTrivia(contents, tokenEnd);
146
+ const delimiter = contents[afterKey];
147
+ if (
148
+ EXPLICIT_ACCESS_KEYS.has(key) &&
149
+ (delimiter === ":" || delimiter === "," || afterKey >= objectEnd)
150
+ ) {
151
+ return true;
152
+ }
153
+ i = tokenEnd - 1;
154
+ expectingProperty = false;
155
+ continue;
156
+ }
157
+
158
+ if (char === '"' || char === "'" || char === "`") {
159
+ i = skipQuoted(contents, i) - 1;
160
+ continue;
161
+ }
162
+ if (contents.startsWith("//", i) || contents.startsWith("/*", i)) {
163
+ i = skipTrivia(contents, i) - 1;
164
+ continue;
165
+ }
166
+
167
+ if (char === "{") braceDepth++;
168
+ else if (char === "}") braceDepth--;
169
+ else if (char === "[") bracketDepth++;
170
+ else if (char === "]") bracketDepth--;
171
+ else if (char === "(") parenDepth++;
172
+ else if (char === ")") parenDepth--;
173
+ else if (
174
+ char === "," &&
175
+ braceDepth === 0 &&
176
+ bracketDepth === 0 &&
177
+ parenDepth === 0
178
+ ) {
179
+ expectingProperty = true;
180
+ }
181
+ }
182
+
183
+ return false;
184
+ }
185
+
186
+ export function scanExplicitCollabAccess(
187
+ options: GuardScanOptions,
188
+ ): GuardResult {
189
+ const { root } = options;
190
+ const findings: GuardFinding[] = [];
191
+
192
+ for (const file of walk(root)) {
193
+ if (!SOURCE_FILE.test(file) || file.endsWith(".d.ts")) continue;
194
+ const contents = readFileSafe(file);
195
+ if (contents === null || !contents.includes("createCollabPlugin")) continue;
196
+ const searchable = maskCommentsAndStrings(contents);
197
+
198
+ CALL.lastIndex = 0;
199
+ let match: RegExpExecArray | null;
200
+ while ((match = CALL.exec(searchable)) !== null) {
201
+ const callStart = match.index;
202
+ const objectStart = skipTrivia(contents, CALL.lastIndex);
203
+ if (contents[objectStart] !== "{") {
204
+ if (contents[objectStart] === ")") {
205
+ const { line } = lineColForOffset(contents, callStart);
206
+ findings.push({
207
+ file: relPosix(root, file),
208
+ line,
209
+ message: FINDING_MESSAGE,
210
+ });
211
+ }
212
+ continue;
213
+ }
214
+ const objectEnd = findObjectEnd(contents, objectStart);
215
+ if (objectEnd === null) continue;
216
+ CALL.lastIndex = objectEnd + 1;
217
+
218
+ if (hasExplicitAccessProperty(contents, objectStart, objectEnd)) continue;
219
+ const { line } = lineColForOffset(contents, callStart);
220
+ findings.push({
221
+ file: relPosix(root, file),
222
+ line,
223
+ message: FINDING_MESSAGE,
224
+ });
225
+ }
226
+ }
227
+
228
+ return { name: "explicit-collab-access", findings };
229
+ }
@@ -12,6 +12,7 @@
12
12
 
13
13
  export { scanDbToolScoping } from "./db-tool-scoping.js";
14
14
  export type { DbToolScopingOptions } from "./db-tool-scoping.js";
15
+ export { scanExplicitCollabAccess } from "./explicit-collab-access.js";
15
16
  export { scanDrizzlePush } from "./no-drizzle-push.js";
16
17
  export { scanEnvCredentials } from "./no-env-credentials.js";
17
18
  export { scanEnvMutation } from "./no-env-mutation.js";
@@ -33,6 +33,47 @@ const messages = {
33
33
  openResourceSettings: "Open resource settings",
34
34
  backHome: "Back to home",
35
35
  },
36
+ agentResources: {
37
+ openDocs: "Open {{section}} documentation",
38
+ backToResources: "Back to agent resources",
39
+ createFile: {
40
+ nameLabel: "File name",
41
+ namePlaceholder: "notes/ideas",
42
+ menuDescription: "Add a new file by name",
43
+ },
44
+ files: {
45
+ title: "Files",
46
+ description: "Files the agent can read and write.",
47
+ },
48
+ instructions: {
49
+ title: "Instructions",
50
+ description:
51
+ "The rules, preferences, and project guidance that steer the agent.",
52
+ },
53
+ agents: {
54
+ title: "Agents",
55
+ description:
56
+ "Reusable profiles for focused sub-agents and delegated work.",
57
+ },
58
+ memory: {
59
+ title: "Memory",
60
+ description: "Durable notes the agent can retrieve across conversations.",
61
+ },
62
+ skills: {
63
+ title: "Skills",
64
+ description:
65
+ "Specialized instructions that give the agent repeatable abilities.",
66
+ },
67
+ learnings: {
68
+ title: "Learnings",
69
+ description:
70
+ "Corrections and patterns worth carrying forward for future work.",
71
+ },
72
+ remoteAgents: {
73
+ title: "Remote agents",
74
+ description: "Other agents this agent can call through A2A.",
75
+ },
76
+ },
36
77
  featureFlags: {
37
78
  title: "Feature flags",
38
79
  description: "Control staged capabilities without changing a deployment.",
@@ -276,7 +317,7 @@ const messages = {
276
317
  checkingAiConnection: "Checking AI connection...",
277
318
  voiceMode: {
278
319
  entryButtonLabel: "Use microphone",
279
- promptTitle: "Talk to your app",
320
+ promptTitle: "Use your voice",
280
321
  promptDescription:
281
322
  "Voice mode keeps listening while the agent navigates and takes actions.",
282
323
  setupTitle: "Set up voice mode",
@@ -285,8 +326,9 @@ const messages = {
285
326
  connectBuilder: "Connect Builder.io",
286
327
  useOpenAiKey: "Add your own keys",
287
328
  startWithOpenAiKey: "Start with OpenAI key",
288
- start: "Start voice mode",
289
- keepDictating: "Keep dictating",
329
+ start: "Real-time voice",
330
+ keepDictating: "Dictate",
331
+ rememberPreference: "Remember my preference",
290
332
  showChat: "Show chat",
291
333
  hideChat: "Hide chat",
292
334
  end: "End voice mode",
@@ -744,9 +786,9 @@ const messages = {
744
786
  connect: "Connect",
745
787
  connectWithOAuth: "Connect with OAuth",
746
788
  useApiToken: "Use API token",
747
- connectSuggestion: "Connect {{name}} to use this link in chat",
789
+ connectSuggestion: "Connect {{name}} to use it in chat",
748
790
  connectSuggestionWithApiToken:
749
- "Connect {{name}} with an API token to use this link in chat",
791
+ "Connect {{name}} with an API token to use it in chat",
750
792
  dismissSuggestion: "Dismiss integration suggestion",
751
793
  backToIntegrations: "Back to integrations",
752
794
  customTitle: "Add custom MCP server",
@@ -795,6 +837,13 @@ const messages = {
795
837
  setupNote:
796
838
  "Notion MCP uses user OAuth. Enterprise workspaces can audit MCP usage and allow or block clients; reconnect after admin policy changes.",
797
839
  },
840
+ granola: {
841
+ description: "Search meeting notes, transcripts, and action items.",
842
+ useCase:
843
+ "Meeting notes, recordings, transcripts, action items, follow-ups",
844
+ setupNote:
845
+ "Granola MCP uses browser OAuth. Authorize the signed-in Granola account and review which meeting notes and transcripts the agent can access.",
846
+ },
798
847
  semgrep: {
799
848
  description: "Scan code for security findings.",
800
849
  useCase: "Security scanning, vulnerability detection, code analysis",