@agent-native/core 0.115.4 → 0.116.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (408) hide show
  1. package/agent-native.eject.json +1 -0
  2. package/corpus/README.md +3 -3
  3. package/corpus/core/CHANGELOG.md +28 -0
  4. package/corpus/core/agent-native.eject.json +1 -0
  5. package/corpus/core/docs/AGENTS.md +1 -1
  6. package/corpus/core/docs/content/agent-mentions.mdx +2 -2
  7. package/corpus/core/docs/content/{workspace.mdx → agent-resources.mdx} +1 -7
  8. package/corpus/core/docs/content/agent-teams.mdx +4 -4
  9. package/corpus/core/docs/content/dispatch.mdx +10 -10
  10. package/corpus/core/docs/content/drop-in-agent.mdx +4 -4
  11. package/corpus/core/docs/content/external-agents.mdx +1 -1
  12. package/corpus/core/docs/content/frames.mdx +1 -1
  13. package/corpus/core/docs/content/integrations.mdx +13 -2
  14. package/corpus/core/docs/content/key-concepts.mdx +2 -2
  15. package/corpus/core/docs/content/mcp-clients.mdx +7 -1
  16. package/corpus/core/docs/content/multi-app-workspace.mdx +3 -3
  17. package/corpus/core/docs/content/real-time-collaboration.mdx +33 -15
  18. package/corpus/core/docs/content/recurring-jobs.mdx +7 -7
  19. package/corpus/core/docs/content/skills-guide.mdx +4 -4
  20. package/corpus/core/docs/content/template-brain.mdx +1 -1
  21. package/corpus/core/docs/content/toolkit-collaboration.mdx +1 -1
  22. package/corpus/core/docs/content/using-your-agent.mdx +1 -1
  23. package/corpus/core/docs/content/what-is-agent-native.mdx +4 -4
  24. package/corpus/core/docs/content/workspace-management.mdx +4 -4
  25. package/corpus/core/package.json +1 -1
  26. package/corpus/core/src/agent/production-agent.ts +13 -3
  27. package/corpus/core/src/cli/doctor.ts +6 -1
  28. package/corpus/core/src/client/AgentPanel.tsx +79 -41
  29. package/corpus/core/src/client/AssistantChat.tsx +71 -25
  30. package/corpus/core/src/client/FeedbackButton.tsx +33 -7
  31. package/corpus/core/src/client/MultiTabAssistantChat.tsx +6 -8
  32. package/corpus/core/src/client/agent-chat-adapter.ts +11 -2
  33. package/corpus/core/src/client/agent-page/AgentTabFrame.tsx +22 -3
  34. package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +34 -19
  35. package/corpus/core/src/client/chat/message-components.tsx +43 -16
  36. package/corpus/core/src/client/chat/tool-call-display.tsx +30 -18
  37. package/corpus/core/src/client/chat/tool-render-registry.tsx +2 -0
  38. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +19 -2
  39. package/corpus/core/src/client/resources/ResourceTree.tsx +7 -10
  40. package/corpus/core/src/client/resources/ResourcesPanel.tsx +33 -70
  41. package/corpus/core/src/client/resources/mcp-connection-resume.ts +107 -0
  42. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +65 -12
  43. package/corpus/core/src/client/resources/mcp-integration-logos.ts +4 -0
  44. package/corpus/core/src/client/sse-event-processor.ts +50 -14
  45. package/corpus/core/src/client/use-db-sync.ts +16 -6
  46. package/corpus/core/src/connections/catalog.ts +7 -1
  47. package/corpus/core/src/eject/remote-mcp-presets.ts +37 -5
  48. package/corpus/core/src/guards/explicit-collab-access.ts +229 -0
  49. package/corpus/core/src/guards/index.ts +1 -0
  50. package/corpus/core/src/localization/default-messages.ts +54 -5
  51. package/corpus/core/src/mcp/connect-route.ts +34 -51
  52. package/corpus/core/src/provider-api/index.ts +1 -1
  53. package/corpus/core/src/server/collab-plugin.ts +137 -18
  54. package/corpus/core/src/server/index.ts +2 -0
  55. package/corpus/core/src/styles/agent-native.css +40 -0
  56. package/corpus/core/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  57. package/corpus/core/src/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
  58. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  59. package/corpus/core/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  60. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  61. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
  62. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  63. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
  64. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  65. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
  66. package/corpus/templates/analytics/AGENTS.md +7 -2
  67. package/corpus/templates/analytics/actions/export-dashboard-panel-to-google-sheet.ts +144 -0
  68. package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -88
  69. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +34 -37
  70. package/corpus/templates/analytics/app/global.css +0 -4
  71. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +2 -7
  72. package/corpus/templates/analytics/app/i18n-data.ts +107 -0
  73. package/corpus/templates/analytics/app/lib/data-source-status.ts +9 -0
  74. package/corpus/templates/analytics/app/lib/sql-query.ts +1 -2
  75. package/corpus/templates/analytics/app/pages/Ask.tsx +2 -7
  76. package/corpus/templates/analytics/app/pages/DataSources.tsx +48 -0
  77. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +59 -0
  78. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -0
  79. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-panel-window.ts +3 -1
  80. package/corpus/templates/analytics/changelog/2026-07-22-clear-background-chat-progress.md +6 -0
  81. package/corpus/templates/analytics/changelog/2026-07-22-daily-dashboard-email-query-batches.md +6 -0
  82. package/corpus/templates/analytics/changelog/2026-07-22-export-table-panels-directly-to-google-sheets.md +6 -0
  83. package/corpus/templates/analytics/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  84. package/corpus/templates/analytics/changelog/2026-07-22-recent-chats-can-expand-in-the-sidebar.md +6 -0
  85. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +8 -8
  86. package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +31 -0
  87. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +3 -5
  88. package/corpus/templates/analytics/server/lib/dashboard-report.ts +12 -0
  89. package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +3 -5
  90. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +150 -21
  91. package/corpus/templates/analytics/server/lib/google-sheets-export.ts +188 -0
  92. package/corpus/templates/analytics/server/lib/provider-api.ts +7 -2
  93. package/corpus/templates/analytics/server/plugins/collab.ts +6 -3
  94. package/corpus/templates/analytics/shared/sql-query-limits.ts +1 -0
  95. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  96. package/corpus/templates/assets/.agents/skills/real-time-collab/SKILL.md +35 -13
  97. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
  98. package/corpus/templates/assets/app/components/layout/Layout.tsx +1 -1
  99. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +54 -62
  100. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -6
  101. package/corpus/templates/assets/app/routes/_index.tsx +8 -5
  102. package/corpus/templates/assets/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  103. package/corpus/templates/assets/changelog/2026-07-22-recent-chats-expand-from-a-compact-list.md +6 -0
  104. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  105. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
  106. package/corpus/templates/brain/actions/rotate-source-ingest-token.ts +77 -0
  107. package/corpus/templates/brain/app/components/layout/Layout.tsx +5 -1
  108. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +38 -51
  109. package/corpus/templates/brain/app/hooks/use-navigation-state.ts +2 -9
  110. package/corpus/templates/brain/app/i18n-data.ts +120 -0
  111. package/corpus/templates/brain/app/routes/sources.tsx +156 -5
  112. package/corpus/templates/brain/changelog/2026-07-22-chat-runs-always-end-with-an-answer.md +6 -0
  113. package/corpus/templates/brain/changelog/2026-07-22-clear-background-chat-progress.md +6 -0
  114. package/corpus/templates/brain/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  115. package/corpus/templates/brain/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  116. package/corpus/templates/brain/changelog/2026-07-22-long-chat-titles-stay-inside-the-sidebar.md +6 -0
  117. package/corpus/templates/brain/changelog/2026-07-22-new-clips-and-webhook-sources-now-show-their-secure-connecti.md +6 -0
  118. package/corpus/templates/brain/jobs/emit-netlify-brain-queue-cron.ts +125 -0
  119. package/corpus/templates/brain/netlify.toml +5 -1
  120. package/corpus/templates/brain/scripts/configure-prod-clips-source.ts +50 -0
  121. package/corpus/templates/brain/server/lib/capture-sanitization.ts +64 -6
  122. package/corpus/templates/brain/server/plugins/agent-chat.ts +4 -0
  123. package/corpus/templates/brain/server/plugins/brain-jobs.ts +1 -0
  124. package/corpus/templates/brain/server/routes/api/brain/queue/run.post.ts +55 -0
  125. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  126. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
  127. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  128. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  129. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -0
  130. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +43 -67
  131. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +2 -7
  132. package/corpus/templates/chat/app/routes/_index.tsx +8 -5
  133. package/corpus/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  134. package/corpus/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  135. package/corpus/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  136. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  137. package/corpus/templates/clips/AGENTS.md +9 -1
  138. package/corpus/templates/clips/actions/export-to-brain.ts +82 -6
  139. package/corpus/templates/clips/actions/request-transcript.ts +25 -14
  140. package/corpus/templates/clips/changelog/2026-07-22-clips-transcripts-now-retry-brain-export.md +5 -0
  141. package/corpus/templates/clips/changelog/2026-07-22-german-umlauts-and-other-non-ascii-characters-now-paste-corr.md +6 -0
  142. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +26 -3
  143. package/corpus/templates/clips/jobs/emit-netlify-brain-export-cron.ts +118 -0
  144. package/corpus/templates/clips/netlify.toml +4 -1
  145. package/corpus/templates/clips/scripts/configure-prod-brain-export.ts +92 -0
  146. package/corpus/templates/clips/server/jobs/brain-export.ts +182 -0
  147. package/corpus/templates/clips/server/lib/brain-export-state.ts +42 -0
  148. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +5 -1
  149. package/corpus/templates/clips/server/plugins/calendar-jobs.ts +2 -0
  150. package/corpus/templates/clips/server/register-secrets.ts +42 -0
  151. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +10 -1
  152. package/corpus/templates/clips/server/routes/api/clips/brain-export/run.post.ts +45 -0
  153. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  154. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
  155. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +1 -1
  156. package/corpus/templates/content/server/plugins/collab.ts +1 -1
  157. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  158. package/corpus/templates/crm/actions/_crm-data-program-actions.ts +15 -0
  159. package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +2 -0
  160. package/corpus/templates/crm/actions/run.ts +2 -6
  161. package/corpus/templates/crm/actions/update-crm-record.ts +4 -2
  162. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +6 -0
  163. package/corpus/templates/crm/changelog/2026-07-22-crm-field-validation-now-explains-which-fields-cannot-be-edi.md +6 -0
  164. package/corpus/templates/crm/changelog/2026-07-22-fixed-hubspot-contact-syncs-missing-records-updated-after-th.md +6 -0
  165. package/corpus/templates/crm/changelog/2026-07-22-fixed-pipeline-dashboard-panels-so-their-opportunity-data-lo.md +6 -0
  166. package/corpus/templates/crm/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  167. package/corpus/templates/crm/server/crm/hubspot-adapter.ts +4 -1
  168. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  169. package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
  170. package/corpus/templates/design/server/plugins/collab.ts +11 -8
  171. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  172. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  173. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
  174. package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -0
  175. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +1 -1
  176. package/corpus/templates/forms/app/hooks/use-navigation-state.ts +2 -9
  177. package/corpus/templates/forms/app/root.tsx +1 -6
  178. package/corpus/templates/forms/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  179. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  180. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  181. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
  182. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
  183. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  184. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
  185. package/corpus/templates/plan/app/components/layout/Layout.tsx +5 -1
  186. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +57 -72
  187. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +2 -9
  188. package/corpus/templates/plan/app/lib/create-plan-routing.ts +2 -2
  189. package/corpus/templates/plan/app/pages/PlanChatPage.tsx +0 -1
  190. package/corpus/templates/plan/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  191. package/corpus/templates/plan/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  192. package/corpus/templates/plan/changelog/2026-07-22-recent-chats-and-sidebar-controls-are-more-compact.md +6 -0
  193. package/corpus/templates/plan/server/plugins/collab.ts +5 -2
  194. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  195. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +1 -1
  196. package/corpus/templates/slides/server/plugins/collab.ts +11 -8
  197. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  198. package/corpus/templates/tasks/.agents/skills/real-time-sync/SKILL.md +1 -1
  199. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +5 -22
  200. package/corpus/templates/tasks/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  201. package/corpus/toolkit/CHANGELOG.md +7 -0
  202. package/corpus/toolkit/README.md +12 -3
  203. package/corpus/toolkit/package.json +1 -1
  204. package/corpus/toolkit/src/chat-history/ChatHistoryRail.tsx +89 -0
  205. package/corpus/toolkit/src/chat-history/index.ts +5 -0
  206. package/corpus/toolkit/src/chat-history.css +59 -0
  207. package/corpus/toolkit/src/composer/RealtimeVoiceMode.tsx +106 -36
  208. package/corpus/toolkit/src/composer/VoiceButton.tsx +49 -0
  209. package/corpus/toolkit/src/composer/realtime-voice-audio-level.ts +2 -1
  210. package/corpus/toolkit/src/composer/useRealtimeVoiceMode.tsx +5 -3
  211. package/corpus/toolkit/src/styles.css +35 -0
  212. package/dist/agent/production-agent.d.ts.map +1 -1
  213. package/dist/agent/production-agent.js +13 -3
  214. package/dist/agent/production-agent.js.map +1 -1
  215. package/dist/cli/doctor.d.ts +1 -1
  216. package/dist/cli/doctor.d.ts.map +1 -1
  217. package/dist/cli/doctor.js +5 -2
  218. package/dist/cli/doctor.js.map +1 -1
  219. package/dist/client/AgentPanel.d.ts +1 -0
  220. package/dist/client/AgentPanel.d.ts.map +1 -1
  221. package/dist/client/AgentPanel.js +38 -18
  222. package/dist/client/AgentPanel.js.map +1 -1
  223. package/dist/client/AssistantChat.d.ts.map +1 -1
  224. package/dist/client/AssistantChat.js +55 -20
  225. package/dist/client/AssistantChat.js.map +1 -1
  226. package/dist/client/FeedbackButton.d.ts +4 -2
  227. package/dist/client/FeedbackButton.d.ts.map +1 -1
  228. package/dist/client/FeedbackButton.js +18 -2
  229. package/dist/client/FeedbackButton.js.map +1 -1
  230. package/dist/client/MultiTabAssistantChat.d.ts +1 -1
  231. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  232. package/dist/client/MultiTabAssistantChat.js +2 -3
  233. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  234. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  235. package/dist/client/agent-chat-adapter.js +11 -3
  236. package/dist/client/agent-chat-adapter.js.map +1 -1
  237. package/dist/client/agent-page/AgentTabFrame.d.ts +3 -1
  238. package/dist/client/agent-page/AgentTabFrame.d.ts.map +1 -1
  239. package/dist/client/agent-page/AgentTabFrame.js +3 -2
  240. package/dist/client/agent-page/AgentTabFrame.js.map +1 -1
  241. package/dist/client/agent-page/AgentTabsPage.d.ts +2 -0
  242. package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
  243. package/dist/client/agent-page/AgentTabsPage.js +26 -15
  244. package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
  245. package/dist/client/chat/message-components.d.ts +6 -1
  246. package/dist/client/chat/message-components.d.ts.map +1 -1
  247. package/dist/client/chat/message-components.js +17 -11
  248. package/dist/client/chat/message-components.js.map +1 -1
  249. package/dist/client/chat/tool-call-display.d.ts +11 -1
  250. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  251. package/dist/client/chat/tool-call-display.js +16 -17
  252. package/dist/client/chat/tool-call-display.js.map +1 -1
  253. package/dist/client/chat/tool-render-registry.d.ts +2 -0
  254. package/dist/client/chat/tool-render-registry.d.ts.map +1 -1
  255. package/dist/client/chat/tool-render-registry.js.map +1 -1
  256. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
  257. package/dist/client/resources/McpConnectionSuggestion.js +15 -1
  258. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
  259. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  260. package/dist/client/resources/ResourceTree.js +3 -3
  261. package/dist/client/resources/ResourceTree.js.map +1 -1
  262. package/dist/client/resources/ResourcesPanel.d.ts +1 -0
  263. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  264. package/dist/client/resources/ResourcesPanel.js +34 -20
  265. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  266. package/dist/client/resources/mcp-connection-resume.d.ts +11 -0
  267. package/dist/client/resources/mcp-connection-resume.d.ts.map +1 -0
  268. package/dist/client/resources/mcp-connection-resume.js +95 -0
  269. package/dist/client/resources/mcp-connection-resume.js.map +1 -0
  270. package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
  271. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  272. package/dist/client/resources/mcp-integration-catalog.js +63 -8
  273. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  274. package/dist/client/resources/mcp-integration-logos.d.ts.map +1 -1
  275. package/dist/client/resources/mcp-integration-logos.js +4 -0
  276. package/dist/client/resources/mcp-integration-logos.js.map +1 -1
  277. package/dist/client/sse-event-processor.d.ts +5 -0
  278. package/dist/client/sse-event-processor.d.ts.map +1 -1
  279. package/dist/client/sse-event-processor.js +39 -13
  280. package/dist/client/sse-event-processor.js.map +1 -1
  281. package/dist/client/use-db-sync.d.ts +3 -2
  282. package/dist/client/use-db-sync.d.ts.map +1 -1
  283. package/dist/client/use-db-sync.js +17 -6
  284. package/dist/client/use-db-sync.js.map +1 -1
  285. package/dist/collab/routes.d.ts +1 -1
  286. package/dist/connections/catalog.d.ts +1 -1
  287. package/dist/connections/catalog.d.ts.map +1 -1
  288. package/dist/connections/catalog.js +7 -1
  289. package/dist/connections/catalog.js.map +1 -1
  290. package/dist/eject/remote-mcp-presets.d.ts.map +1 -1
  291. package/dist/eject/remote-mcp-presets.js +33 -3
  292. package/dist/eject/remote-mcp-presets.js.map +1 -1
  293. package/dist/guards/explicit-collab-access.d.ts +8 -0
  294. package/dist/guards/explicit-collab-access.d.ts.map +1 -0
  295. package/dist/guards/explicit-collab-access.js +214 -0
  296. package/dist/guards/explicit-collab-access.js.map +1 -0
  297. package/dist/guards/index.d.ts +1 -0
  298. package/dist/guards/index.d.ts.map +1 -1
  299. package/dist/guards/index.js +1 -0
  300. package/dist/guards/index.js.map +1 -1
  301. package/dist/localization/default-messages.d.ts +43 -0
  302. package/dist/localization/default-messages.d.ts.map +1 -1
  303. package/dist/localization/default-messages.js +48 -5
  304. package/dist/localization/default-messages.js.map +1 -1
  305. package/dist/mcp/connect-route.d.ts.map +1 -1
  306. package/dist/mcp/connect-route.js +34 -48
  307. package/dist/mcp/connect-route.js.map +1 -1
  308. package/dist/notifications/routes.d.ts +3 -3
  309. package/dist/observability/routes.d.ts +1 -1
  310. package/dist/progress/routes.d.ts +1 -1
  311. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  312. package/dist/provider-api/actions/provider-api.d.ts +7 -7
  313. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  314. package/dist/provider-api/index.js +1 -1
  315. package/dist/provider-api/index.js.map +1 -1
  316. package/dist/server/collab-plugin.d.ts +34 -3
  317. package/dist/server/collab-plugin.d.ts.map +1 -1
  318. package/dist/server/collab-plugin.js +65 -12
  319. package/dist/server/collab-plugin.js.map +1 -1
  320. package/dist/server/index.d.ts +1 -1
  321. package/dist/server/index.d.ts.map +1 -1
  322. package/dist/server/index.js.map +1 -1
  323. package/dist/styles/agent-native.css +40 -0
  324. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  325. package/dist/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  326. package/dist/templates/chat/app/components/layout/Layout.tsx +1 -0
  327. package/dist/templates/chat/app/components/layout/Sidebar.tsx +43 -67
  328. package/dist/templates/chat/app/hooks/use-navigation-state.ts +2 -7
  329. package/dist/templates/chat/app/routes/_index.tsx +8 -5
  330. package/dist/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  331. package/dist/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  332. package/dist/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  333. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  334. package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
  335. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  336. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  337. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  338. package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
  339. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  340. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
  341. package/docs/AGENTS.md +1 -1
  342. package/docs/content/agent-mentions.mdx +2 -2
  343. package/docs/content/{workspace.mdx → agent-resources.mdx} +1 -7
  344. package/docs/content/agent-teams.mdx +4 -4
  345. package/docs/content/dispatch.mdx +10 -10
  346. package/docs/content/drop-in-agent.mdx +4 -4
  347. package/docs/content/external-agents.mdx +1 -1
  348. package/docs/content/frames.mdx +1 -1
  349. package/docs/content/integrations.mdx +13 -2
  350. package/docs/content/key-concepts.mdx +2 -2
  351. package/docs/content/mcp-clients.mdx +7 -1
  352. package/docs/content/multi-app-workspace.mdx +3 -3
  353. package/docs/content/real-time-collaboration.mdx +33 -15
  354. package/docs/content/recurring-jobs.mdx +7 -7
  355. package/docs/content/skills-guide.mdx +4 -4
  356. package/docs/content/template-brain.mdx +1 -1
  357. package/docs/content/toolkit-collaboration.mdx +1 -1
  358. package/docs/content/using-your-agent.mdx +1 -1
  359. package/docs/content/what-is-agent-native.mdx +4 -4
  360. package/docs/content/workspace-management.mdx +4 -4
  361. package/package.json +3 -3
  362. package/src/agent/production-agent.ts +13 -3
  363. package/src/cli/doctor.ts +6 -1
  364. package/src/client/AgentPanel.tsx +79 -41
  365. package/src/client/AssistantChat.tsx +71 -25
  366. package/src/client/FeedbackButton.tsx +33 -7
  367. package/src/client/MultiTabAssistantChat.tsx +6 -8
  368. package/src/client/agent-chat-adapter.ts +11 -2
  369. package/src/client/agent-page/AgentTabFrame.tsx +22 -3
  370. package/src/client/agent-page/AgentTabsPage.tsx +34 -19
  371. package/src/client/chat/message-components.tsx +43 -16
  372. package/src/client/chat/tool-call-display.tsx +30 -18
  373. package/src/client/chat/tool-render-registry.tsx +2 -0
  374. package/src/client/resources/McpConnectionSuggestion.tsx +19 -2
  375. package/src/client/resources/ResourceTree.tsx +7 -10
  376. package/src/client/resources/ResourcesPanel.tsx +33 -70
  377. package/src/client/resources/mcp-connection-resume.ts +107 -0
  378. package/src/client/resources/mcp-integration-catalog.ts +65 -12
  379. package/src/client/resources/mcp-integration-logos.ts +4 -0
  380. package/src/client/sse-event-processor.ts +50 -14
  381. package/src/client/use-db-sync.ts +16 -6
  382. package/src/connections/catalog.ts +7 -1
  383. package/src/eject/remote-mcp-presets.ts +37 -5
  384. package/src/guards/explicit-collab-access.ts +229 -0
  385. package/src/guards/index.ts +1 -0
  386. package/src/localization/default-messages.ts +54 -5
  387. package/src/mcp/connect-route.ts +34 -51
  388. package/src/provider-api/index.ts +1 -1
  389. package/src/server/collab-plugin.ts +137 -18
  390. package/src/server/index.ts +2 -0
  391. package/src/styles/agent-native.css +40 -0
  392. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  393. package/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  394. package/src/templates/chat/app/components/layout/Layout.tsx +1 -0
  395. package/src/templates/chat/app/components/layout/Sidebar.tsx +43 -67
  396. package/src/templates/chat/app/hooks/use-navigation-state.ts +2 -7
  397. package/src/templates/chat/app/routes/_index.tsx +8 -5
  398. package/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  399. package/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  400. package/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  401. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  402. package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +35 -13
  403. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  404. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  405. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -1
  406. package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +35 -13
  407. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  408. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +12 -8
@@ -0,0 +1,182 @@
1
+ import { getDbExec } from "@agent-native/core/db";
2
+ import { runWithRequestContext } from "@agent-native/core/server";
3
+ import { and, eq, isNull } from "drizzle-orm";
4
+
5
+ import exportToBrain from "../../actions/export-to-brain.js";
6
+ import { getDb, schema } from "../db/index.js";
7
+ import {
8
+ BRAIN_EXPORT_STATE_PREFIX,
9
+ parseBrainExportState,
10
+ writeBrainExportState,
11
+ } from "../lib/brain-export-state.js";
12
+ import { ownerEmailMatches } from "../lib/recordings.js";
13
+
14
+ const SWEEP_INTERVAL_MS = 60_000;
15
+ const MAX_ATTEMPTS = 8;
16
+ const SWEEP_LIMIT = 4;
17
+ const DISCOVERY_LIMIT = 20;
18
+ const BACKFILL_DAYS = 7;
19
+ let skippingLogged = false;
20
+
21
+ async function seedRecentBrainExports(): Promise<void> {
22
+ const now = new Date();
23
+ const { rows } = await getDbExec().execute({
24
+ sql: `SELECT recordings.id, recordings.owner_email, recordings.org_id
25
+ FROM recordings
26
+ INNER JOIN recording_transcripts
27
+ ON recording_transcripts.recording_id = recordings.id
28
+ WHERE recordings.status = ?
29
+ AND recordings.trashed_at IS NULL
30
+ AND recordings.org_id IS NOT NULL
31
+ AND recordings.created_at >= ?
32
+ AND recording_transcripts.status = ?
33
+ AND LENGTH(TRIM(COALESCE(recording_transcripts.full_text, ''))) > 0
34
+ AND NOT EXISTS (
35
+ SELECT 1 FROM application_state
36
+ WHERE application_state.session_id = recordings.owner_email
37
+ AND application_state.key = ? || recordings.id
38
+ )
39
+ ORDER BY recordings.created_at DESC
40
+ LIMIT ?`,
41
+ args: [
42
+ "ready",
43
+ new Date(
44
+ now.getTime() - BACKFILL_DAYS * 24 * 60 * 60 * 1000,
45
+ ).toISOString(),
46
+ "ready",
47
+ BRAIN_EXPORT_STATE_PREFIX,
48
+ DISCOVERY_LIMIT,
49
+ ],
50
+ });
51
+ for (const row of rows as Array<{
52
+ id?: unknown;
53
+ owner_email?: unknown;
54
+ org_id?: unknown;
55
+ }>) {
56
+ const recordingId = typeof row.id === "string" ? row.id.trim() : "";
57
+ const ownerEmail =
58
+ typeof row.owner_email === "string" ? row.owner_email.trim() : "";
59
+ const orgId = typeof row.org_id === "string" ? row.org_id.trim() : "";
60
+ if (!recordingId || !ownerEmail || !orgId) continue;
61
+ await runWithRequestContext({ userEmail: ownerEmail, orgId }, () =>
62
+ writeBrainExportState({
63
+ recordingId,
64
+ status: "pending",
65
+ attempts: 0,
66
+ updatedAt: now.toISOString(),
67
+ nextAttemptAt: now.toISOString(),
68
+ }),
69
+ );
70
+ }
71
+ }
72
+
73
+ export async function runBrainExportSweepOnce(): Promise<void> {
74
+ await seedRecentBrainExports();
75
+ const { rows } = await getDbExec().execute({
76
+ sql: "SELECT session_id, key, value FROM application_state WHERE key LIKE ? AND (value LIKE ? OR value LIKE ?) ORDER BY updated_at ASC LIMIT ?",
77
+ args: [
78
+ `${BRAIN_EXPORT_STATE_PREFIX}%`,
79
+ '%"status":"pending"%',
80
+ '%"status":"failed"%',
81
+ SWEEP_LIMIT,
82
+ ],
83
+ });
84
+ const now = Date.now();
85
+ for (const row of rows as Array<{
86
+ session_id?: unknown;
87
+ key?: unknown;
88
+ value?: unknown;
89
+ }>) {
90
+ const ownerEmail =
91
+ typeof row.session_id === "string" ? row.session_id.trim() : "";
92
+ const key = typeof row.key === "string" ? row.key : "";
93
+ const recordingId = key.slice(BRAIN_EXPORT_STATE_PREFIX.length);
94
+ let raw: unknown;
95
+ try {
96
+ raw = JSON.parse(typeof row.value === "string" ? row.value : "");
97
+ } catch {
98
+ continue;
99
+ }
100
+ const state = parseBrainExportState(raw);
101
+ if (
102
+ !ownerEmail ||
103
+ !recordingId ||
104
+ !state ||
105
+ state.recordingId !== recordingId ||
106
+ !["pending", "failed"].includes(state.status) ||
107
+ state.attempts >= MAX_ATTEMPTS ||
108
+ Date.parse(state.nextAttemptAt ?? "") > now
109
+ )
110
+ continue;
111
+ try {
112
+ const [recording] = await getDb()
113
+ .select({
114
+ ownerEmail: schema.recordings.ownerEmail,
115
+ orgId: schema.recordings.orgId,
116
+ })
117
+ .from(schema.recordings)
118
+ .where(
119
+ and(
120
+ eq(schema.recordings.id, recordingId),
121
+ ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
122
+ eq(schema.recordings.status, "ready"),
123
+ isNull(schema.recordings.trashedAt),
124
+ ),
125
+ )
126
+ .limit(1);
127
+ if (!recording) continue;
128
+ await runWithRequestContext(
129
+ {
130
+ userEmail: recording.ownerEmail,
131
+ orgId: recording.orgId ?? undefined,
132
+ },
133
+ () =>
134
+ exportToBrain.run({ recordingId, retryAttempt: state.attempts + 1 }),
135
+ );
136
+ } catch (error) {
137
+ const attempts = state.attempts + 1;
138
+ await runWithRequestContext({ userEmail: ownerEmail }, () =>
139
+ writeBrainExportState({
140
+ recordingId,
141
+ status: "failed",
142
+ attempts,
143
+ reason: "brain-export-worker-failed",
144
+ updatedAt: new Date().toISOString(),
145
+ nextAttemptAt: new Date(
146
+ Date.now() +
147
+ Math.min(15 * 60_000, 30_000 * 2 ** Math.max(0, attempts - 1)),
148
+ ).toISOString(),
149
+ }),
150
+ );
151
+ console.warn("[brain-export] sweep item failed", {
152
+ recordingId,
153
+ error: error instanceof Error ? error.message : String(error),
154
+ });
155
+ }
156
+ }
157
+ }
158
+
159
+ export default function registerBrainExportJob(): void {
160
+ if (process.env.NETLIFY === "true") return;
161
+ const enabled =
162
+ process.env.RUN_BACKGROUND_JOBS === "1" ||
163
+ (process.env.NODE_ENV === "production" &&
164
+ process.env.RUN_BACKGROUND_JOBS !== "0");
165
+ if (!enabled) {
166
+ if (process.env.DEBUG && !skippingLogged) {
167
+ console.log(
168
+ "[brain-export] Skipping background sweep (set RUN_BACKGROUND_JOBS=1 to enable in dev).",
169
+ );
170
+ skippingLogged = true;
171
+ }
172
+ return;
173
+ }
174
+ setInterval(() => {
175
+ runBrainExportSweepOnce().catch((error) =>
176
+ console.error("[brain-export] interval failed:", error),
177
+ );
178
+ }, SWEEP_INTERVAL_MS);
179
+ console.log(
180
+ `[brain-export] Recurring recovery sweep every ${SWEEP_INTERVAL_MS / 1000}s.`,
181
+ );
182
+ }
@@ -0,0 +1,42 @@
1
+ import { writeAppState } from "@agent-native/core/application-state";
2
+
3
+ export const BRAIN_EXPORT_STATE_PREFIX = "clips-brain-export-";
4
+
5
+ export type BrainExportState = {
6
+ recordingId: string;
7
+ status: "pending" | "exported" | "quarantined" | "failed" | "skipped";
8
+ attempts: number;
9
+ updatedAt: string;
10
+ nextAttemptAt?: string;
11
+ captureId?: string;
12
+ sensitivityReceiptId?: string;
13
+ sensitivityDisposition?: string;
14
+ reason?: string;
15
+ };
16
+
17
+ export function brainExportStateKey(recordingId: string): string {
18
+ return `${BRAIN_EXPORT_STATE_PREFIX}${recordingId}`;
19
+ }
20
+
21
+ export async function writeBrainExportState(state: BrainExportState) {
22
+ await writeAppState(brainExportStateKey(state.recordingId), state);
23
+ }
24
+
25
+ export function parseBrainExportState(value: unknown): BrainExportState | null {
26
+ if (!value || typeof value !== "object") return null;
27
+ const state = value as Partial<BrainExportState>;
28
+ if (
29
+ typeof state.recordingId !== "string" ||
30
+ !state.recordingId ||
31
+ !["pending", "exported", "quarantined", "failed", "skipped"].includes(
32
+ String(state.status),
33
+ ) ||
34
+ typeof state.attempts !== "number" ||
35
+ !Number.isInteger(state.attempts) ||
36
+ state.attempts < 0 ||
37
+ typeof state.updatedAt !== "string"
38
+ ) {
39
+ return null;
40
+ }
41
+ return state as BrainExportState;
42
+ }
@@ -7,7 +7,11 @@ import {
7
7
  signScopedAgentAccessToken,
8
8
  } from "@agent-native/core/server";
9
9
 
10
- export type PostFinalizeJobKind = "media-ready" | "seekable" | "transcript";
10
+ export type PostFinalizeJobKind =
11
+ | "media-ready"
12
+ | "seekable"
13
+ | "transcript"
14
+ | "brain-export";
11
15
 
12
16
  export const POST_FINALIZE_JOB_TOKEN_KIND = "clips-post-finalize-job";
13
17
 
@@ -5,6 +5,7 @@
5
5
  * pattern).
6
6
  */
7
7
 
8
+ import registerBrainExportJob from "../jobs/brain-export.js";
8
9
  import registerBuilderMediaCompressionJob from "../jobs/builder-media-compression.js";
9
10
  import registerMediaVerificationJob from "../jobs/media-verification.js";
10
11
  import registerMeetingRemindersJob from "../jobs/meeting-reminders.js";
@@ -17,6 +18,7 @@ export default () => {
17
18
  // background loop is off.
18
19
  registerMeetingRemindersJob();
19
20
  registerBuilderMediaCompressionJob();
21
+ registerBrainExportJob();
20
22
  registerMediaVerificationJob();
21
23
  registerPollCalendarsJob();
22
24
  registerStaleMeetingSweeperJob();
@@ -219,6 +219,48 @@ registerRequiredSecret({
219
219
  required: false,
220
220
  });
221
221
 
222
+ // ── Brain transcript ingest ──────────────────────────────────────────
223
+ // Both values are workspace-scoped: every clip in the workspace must reach
224
+ // the same Brain source, while the encrypted secret store keeps the token out
225
+ // of action responses, application state, and client bundles.
226
+
227
+ registerRequiredSecret({
228
+ key: "BRAIN_INGEST_URL",
229
+ label: "Brain ingest URL",
230
+ description:
231
+ "Signed Brain generic-ingest endpoint for ready Clips transcripts. Pair with BRAIN_INGEST_TOKEN.",
232
+ scope: "workspace",
233
+ kind: "api-key",
234
+ required: false,
235
+ validator: (value) => {
236
+ if (!value) return true;
237
+ try {
238
+ const url = new URL(value);
239
+ return url.protocol === "http:" || url.protocol === "https:"
240
+ ? true
241
+ : { ok: false, error: "Use an HTTP or HTTPS URL." };
242
+ } catch {
243
+ return { ok: false, error: "Enter a valid ingest URL." };
244
+ }
245
+ },
246
+ });
247
+
248
+ registerRequiredSecret({
249
+ key: "BRAIN_INGEST_TOKEN",
250
+ label: "Brain ingest token",
251
+ description:
252
+ "Bearer token for the configured Brain ingest URL. Stored encrypted and never returned to Clips clients or export receipts.",
253
+ scope: "workspace",
254
+ kind: "api-key",
255
+ required: false,
256
+ validator: (value) => {
257
+ if (!value) return true;
258
+ return typeof value === "string" && value.trim().length >= 8
259
+ ? true
260
+ : { ok: false, error: "Token looks too short." };
261
+ },
262
+ });
263
+
222
264
  // ── Dark-launched media worker plumbing ──────────────────────────────
223
265
  // These are optional until the ai-services worker is deployed. When enabled,
224
266
  // Clips enqueues background video compression jobs there instead of using
@@ -11,6 +11,7 @@ import {
11
11
  } from "h3";
12
12
  import { z } from "zod";
13
13
 
14
+ import exportToBrain from "../../../../actions/export-to-brain.js";
14
15
  import finalizeRecording from "../../../../actions/finalize-recording.js";
15
16
  import { ensureRecordingSeekable } from "../../../../actions/lib/ensure-seekable-video.js";
16
17
  import requestTranscript from "../../../../actions/request-transcript.js";
@@ -23,7 +24,7 @@ import {
23
24
 
24
25
  const bodySchema = z.object({
25
26
  recordingId: z.string().min(1).max(200),
26
- kind: z.enum(["media-ready", "seekable", "transcript"]),
27
+ kind: z.enum(["media-ready", "seekable", "transcript", "brain-export"]),
27
28
  token: z.string().min(1),
28
29
  delayMs: z.number().int().min(0).max(30_000).optional(),
29
30
  retryAttempt: z.number().int().min(1).max(10).optional(),
@@ -111,6 +112,14 @@ export default defineEventHandler(async (event: H3Event) => {
111
112
  return { ok: true, kind, result };
112
113
  }
113
114
 
115
+ if (kind === "brain-export") {
116
+ const result = await exportToBrain.run({
117
+ recordingId,
118
+ retryAttempt,
119
+ });
120
+ return { ok: true, kind, result };
121
+ }
122
+
114
123
  const result = await requestTranscript.run({
115
124
  recordingId,
116
125
  force: true,
@@ -0,0 +1,45 @@
1
+ import { timingSafeEqual } from "node:crypto";
2
+
3
+ import { createError, defineEventHandler, getHeader } from "h3";
4
+
5
+ import { runBrainExportSweepOnce } from "../../../../jobs/brain-export.js";
6
+
7
+ declare global {
8
+ var __AGENT_NATIVE_CLIPS_BRAIN_EXPORT_SCHEDULED_RUNTIME__:
9
+ | boolean
10
+ | undefined;
11
+ }
12
+
13
+ function productionLike() {
14
+ return (
15
+ process.env.NODE_ENV === "production" || process.env.NETLIFY === "true"
16
+ );
17
+ }
18
+
19
+ function headerMatchesSecret(header: string | undefined, secret: string) {
20
+ const expected = `Bearer ${secret}`;
21
+ const value = header?.trim() ?? "";
22
+ return (
23
+ value.length === expected.length &&
24
+ timingSafeEqual(Buffer.from(value), Buffer.from(expected))
25
+ );
26
+ }
27
+
28
+ export default defineEventHandler(async (event) => {
29
+ const scheduled =
30
+ globalThis.__AGENT_NATIVE_CLIPS_BRAIN_EXPORT_SCHEDULED_RUNTIME__ === true;
31
+ const secret = process.env.CLIPS_BRAIN_EXPORT_JOBS_SECRET?.trim(); // guard:allow-env-credential — deployment scheduler route secret
32
+ if (!secret && productionLike() && !scheduled)
33
+ throw createError({
34
+ statusCode: 503,
35
+ statusMessage: "CLIPS_BRAIN_EXPORT_JOBS_SECRET is required",
36
+ });
37
+ if (
38
+ secret &&
39
+ !scheduled &&
40
+ !headerMatchesSecret(getHeader(event, "authorization"), secret)
41
+ )
42
+ throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
43
+ await runBrainExportSweepOnce();
44
+ return { ok: true };
45
+ });
@@ -85,7 +85,10 @@ in the moment of agent use.
85
85
  approval, generative UI, progress, and screen-state exposure.
86
86
  - **Chat history kit**: presentational chat lists and recent-chat rails belong
87
87
  in Toolkit; Core keeps thread persistence, agent execution, transport, and
88
- page-to-sidebar handoff. Apps inject routing, labels, and domain actions.
88
+ page-to-sidebar handoff. Use Toolkit's `ChatHistoryRail` for the standard
89
+ five-item sidebar preview and a footer row with New chat followed by an
90
+ ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
91
+ actions.
89
92
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
90
93
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
91
94
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -72,7 +72,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
72
72
  });
73
73
  ```
74
74
 
75
- `useDbSync` and every `subscribeSyncEvents` subscriber share one `EventSource` and one fallback poll loop per tab — this is how collaborative documents receive doc updates and cursor/awareness events.
75
+ `useDbSync` and every `subscribeSyncEvents` subscriber share one `EventSource` and one fallback poll loop per tab — this is how collaborative documents receive doc updates and cursor/awareness events. Hidden tabs keep that shared transport alive by default: SSE stays connected and active fallback polling relaxes to a 10-second floor (idle polling remains once per minute). Pass `pauseWhenHidden: true` only for a consumer that explicitly must stop all hidden-tab sync.
76
76
 
77
77
  ## Which sources to depend on
78
78
 
@@ -2093,7 +2093,7 @@ export function DocumentSidebar({
2093
2093
  {/* Footer */}
2094
2094
  <div className="shrink-0 space-y-2 px-3 py-2">
2095
2095
  {isCodeMode ? <DevDatabaseLink /> : null}
2096
- <div className="flex items-center gap-1">
2096
+ <div className="flex items-center justify-end gap-1">
2097
2097
  <FeedbackButton className="h-8 min-w-0 flex-1 gap-2 rounded-md px-2 py-0" />
2098
2098
  <div className="flex shrink-0 items-center gap-0.5">
2099
2099
  <NotionButton />
@@ -5,5 +5,5 @@ export default createCollabPlugin({
5
5
  contentColumn: "content",
6
6
  idColumn: "id",
7
7
  autoSeed: false, // Seeding happens via edit-document action, not on startup
8
- resourceType: "document",
8
+ access: { mode: "resource", resourceType: "document" },
9
9
  });
@@ -85,7 +85,10 @@ in the moment of agent use.
85
85
  approval, generative UI, progress, and screen-state exposure.
86
86
  - **Chat history kit**: presentational chat lists and recent-chat rails belong
87
87
  in Toolkit; Core keeps thread persistence, agent execution, transport, and
88
- page-to-sidebar handoff. Apps inject routing, labels, and domain actions.
88
+ page-to-sidebar handoff. Use Toolkit's `ChatHistoryRail` for the standard
89
+ five-item sidebar preview and a footer row with New chat followed by an
90
+ ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
91
+ actions.
89
92
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
90
93
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
91
94
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -0,0 +1,15 @@
1
+ import { initDataPrograms } from "@agent-native/core/data-programs";
2
+
3
+ import { CRM_APP_ID } from "../server/lib/provider-api.js";
4
+ import getCrmPipelineData from "./get-crm-pipeline-data.js";
5
+
6
+ export function getCrmDataProgramActions() {
7
+ return { "get-crm-pipeline-data": getCrmPipelineData };
8
+ }
9
+
10
+ export function initCrmDataPrograms(): void {
11
+ initDataPrograms({
12
+ appId: CRM_APP_ID,
13
+ getActions: getCrmDataProgramActions,
14
+ });
15
+ }
@@ -5,6 +5,7 @@ import { z } from "zod";
5
5
  import { crmDashboardStore } from "../server/db/index.js";
6
6
  import { CRM_APP_ID } from "../server/lib/provider-api.js";
7
7
  import { requireDashboardAccess } from "./_crm-dashboard.js";
8
+ import { initCrmDataPrograms } from "./_crm-data-program-actions.js";
8
9
 
9
10
  const programResolver = createProgramPanelSourceResolver({ appId: CRM_APP_ID });
10
11
 
@@ -25,6 +26,7 @@ export default defineAction({
25
26
  if (!dashboard) throw new Error("CRM dashboard was not found.");
26
27
  const panel = dashboard.config.panels.find((item) => item.id === panelId);
27
28
  if (!panel) throw new Error("CRM dashboard panel was not found.");
29
+ initCrmDataPrograms();
28
30
  return programResolver.resolve(
29
31
  { source: panel.source, query: panel.query },
30
32
  { userEmail: access.userEmail, orgId: access.orgId ?? null },
@@ -1,11 +1,7 @@
1
- import { initDataPrograms } from "@agent-native/core/data-programs";
2
1
  import { runScript } from "@agent-native/core/scripts";
3
2
 
4
- import getCrmPipelineData from "./get-crm-pipeline-data.js";
3
+ import { initCrmDataPrograms } from "./_crm-data-program-actions.js";
5
4
 
6
- initDataPrograms({
7
- appId: "crm",
8
- getActions: () => ({ "get-crm-pipeline-data": getCrmPipelineData }),
9
- });
5
+ initCrmDataPrograms();
10
6
 
11
7
  runScript();
@@ -272,9 +272,11 @@ export default defineAction({
272
272
  );
273
273
  });
274
274
  if (missing.length || blocked.length) {
275
- throw new Error(
275
+ const error = new Error(
276
276
  `Only discovered, updateable CRM fields can be changed. Unsupported: ${[...new Set([...missing, ...blocked])].join(", ")}`,
277
- );
277
+ ) as Error & { statusCode?: number };
278
+ error.statusCode = 422;
279
+ throw error;
278
280
  }
279
281
 
280
282
  const wrongAuthority = fieldNames.filter((fieldName) => {
@@ -4,6 +4,7 @@ import {
4
4
  focusAgentChat,
5
5
  navigateWithAgentChatViewTransition,
6
6
  useAgentChatHomeHandoff,
7
+ useAgentChatHomeHandoffLinks,
7
8
  } from "@agent-native/core/client/agent-chat";
8
9
  import { Button } from "@agent-native/toolkit/ui/button";
9
10
  import {
@@ -29,6 +30,11 @@ export function CrmLayout({ children }: { children: React.ReactNode }) {
29
30
  activePath: location.pathname,
30
31
  enabled: !isAskRoute,
31
32
  });
33
+ useAgentChatHomeHandoffLinks({
34
+ storageKey: "crm",
35
+ chatPath: "/ask",
36
+ requireActiveHandoff: false,
37
+ });
32
38
 
33
39
  useEffect(() => setMobileOpen(false), [location.pathname]);
34
40
 
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-22
4
+ ---
5
+
6
+ CRM field validation now explains which fields cannot be edited instead of showing a generic error.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-22
4
+ ---
5
+
6
+ Fixed HubSpot contact syncs missing records updated after the sync cursor.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-22
4
+ ---
5
+
6
+ Fixed Pipeline dashboard panels so their opportunity data loads reliably.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-22
4
+ ---
5
+
6
+ Full-page chat keeps the active conversation when moving to and from the sidebar.
@@ -751,7 +751,10 @@ export class HubSpotCrmAdapter implements CrmAdapter {
751
751
  }
752
752
  if (scope.updatedAfter) {
753
753
  filters.push({
754
- propertyName: "hs_lastmodifieddate",
754
+ propertyName:
755
+ scope.objectType.toLowerCase() === "contacts"
756
+ ? "lastmodifieddate"
757
+ : "hs_lastmodifieddate",
755
758
  operator: "GTE",
756
759
  value: scope.updatedAfter,
757
760
  });
@@ -85,7 +85,10 @@ in the moment of agent use.
85
85
  approval, generative UI, progress, and screen-state exposure.
86
86
  - **Chat history kit**: presentational chat lists and recent-chat rails belong
87
87
  in Toolkit; Core keeps thread persistence, agent execution, transport, and
88
- page-to-sidebar handoff. Apps inject routing, labels, and domain actions.
88
+ page-to-sidebar handoff. Use Toolkit's `ChatHistoryRail` for the standard
89
+ five-item sidebar preview and a footer row with New chat followed by an
90
+ ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
91
+ actions.
89
92
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
90
93
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
91
94
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -168,7 +168,7 @@ export function Sidebar() {
168
168
 
169
169
  <div className="px-3 py-2">
170
170
  <DevDatabaseLink />
171
- <div className="flex items-center gap-1">
171
+ <div className="flex items-center justify-end gap-1">
172
172
  <FeedbackButton className="min-w-0 flex-1" />
173
173
  <ThemeToggle className="h-8 w-8 shrink-0" />
174
174
  </div>
@@ -8,13 +8,16 @@ export default createCollabPlugin({
8
8
  contentColumn: "content",
9
9
  idColumn: "id",
10
10
  autoSeed: true,
11
- resourceType: "design",
12
- resolveResourceId: async (docId) => {
13
- const db = getDb();
14
- const [file] = await db
15
- .select({ designId: schema.designFiles.designId })
16
- .from(schema.designFiles)
17
- .where(eq(schema.designFiles.id, docId));
18
- return file?.designId ?? null;
11
+ access: {
12
+ mode: "resource",
13
+ resourceType: "design",
14
+ resolveResourceId: async (docId) => {
15
+ const db = getDb();
16
+ const [file] = await db
17
+ .select({ designId: schema.designFiles.designId })
18
+ .from(schema.designFiles)
19
+ .where(eq(schema.designFiles.id, docId));
20
+ return file?.designId ?? null;
21
+ },
19
22
  },
20
23
  });
@@ -85,7 +85,10 @@ in the moment of agent use.
85
85
  approval, generative UI, progress, and screen-state exposure.
86
86
  - **Chat history kit**: presentational chat lists and recent-chat rails belong
87
87
  in Toolkit; Core keeps thread persistence, agent execution, transport, and
88
- page-to-sidebar handoff. Apps inject routing, labels, and domain actions.
88
+ page-to-sidebar handoff. Use Toolkit's `ChatHistoryRail` for the standard
89
+ five-item sidebar preview and a footer row with New chat followed by an
90
+ ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
91
+ actions.
89
92
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
90
93
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
91
94
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -85,7 +85,10 @@ in the moment of agent use.
85
85
  approval, generative UI, progress, and screen-state exposure.
86
86
  - **Chat history kit**: presentational chat lists and recent-chat rails belong
87
87
  in Toolkit; Core keeps thread persistence, agent execution, transport, and
88
- page-to-sidebar handoff. Apps inject routing, labels, and domain actions.
88
+ page-to-sidebar handoff. Use Toolkit's `ChatHistoryRail` for the standard
89
+ five-item sidebar preview and a footer row with New chat followed by an
90
+ ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
91
+ actions.
89
92
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
90
93
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
91
94
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -72,7 +72,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
72
72
  });
73
73
  ```
74
74
 
75
- `useDbSync` and every `subscribeSyncEvents` subscriber share one `EventSource` and one fallback poll loop per tab — this is how collaborative documents receive doc updates and cursor/awareness events.
75
+ `useDbSync` and every `subscribeSyncEvents` subscriber share one `EventSource` and one fallback poll loop per tab — this is how collaborative documents receive doc updates and cursor/awareness events. Hidden tabs keep that shared transport alive by default: SSE stays connected and active fallback polling relaxes to a 10-second floor (idle polling remains once per minute). Pass `pauseWhenHidden: true` only for a consumer that explicitly must stop all hidden-tab sync.
76
76
 
77
77
  ## Which sources to depend on
78
78