@agent-native/core 0.118.0 → 0.118.1

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 (375) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +21 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/a2a/client.ts +32 -10
  5. package/corpus/core/src/cli/index.ts +18 -10
  6. package/corpus/core/src/cli/multi-frontier-runs.ts +5 -3
  7. package/corpus/core/src/cli/templates-meta.ts +0 -12
  8. package/corpus/core/src/cli/workspace-dev.ts +1 -1
  9. package/corpus/core/src/client/AgentPanel.tsx +9 -1
  10. package/corpus/core/src/client/RunStuckBanner.tsx +39 -47
  11. package/corpus/core/src/client/chat/action-chat-ui-surface.tsx +32 -0
  12. package/corpus/core/src/client/chat/message-components.tsx +53 -8
  13. package/corpus/core/src/client/chat/tool-call-display.tsx +24 -9
  14. package/corpus/core/src/client/chat/widgets/InlineExtensionWidget.tsx +0 -1
  15. package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +7 -3
  16. package/corpus/core/src/client/conversation/AgentConversation.tsx +12 -1
  17. package/corpus/core/src/client/error-capture.ts +2 -6
  18. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +20 -14
  19. package/corpus/core/src/client/resources/ResourcesPanel.tsx +5 -1
  20. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +7 -17
  21. package/corpus/core/src/client/resources/mcp-integration-logos.ts +2 -2
  22. package/corpus/core/src/client/route-chunk-recovery.ts +5 -3
  23. package/corpus/core/src/client/session-replay.ts +3 -3
  24. package/corpus/core/src/client/settings/SettingsPanel.tsx +15 -6
  25. package/corpus/core/src/client/transcription/use-live-transcription.ts +64 -45
  26. package/corpus/core/src/deploy/build.ts +2 -1
  27. package/corpus/core/src/guards/db-tool-scoping.ts +1 -1
  28. package/corpus/core/src/integrations/adapters/slack.ts +84 -5
  29. package/corpus/core/src/integrations/index.ts +5 -1
  30. package/corpus/core/src/localization/default-messages.ts +1 -1
  31. package/corpus/core/src/mcp-client/oauth-routes.ts +45 -12
  32. package/corpus/core/src/server/realtime-voice.ts +4 -1
  33. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +7 -5
  34. package/corpus/core/src/terminal/cli-registry.ts +1 -1
  35. package/corpus/core/src/vite/client.ts +166 -1
  36. package/corpus/templates/analytics/app/hooks/use-dashboard-views.ts +13 -1
  37. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewsMenu.tsx +10 -0
  38. package/corpus/templates/analytics/changelog/2026-07-22-show-a-useful-error-when-saving-a-dashboard-view-fails.md +6 -0
  39. package/corpus/templates/brain/app/routes/sources.tsx +181 -114
  40. package/corpus/templates/clips/AGENTS.md +8 -6
  41. package/corpus/templates/clips/actions/request-transcript.ts +90 -420
  42. package/corpus/templates/clips/actions/save-browser-transcript.ts +11 -28
  43. package/corpus/templates/clips/app/components/capture-install-options.tsx +5 -3
  44. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +3 -136
  45. package/corpus/templates/clips/app/lib/capture-install-options.ts +15 -4
  46. package/corpus/templates/clips/app/routes/download.tsx +3 -2
  47. package/corpus/templates/clips/changelog/2026-07-22-fixed-an-intermittent-hydration-error-on-the-download-page.md +6 -0
  48. package/corpus/templates/clips/changelog/2026-07-22-fixed-transcript-generation-when-native-speech-capture-retur.md +6 -0
  49. package/corpus/templates/clips/changelog/2026-07-22-transcript-generation-now-retries-with-backup-speech-recogni.md +6 -0
  50. package/corpus/templates/clips/server/lib/public-agent-context.ts +2 -2
  51. package/corpus/templates/clips/server/register-secrets.ts +7 -6
  52. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +16 -84
  53. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +13 -7
  54. package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +2 -2
  55. package/corpus/templates/content/app/i18n-data.ts +10 -0
  56. package/corpus/templates/design/server/lib/fig-file-decoder.ts +1 -0
  57. package/corpus/templates/plan/app/entry.client.tsx +3 -0
  58. package/corpus/templates/plan/changelog/2026-07-22-recover-stale-pages-after-a-deployment-refresh-automatically.md +6 -0
  59. package/corpus/templates/slides/app/hooks/use-agent-generating.ts +10 -3
  60. package/corpus/templates/slides/app/pages/Index.tsx +1 -0
  61. package/corpus/templates/slides/changelog/2026-07-22-new-deck-prompts-now-open-in-their-own-visible-chat-thread.md +6 -0
  62. package/corpus/toolkit/CHANGELOG.md +9 -0
  63. package/corpus/toolkit/package.json +1 -1
  64. package/corpus/toolkit/src/composer/PromptComposer.tsx +5 -1
  65. package/corpus/toolkit/src/composer/RealtimeVoiceMode.tsx +119 -31
  66. package/corpus/toolkit/src/composer/useRealtimeVoiceMode.tsx +30 -0
  67. package/corpus/toolkit/src/conformance/runner.tsx +153 -1
  68. package/corpus/toolkit/src/editor/SharedRichEditor.tsx +13 -2
  69. package/corpus/toolkit/src/editor/SlashCommandMenu.tsx +20 -0
  70. package/corpus/toolkit/src/editor/index.ts +2 -0
  71. package/corpus/toolkit/src/styles.css +52 -23
  72. package/dist/a2a/client.d.ts +3 -1
  73. package/dist/a2a/client.d.ts.map +1 -1
  74. package/dist/a2a/client.js +17 -12
  75. package/dist/a2a/client.js.map +1 -1
  76. package/dist/cli/index.js +18 -8
  77. package/dist/cli/index.js.map +1 -1
  78. package/dist/cli/multi-frontier-runs.js +3 -3
  79. package/dist/cli/multi-frontier-runs.js.map +1 -1
  80. package/dist/cli/templates-meta.d.ts.map +1 -1
  81. package/dist/cli/templates-meta.js +0 -12
  82. package/dist/cli/templates-meta.js.map +1 -1
  83. package/dist/cli/workspace-dev.js +1 -1
  84. package/dist/cli/workspace-dev.js.map +1 -1
  85. package/dist/client/AgentPanel.d.ts.map +1 -1
  86. package/dist/client/AgentPanel.js +4 -1
  87. package/dist/client/AgentPanel.js.map +1 -1
  88. package/dist/client/RunStuckBanner.d.ts +3 -5
  89. package/dist/client/RunStuckBanner.d.ts.map +1 -1
  90. package/dist/client/RunStuckBanner.js +17 -18
  91. package/dist/client/RunStuckBanner.js.map +1 -1
  92. package/dist/client/chat/action-chat-ui-surface.d.ts +8 -0
  93. package/dist/client/chat/action-chat-ui-surface.d.ts.map +1 -0
  94. package/dist/client/chat/action-chat-ui-surface.js +10 -0
  95. package/dist/client/chat/action-chat-ui-surface.js.map +1 -0
  96. package/dist/client/chat/message-components.d.ts +3 -0
  97. package/dist/client/chat/message-components.d.ts.map +1 -1
  98. package/dist/client/chat/message-components.js +40 -7
  99. package/dist/client/chat/message-components.js.map +1 -1
  100. package/dist/client/chat/tool-call-display.d.ts +3 -1
  101. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  102. package/dist/client/chat/tool-call-display.js +13 -9
  103. package/dist/client/chat/tool-call-display.js.map +1 -1
  104. package/dist/client/chat/widgets/InlineExtensionWidget.d.ts.map +1 -1
  105. package/dist/client/chat/widgets/InlineExtensionWidget.js +1 -1
  106. package/dist/client/chat/widgets/InlineExtensionWidget.js.map +1 -1
  107. package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
  108. package/dist/client/chat/widgets/builtin-tool-renderers.js +5 -3
  109. package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
  110. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  111. package/dist/client/conversation/AgentConversation.js +3 -2
  112. package/dist/client/conversation/AgentConversation.js.map +1 -1
  113. package/dist/client/error-capture.d.ts.map +1 -1
  114. package/dist/client/error-capture.js +2 -2
  115. package/dist/client/error-capture.js.map +1 -1
  116. package/dist/client/resources/McpConnectionSuggestion.d.ts +1 -0
  117. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
  118. package/dist/client/resources/McpConnectionSuggestion.js +9 -8
  119. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
  120. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  121. package/dist/client/resources/ResourcesPanel.js +3 -1
  122. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  123. package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
  124. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  125. package/dist/client/resources/mcp-integration-catalog.js +4 -17
  126. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  127. package/dist/client/resources/mcp-integration-logos.js +2 -2
  128. package/dist/client/resources/mcp-integration-logos.js.map +1 -1
  129. package/dist/client/route-chunk-recovery.d.ts.map +1 -1
  130. package/dist/client/route-chunk-recovery.js +5 -3
  131. package/dist/client/route-chunk-recovery.js.map +1 -1
  132. package/dist/client/session-replay.js +3 -3
  133. package/dist/client/session-replay.js.map +1 -1
  134. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  135. package/dist/client/settings/SettingsPanel.js +2 -2
  136. package/dist/client/settings/SettingsPanel.js.map +1 -1
  137. package/dist/client/transcription/use-live-transcription.d.ts +3 -3
  138. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  139. package/dist/client/transcription/use-live-transcription.js +22 -11
  140. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  141. package/dist/collab/routes.d.ts +1 -1
  142. package/dist/collab/struct-routes.d.ts +1 -1
  143. package/dist/deploy/build.d.ts.map +1 -1
  144. package/dist/deploy/build.js +1 -1
  145. package/dist/deploy/build.js.map +1 -1
  146. package/dist/guards/db-tool-scoping.js +1 -1
  147. package/dist/guards/db-tool-scoping.js.map +1 -1
  148. package/dist/integrations/adapters/slack.d.ts +1 -0
  149. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  150. package/dist/integrations/adapters/slack.js +61 -5
  151. package/dist/integrations/adapters/slack.js.map +1 -1
  152. package/dist/integrations/index.d.ts +1 -1
  153. package/dist/integrations/index.d.ts.map +1 -1
  154. package/dist/integrations/index.js +1 -1
  155. package/dist/integrations/index.js.map +1 -1
  156. package/dist/localization/default-messages.js +1 -1
  157. package/dist/localization/default-messages.js.map +1 -1
  158. package/dist/mcp-client/oauth-routes.d.ts +3 -0
  159. package/dist/mcp-client/oauth-routes.d.ts.map +1 -1
  160. package/dist/mcp-client/oauth-routes.js +41 -12
  161. package/dist/mcp-client/oauth-routes.js.map +1 -1
  162. package/dist/notifications/routes.d.ts +2 -2
  163. package/dist/observability/routes.d.ts +3 -3
  164. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  165. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  166. package/dist/secrets/routes.d.ts +6 -6
  167. package/dist/server/realtime-voice.d.ts.map +1 -1
  168. package/dist/server/realtime-voice.js +1 -1
  169. package/dist/server/realtime-voice.js.map +1 -1
  170. package/dist/server/transcribe-voice.d.ts +1 -1
  171. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +7 -5
  172. package/dist/terminal/cli-registry.js +1 -1
  173. package/dist/terminal/cli-registry.js.map +1 -1
  174. package/dist/vite/client.d.ts +8 -1
  175. package/dist/vite/client.d.ts.map +1 -1
  176. package/dist/vite/client.js +113 -2
  177. package/dist/vite/client.js.map +1 -1
  178. package/package.json +2 -2
  179. package/src/a2a/client.ts +32 -10
  180. package/src/cli/index.ts +18 -10
  181. package/src/cli/multi-frontier-runs.ts +5 -3
  182. package/src/cli/templates-meta.ts +0 -12
  183. package/src/cli/workspace-dev.ts +1 -1
  184. package/src/client/AgentPanel.tsx +9 -1
  185. package/src/client/RunStuckBanner.tsx +39 -47
  186. package/src/client/chat/action-chat-ui-surface.tsx +32 -0
  187. package/src/client/chat/message-components.tsx +53 -8
  188. package/src/client/chat/tool-call-display.tsx +24 -9
  189. package/src/client/chat/widgets/InlineExtensionWidget.tsx +0 -1
  190. package/src/client/chat/widgets/builtin-tool-renderers.tsx +7 -3
  191. package/src/client/conversation/AgentConversation.tsx +12 -1
  192. package/src/client/error-capture.ts +2 -6
  193. package/src/client/resources/McpConnectionSuggestion.tsx +20 -14
  194. package/src/client/resources/ResourcesPanel.tsx +5 -1
  195. package/src/client/resources/mcp-integration-catalog.ts +7 -17
  196. package/src/client/resources/mcp-integration-logos.ts +2 -2
  197. package/src/client/route-chunk-recovery.ts +5 -3
  198. package/src/client/session-replay.ts +3 -3
  199. package/src/client/settings/SettingsPanel.tsx +15 -6
  200. package/src/client/transcription/use-live-transcription.ts +64 -45
  201. package/src/deploy/build.ts +2 -1
  202. package/src/guards/db-tool-scoping.ts +1 -1
  203. package/src/integrations/adapters/slack.ts +84 -5
  204. package/src/integrations/index.ts +5 -1
  205. package/src/localization/default-messages.ts +1 -1
  206. package/src/mcp-client/oauth-routes.ts +45 -12
  207. package/src/server/realtime-voice.ts +4 -1
  208. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +7 -5
  209. package/src/terminal/cli-registry.ts +1 -1
  210. package/src/vite/client.ts +166 -1
  211. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +0 -115
  212. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +0 -177
  213. package/corpus/templates/crm/.agents/skills/crm/SKILL.md +0 -128
  214. package/corpus/templates/crm/.agents/skills/customizing-agent-native/SKILL.md +0 -220
  215. package/corpus/templates/crm/.agents/skills/feature-flags/SKILL.md +0 -169
  216. package/corpus/templates/crm/.agents/skills/upgrade-agent-native/SKILL.md +0 -100
  217. package/corpus/templates/crm/.env.example +0 -5
  218. package/corpus/templates/crm/AGENTS.md +0 -120
  219. package/corpus/templates/crm/CHANGELOG.md +0 -1
  220. package/corpus/templates/crm/DEVELOPING.md +0 -66
  221. package/corpus/templates/crm/README.md +0 -106
  222. package/corpus/templates/crm/_gitignore +0 -12
  223. package/corpus/templates/crm/actions/_crm-action-utils.ts +0 -87
  224. package/corpus/templates/crm/actions/_crm-dashboard.ts +0 -69
  225. package/corpus/templates/crm/actions/_crm-data-program-actions.ts +0 -15
  226. package/corpus/templates/crm/actions/_crm-signal-utils.ts +0 -79
  227. package/corpus/templates/crm/actions/apply-crm-proposals.ts +0 -203
  228. package/corpus/templates/crm/actions/attach-call-evidence.ts +0 -170
  229. package/corpus/templates/crm/actions/configure-crm-connection.ts +0 -126
  230. package/corpus/templates/crm/actions/configure-native-crm.ts +0 -44
  231. package/corpus/templates/crm/actions/create-crm-record.ts +0 -148
  232. package/corpus/templates/crm/actions/create-crm-signal-tracker.ts +0 -58
  233. package/corpus/templates/crm/actions/delete-staged-dataset.ts +0 -14
  234. package/corpus/templates/crm/actions/get-crm-automation-recipe.ts +0 -36
  235. package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +0 -35
  236. package/corpus/templates/crm/actions/get-crm-dashboard.ts +0 -14
  237. package/corpus/templates/crm/actions/get-crm-overview.ts +0 -13
  238. package/corpus/templates/crm/actions/get-crm-pipeline-data.ts +0 -61
  239. package/corpus/templates/crm/actions/get-crm-record.ts +0 -75
  240. package/corpus/templates/crm/actions/install-crm-pipeline-dashboard.ts +0 -81
  241. package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +0 -15
  242. package/corpus/templates/crm/actions/list-crm-dashboards.ts +0 -15
  243. package/corpus/templates/crm/actions/list-crm-proposals.ts +0 -31
  244. package/corpus/templates/crm/actions/list-crm-records.ts +0 -79
  245. package/corpus/templates/crm/actions/list-crm-saved-views.ts +0 -15
  246. package/corpus/templates/crm/actions/list-crm-signal-hits.ts +0 -43
  247. package/corpus/templates/crm/actions/list-crm-signal-trackers.ts +0 -32
  248. package/corpus/templates/crm/actions/list-crm-tasks.ts +0 -22
  249. package/corpus/templates/crm/actions/list-staged-datasets.ts +0 -14
  250. package/corpus/templates/crm/actions/list-workspace-connections.ts +0 -47
  251. package/corpus/templates/crm/actions/manage-crm-signal-tracker.ts +0 -87
  252. package/corpus/templates/crm/actions/manage-crm-task.ts +0 -132
  253. package/corpus/templates/crm/actions/navigate.ts +0 -63
  254. package/corpus/templates/crm/actions/provider-api-catalog.ts +0 -22
  255. package/corpus/templates/crm/actions/provider-api-docs.ts +0 -54
  256. package/corpus/templates/crm/actions/provider-api-request.ts +0 -92
  257. package/corpus/templates/crm/actions/query-staged-dataset.ts +0 -44
  258. package/corpus/templates/crm/actions/record-crm-call-insight.ts +0 -160
  259. package/corpus/templates/crm/actions/record-crm-smart-signal.ts +0 -150
  260. package/corpus/templates/crm/actions/restore-crm-dashboard-revision.ts +0 -23
  261. package/corpus/templates/crm/actions/review-crm-signal.ts +0 -31
  262. package/corpus/templates/crm/actions/run-crm-saved-view-program.ts +0 -103
  263. package/corpus/templates/crm/actions/run-crm-signal-trackers.ts +0 -275
  264. package/corpus/templates/crm/actions/run.ts +0 -7
  265. package/corpus/templates/crm/actions/save-crm-dashboard.ts +0 -51
  266. package/corpus/templates/crm/actions/save-crm-saved-view.ts +0 -119
  267. package/corpus/templates/crm/actions/sync-crm.ts +0 -146
  268. package/corpus/templates/crm/actions/update-crm-record.ts +0 -510
  269. package/corpus/templates/crm/actions/view-screen.ts +0 -218
  270. package/corpus/templates/crm/agent-native.app-skill.json +0 -58
  271. package/corpus/templates/crm/app/components/crm/CreateCrmRecordDialog.tsx +0 -158
  272. package/corpus/templates/crm/app/components/crm/CrmDashboardPanel.tsx +0 -78
  273. package/corpus/templates/crm/app/components/crm/CrmSignalsPanel.tsx +0 -226
  274. package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +0 -414
  275. package/corpus/templates/crm/app/components/crm/RecordActions.tsx +0 -510
  276. package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +0 -134
  277. package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +0 -362
  278. package/corpus/templates/crm/app/components/crm/SavedViewDataProgram.tsx +0 -93
  279. package/corpus/templates/crm/app/components/crm/Surface.tsx +0 -97
  280. package/corpus/templates/crm/app/components/crm/WorkOverview.tsx +0 -180
  281. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +0 -112
  282. package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +0 -84
  283. package/corpus/templates/crm/app/components/ui/alert-dialog.tsx +0 -1
  284. package/corpus/templates/crm/app/components/ui/badge.tsx +0 -1
  285. package/corpus/templates/crm/app/components/ui/button.tsx +0 -1
  286. package/corpus/templates/crm/app/components/ui/card.tsx +0 -1
  287. package/corpus/templates/crm/app/components/ui/dialog.tsx +0 -1
  288. package/corpus/templates/crm/app/components/ui/input.tsx +0 -1
  289. package/corpus/templates/crm/app/components/ui/label.tsx +0 -1
  290. package/corpus/templates/crm/app/components/ui/select.tsx +0 -1
  291. package/corpus/templates/crm/app/components/ui/sheet.tsx +0 -1
  292. package/corpus/templates/crm/app/components/ui/skeleton.tsx +0 -1
  293. package/corpus/templates/crm/app/components/ui/switch.tsx +0 -1
  294. package/corpus/templates/crm/app/components/ui/table.tsx +0 -1
  295. package/corpus/templates/crm/app/components/ui/tabs.tsx +0 -1
  296. package/corpus/templates/crm/app/components/ui/textarea.tsx +0 -1
  297. package/corpus/templates/crm/app/components/ui/toolkit-provider.tsx +0 -17
  298. package/corpus/templates/crm/app/design-system.ts +0 -3
  299. package/corpus/templates/crm/app/entry.client.tsx +0 -16
  300. package/corpus/templates/crm/app/entry.server.tsx +0 -10
  301. package/corpus/templates/crm/app/global.css +0 -167
  302. package/corpus/templates/crm/app/hooks/use-navigation-state.ts +0 -60
  303. package/corpus/templates/crm/app/i18n/en-US.ts +0 -89
  304. package/corpus/templates/crm/app/i18n/index.ts +0 -34
  305. package/corpus/templates/crm/app/lib/dashboard.ts +0 -13
  306. package/corpus/templates/crm/app/lib/navigation.ts +0 -54
  307. package/corpus/templates/crm/app/lib/tab-id.ts +0 -1
  308. package/corpus/templates/crm/app/lib/types.ts +0 -172
  309. package/corpus/templates/crm/app/lib/utils.ts +0 -1
  310. package/corpus/templates/crm/app/root.tsx +0 -91
  311. package/corpus/templates/crm/app/routes/_index.tsx +0 -26
  312. package/corpus/templates/crm/app/routes/accounts.tsx +0 -41
  313. package/corpus/templates/crm/app/routes/agent.tsx +0 -5
  314. package/corpus/templates/crm/app/routes/ask.tsx +0 -53
  315. package/corpus/templates/crm/app/routes/dashboard.tsx +0 -118
  316. package/corpus/templates/crm/app/routes/opportunities.tsx +0 -41
  317. package/corpus/templates/crm/app/routes/people.tsx +0 -41
  318. package/corpus/templates/crm/app/routes/proposals.tsx +0 -266
  319. package/corpus/templates/crm/app/routes/records.$recordId.tsx +0 -35
  320. package/corpus/templates/crm/app/routes/settings.tsx +0 -63
  321. package/corpus/templates/crm/app/routes/setup.tsx +0 -308
  322. package/corpus/templates/crm/app/routes/tasks.tsx +0 -252
  323. package/corpus/templates/crm/app/routes/views.tsx +0 -333
  324. package/corpus/templates/crm/app/routes.ts +0 -17
  325. package/corpus/templates/crm/app/vite-env.d.ts +0 -6
  326. package/corpus/templates/crm/changelog/2026-07-21-agent-native-crm.md +0 -6
  327. package/corpus/templates/crm/changelog/2026-07-21-clips-call-evidence-review-recipe.md +0 -6
  328. package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-find-and-review-evidence-grounded-call-signals-w.md +0 -6
  329. package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-manage-keyword-and-smart-call-signal-trackers-fr.md +0 -6
  330. package/corpus/templates/crm/changelog/2026-07-21-delegated-local-crm-automation.md +0 -6
  331. package/corpus/templates/crm/changelog/2026-07-21-native-sql.md +0 -6
  332. package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboard.md +0 -6
  333. package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboards-now-install-correctly-from-the-crm-actio.md +0 -6
  334. package/corpus/templates/crm/changelog/2026-07-21-salesforce-connection.md +0 -6
  335. package/corpus/templates/crm/changelog/2026-07-22-crm-field-validation-now-explains-which-fields-cannot-be-edi.md +0 -6
  336. package/corpus/templates/crm/changelog/2026-07-22-fixed-hubspot-contact-syncs-missing-records-updated-after-th.md +0 -6
  337. package/corpus/templates/crm/changelog/2026-07-22-fixed-pipeline-dashboard-panels-so-their-opportunity-data-lo.md +0 -6
  338. package/corpus/templates/crm/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +0 -6
  339. package/corpus/templates/crm/components.json +0 -20
  340. package/corpus/templates/crm/docs/architecture/crm-contract.md +0 -180
  341. package/corpus/templates/crm/learnings.defaults.md +0 -5
  342. package/corpus/templates/crm/package.json +0 -59
  343. package/corpus/templates/crm/public/favicon.svg +0 -1
  344. package/corpus/templates/crm/public/icon-180.svg +0 -1
  345. package/corpus/templates/crm/public/manifest.json +0 -11
  346. package/corpus/templates/crm/react-router.config.ts +0 -7
  347. package/corpus/templates/crm/server/crm/adapter.ts +0 -32
  348. package/corpus/templates/crm/server/crm/crm-field-firewall.ts +0 -64
  349. package/corpus/templates/crm/server/crm/crm-mirror.ts +0 -711
  350. package/corpus/templates/crm/server/crm/hubspot-adapter.ts +0 -1146
  351. package/corpus/templates/crm/server/crm/native-adapter.ts +0 -1715
  352. package/corpus/templates/crm/server/crm/read-through.ts +0 -207
  353. package/corpus/templates/crm/server/crm/salesforce-adapter.ts +0 -1255
  354. package/corpus/templates/crm/server/db/crm-store.ts +0 -1170
  355. package/corpus/templates/crm/server/db/index.ts +0 -169
  356. package/corpus/templates/crm/server/db/schema.ts +0 -441
  357. package/corpus/templates/crm/server/lib/intelligence/default-detectors.ts +0 -65
  358. package/corpus/templates/crm/server/lib/intelligence/evidence.ts +0 -105
  359. package/corpus/templates/crm/server/lib/intelligence/keyword-detector.ts +0 -100
  360. package/corpus/templates/crm/server/lib/intelligence/smart-detector.ts +0 -144
  361. package/corpus/templates/crm/server/lib/intelligence/summary.ts +0 -141
  362. package/corpus/templates/crm/server/lib/provider-api.ts +0 -64
  363. package/corpus/templates/crm/server/middleware/auth.ts +0 -4
  364. package/corpus/templates/crm/server/plugins/agent-chat.ts +0 -68
  365. package/corpus/templates/crm/server/plugins/auth.ts +0 -14
  366. package/corpus/templates/crm/server/plugins/core-routes.ts +0 -17
  367. package/corpus/templates/crm/server/plugins/db.ts +0 -454
  368. package/corpus/templates/crm/server/routes/[...page].get.ts +0 -5
  369. package/corpus/templates/crm/shared/crm-automation-recipes.ts +0 -132
  370. package/corpus/templates/crm/shared/crm-contract.ts +0 -254
  371. package/corpus/templates/crm/shared/crm-sales-config.ts +0 -63
  372. package/corpus/templates/crm/ssr-entry.ts +0 -11
  373. package/corpus/templates/crm/tsconfig.json +0 -24
  374. package/corpus/templates/crm/vite.config.ts +0 -15
  375. package/corpus/templates/crm/vitest.config.ts +0 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.118.0",
3
+ "version": "0.118.1",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -390,7 +390,7 @@
390
390
  "yjs": "^13.6.31",
391
391
  "zod": "^4.3.6",
392
392
  "@agent-native/recap-cli": "0.5.1",
393
- "@agent-native/toolkit": "^0.10.0"
393
+ "@agent-native/toolkit": "^0.10.1"
394
394
  },
395
395
  "devDependencies": {
396
396
  "@ai-sdk/anthropic": "^3.0.71",
package/src/a2a/client.ts CHANGED
@@ -14,6 +14,8 @@ import type {
14
14
  Task,
15
15
  } from "./types.js";
16
16
 
17
+ const DEFAULT_A2A_POLL_REQUEST_TIMEOUT_MS = 15_000;
18
+
17
19
  export class A2ATaskTimeoutError extends Error {
18
20
  readonly taskId: string;
19
21
  readonly lastTask: Task;
@@ -171,6 +173,7 @@ export class A2AClient {
171
173
  private async rpc(
172
174
  method: string,
173
175
  params: Record<string, unknown>,
176
+ options?: { requestTimeoutMs?: number },
174
177
  ): Promise<JsonRpcResponse> {
175
178
  const body: JsonRpcRequest = {
176
179
  jsonrpc: "2.0",
@@ -186,7 +189,12 @@ export class A2AClient {
186
189
  for (let i = 0; i < this.apiKeyAttempts.length; i++) {
187
190
  console.log(`[A2A Client] POST ${url} method=${method}`);
188
191
  const startTime = Date.now();
189
- const res = await this.postJson(url, body, this.apiKeyAttempts[i]);
192
+ const res = await this.postJson(
193
+ url,
194
+ body,
195
+ this.apiKeyAttempts[i],
196
+ options?.requestTimeoutMs,
197
+ );
190
198
  console.log(
191
199
  `[A2A Client] Response: ${res.status} in ${Date.now() - startTime}ms`,
192
200
  );
@@ -278,8 +286,15 @@ export class A2AClient {
278
286
  /**
279
287
  * Poll for a task by id. Used in async mode after `send({ async: true })`.
280
288
  */
281
- async getTask(taskId: string): Promise<Task> {
282
- const response = await this.rpc("tasks/get", { id: taskId });
289
+ async getTask(
290
+ taskId: string,
291
+ opts?: { requestTimeoutMs?: number },
292
+ ): Promise<Task> {
293
+ const response = await this.rpc(
294
+ "tasks/get",
295
+ { id: taskId },
296
+ { requestTimeoutMs: opts?.requestTimeoutMs },
297
+ );
283
298
  if (response.error) {
284
299
  throw new Error(
285
300
  `A2A error (${response.error.code}): ${response.error.message}`,
@@ -392,9 +407,17 @@ export class A2AClient {
392
407
 
393
408
  let current = submitted;
394
409
  while (Date.now() < deadline) {
395
- await new Promise((r) => setTimeout(r, pollMs));
410
+ const sleepMs = Math.min(pollMs, Math.max(0, deadline - Date.now()));
411
+ await new Promise((r) => setTimeout(r, sleepMs));
412
+ const remainingMs = deadline - Date.now();
413
+ if (remainingMs <= 0) break;
396
414
  try {
397
- current = await this.getTask(submitted.id);
415
+ current = await this.getTask(submitted.id, {
416
+ requestTimeoutMs: Math.min(
417
+ this.requestTimeoutMs ?? DEFAULT_A2A_POLL_REQUEST_TIMEOUT_MS,
418
+ remainingMs,
419
+ ),
420
+ });
398
421
  opts?.onUpdate?.(current);
399
422
  } catch {
400
423
  // Transient fetch failure — keep polling until the deadline.
@@ -509,13 +532,12 @@ export class A2AClient {
509
532
  url: string,
510
533
  body: JsonRpcRequest,
511
534
  apiKey = this.apiKey,
535
+ requestTimeoutMs = this.requestTimeoutMs,
512
536
  ): Promise<Response> {
513
- const controller = this.requestTimeoutMs
514
- ? new AbortController()
515
- : undefined;
537
+ const controller = requestTimeoutMs ? new AbortController() : undefined;
516
538
  const timer =
517
- controller && this.requestTimeoutMs
518
- ? setTimeout(() => controller.abort(), this.requestTimeoutMs)
539
+ controller && requestTimeoutMs
540
+ ? setTimeout(() => controller.abort(), requestTimeoutMs)
519
541
  : undefined;
520
542
  try {
521
543
  return await ssrfSafeFetch(
package/src/cli/index.ts CHANGED
@@ -203,12 +203,12 @@ function parseScaffoldArgs(argv: string[]): {
203
203
  // Track CLI usage (best-effort, non-blocking)
204
204
  function trackCli(event: string, props?: Record<string, unknown>): void {
205
205
  try {
206
- import("../tracking/registry.js").then((m) => {
207
- m.track(event, { command, ...props });
208
- });
209
- import("../tracking/providers.js").then((m) =>
210
- m.registerBuiltinProviders(),
211
- );
206
+ void import("../tracking/registry.js")
207
+ .then((m) => m.track(event, { command, ...props }))
208
+ .catch(() => undefined);
209
+ void import("../tracking/providers.js")
210
+ .then((m) => m.registerBuiltinProviders())
211
+ .catch(() => undefined);
212
212
  } catch {}
213
213
  }
214
214
 
@@ -219,7 +219,9 @@ process.on("uncaughtException", (err) => {
219
219
  console.error(` Send feedback: ${FEEDBACK_URL}\n`);
220
220
  trackCli("cli.crash", { error: err.message });
221
221
  Sentry.captureException(err);
222
- Sentry.flush(2000).finally(() => process.exit(1));
222
+ void Sentry.flush(2000)
223
+ .catch(() => undefined)
224
+ .finally(() => process.exit(1));
223
225
  });
224
226
 
225
227
  process.on("unhandledRejection", (reason: any) => {
@@ -228,7 +230,9 @@ process.on("unhandledRejection", (reason: any) => {
228
230
  console.error(` Send feedback: ${FEEDBACK_URL}\n`);
229
231
  trackCli("cli.crash", { error: reason?.message ?? String(reason) });
230
232
  Sentry.captureException(reason);
231
- Sentry.flush(2000).finally(() => process.exit(1));
233
+ void Sentry.flush(2000)
234
+ .catch(() => undefined)
235
+ .finally(() => process.exit(1));
232
236
  });
233
237
 
234
238
  // Surface a self-heal hint when an interrupted `npx @agent-native/core@latest ...`
@@ -961,14 +965,18 @@ switch (command) {
961
965
  }
962
966
 
963
967
  case "setup-agents": {
964
- import("./setup-agents.js").then((m) => m.runSetupAgents());
968
+ import("./setup-agents.js")
969
+ .then((m) => m.runSetupAgents())
970
+ .catch(handleScaffoldImportError);
965
971
  break;
966
972
  }
967
973
 
968
974
  case "info": {
969
975
  // Print read-only info about an installable package (e.g. @agent-native/scheduling).
970
976
  // Lists subpath exports, source paths in node_modules, and docs pointers.
971
- import("./info.js").then((m) => m.runInfo(args[0]));
977
+ import("./info.js")
978
+ .then((m) => m.runInfo(args[0]))
979
+ .catch(handleScaffoldImportError);
972
980
  break;
973
981
  }
974
982
 
@@ -438,8 +438,8 @@ export function transitionStoredMultiFrontierRun(
438
438
  const isFullStoredRun = hasStoredRunTimestamps(candidate);
439
439
  if (
440
440
  !isFullStoredRun &&
441
- (Object.hasOwn(candidate, "createdAt") ||
442
- Object.hasOwn(candidate, "updatedAt"))
441
+ (Object.prototype.hasOwnProperty.call(candidate, "createdAt") ||
442
+ Object.prototype.hasOwnProperty.call(candidate, "updatedAt"))
443
443
  ) {
444
444
  throw new Error("Invalid multi-frontier coordinator transition state.");
445
445
  }
@@ -1056,7 +1056,9 @@ function isCompleteMultiFrontierRunState(
1056
1056
 
1057
1057
  function normalizeStoredRunDefaults(value: unknown): unknown {
1058
1058
  if (!value || typeof value !== "object" || Array.isArray(value)) return value;
1059
- if (!Object.hasOwn(value, "autoContinueAfterAgreement")) {
1059
+ if (
1060
+ !Object.prototype.hasOwnProperty.call(value, "autoContinueAfterAgreement")
1061
+ ) {
1060
1062
  return { ...value, autoContinueAfterAgreement: false };
1061
1063
  }
1062
1064
  return value;
@@ -228,18 +228,6 @@ export const TEMPLATES: TemplateMeta[] = [
228
228
  hidden: true,
229
229
  core: false,
230
230
  },
231
- {
232
- name: "crm",
233
- label: "CRM",
234
- hint: "Agent-native CRM companion with scoped HubSpot intelligence, workflows, and write proposals",
235
- icon: "Users",
236
- color: "#2563EB",
237
- colorRgb: "37 99 235",
238
- devPort: 8107,
239
- hidden: true,
240
- defaultMode: "dev",
241
- core: false,
242
- },
243
231
  {
244
232
  name: "macros",
245
233
  label: "Macros",
@@ -465,7 +465,7 @@ function probeHttpReady(
465
465
  },
466
466
  (res) => {
467
467
  res.resume();
468
- finish(true);
468
+ finish((res.statusCode ?? 500) < 500);
469
469
  },
470
470
  );
471
471
  req.setTimeout(timeoutMs, () => finish(false));
@@ -2673,7 +2673,7 @@ export function AgentChatSurface({
2673
2673
  const defaultShowPageNewChatButton =
2674
2674
  shouldDefaultAgentChatSurfacePageNewChatButton(mode, showTabBar);
2675
2675
 
2676
- return (
2676
+ const panel = (
2677
2677
  <AgentPanel
2678
2678
  {...props}
2679
2679
  defaultMode={defaultMode}
@@ -2697,6 +2697,14 @@ export function AgentChatSurface({
2697
2697
  }
2698
2698
  />
2699
2699
  );
2700
+
2701
+ if (!pageMode) return panel;
2702
+ return (
2703
+ <>
2704
+ <URLSync browserTabId={props.browserTabId} />
2705
+ {panel}
2706
+ </>
2707
+ );
2700
2708
  }
2701
2709
 
2702
2710
  // ─── AgentSidebar — wraps content with a toggleable agent panel ─────────────
@@ -45,11 +45,9 @@ export interface RunStuckBannerProps {
45
45
  * `chatHandle.hasInFlightWork()`. "No progress" for a stretch of time does
46
46
  * not mean the run is dead: a long provider query or a cross-app `call
47
47
  * agent` can legitimately emit nothing for minutes. When this returns
48
- * true, Retry (which aborts the run) is hidden — aborting would destroy
49
- * real in-flight work and re-execute the same long call from scratch.
50
- * Only Cancel, an explicit destructive choice, remains available. Checked
51
- * fresh on every render; omit to keep the unconditional Retry/Cancel
52
- * behavior.
48
+ * true, the stuck warning is hidden — aborting would destroy real in-flight
49
+ * work and re-execute the same long call from scratch. Checked fresh on every
50
+ * render; omit to keep the unconditional Retry/Cancel behavior.
53
51
  */
54
52
  hasInFlightWork?: () => boolean;
55
53
  /**
@@ -191,9 +189,9 @@ export function RunStuckBanner({
191
189
  const backgroundWorkerStillAlive = isFreshBackgroundWorker(state);
192
190
  // A live tool call or sub-agent (A2A) call means "no progress" is not the
193
191
  // same as "dead" — the process is genuinely still doing the user's work.
194
- // Retry aborts the run, so it must not be offered as the (implicitly
195
- // safe-looking) primary action while real work is in flight; see the
196
- // `hasInFlightWork` prop doc comment. Re-checked on every render (the
192
+ // Retry aborts the run, so the stuck warning stays out of the way while real
193
+ // work is in flight; see the `hasInFlightWork` prop doc comment. Re-checked
194
+ // on every render (the
197
195
  // underlying source mutates in place as tool/agent-call events stream in),
198
196
  // which is why this is a function prop rather than a plain boolean.
199
197
  //
@@ -308,7 +306,18 @@ export function RunStuckBanner({
308
306
  threadId,
309
307
  ]);
310
308
 
311
- if (!state.isStuck || !state.runId) return null;
309
+ // A stale progress timestamp is not actionable while the server is still
310
+ // heartbeating or an unresolved tool/A2A call is known to be running. Keep
311
+ // those healthy long-running states in the chat's inline activity UI; the
312
+ // warning is reserved for runs that may actually need recovery.
313
+ if (
314
+ !state.isStuck ||
315
+ !state.runId ||
316
+ backgroundWorkerStillAlive ||
317
+ inFlightWork
318
+ ) {
319
+ return null;
320
+ }
312
321
 
313
322
  const handleCancel = async () => {
314
323
  if (!state.runId || busy.type !== "none") return;
@@ -323,9 +332,9 @@ export function RunStuckBanner({
323
332
  };
324
333
 
325
334
  const handleRetry = async () => {
326
- // Defense in depth: Retry is hidden while a background worker is still
327
- // heartbeating or work is explicitly in flight (see render below). Guard
328
- // the handler too so this path cannot abort a run the server says is alive.
335
+ // Defense in depth: the banner is hidden while a background worker is
336
+ // still heartbeating or work is explicitly in flight. Guard the handler
337
+ // too so a render transition cannot abort a run the server says is alive.
329
338
  if (
330
339
  !state.runId ||
331
340
  busy.type !== "none" ||
@@ -350,8 +359,6 @@ export function RunStuckBanner({
350
359
  const stuckSeconds =
351
360
  state.stuckSinceMs != null ? Math.floor(state.stuckSinceMs / 1000) : null;
352
361
 
353
- const stillWorking = backgroundWorkerStillAlive || inFlightWork;
354
-
355
362
  return (
356
363
  <div
357
364
  role="status"
@@ -368,51 +375,36 @@ export function RunStuckBanner({
368
375
  />
369
376
  <div className="flex min-w-0 flex-1 flex-col gap-1.5">
370
377
  <div className="leading-snug">
371
- <span className="font-medium">
372
- {stillWorking
373
- ? "The agent is still working."
374
- : "This chat looks stuck."}
375
- </span>{" "}
378
+ <span className="font-medium">This chat looks stuck.</span>{" "}
376
379
  <span className="text-muted-foreground">
377
380
  No progress
378
- {stuckSeconds != null ? ` for ${stuckSeconds}s` : ""}.{" "}
379
- {inFlightWork
380
- ? "It's waiting on a call to another app or a long tool — canceling will stop that work."
381
- : backgroundWorkerStillAlive
382
- ? "The background worker is still alive; large updates can take a few minutes."
383
- : "The agent may have hit a server timeout or lost its connection."}
381
+ {stuckSeconds != null ? ` for ${stuckSeconds}s` : ""}. The agent may
382
+ have hit a server timeout or lost its connection.
384
383
  {autoRetry && busyType === "retry"
385
384
  ? " Retrying automatically now."
386
385
  : ""}
387
386
  </span>
388
387
  </div>
389
388
  <div className="flex flex-wrap items-center gap-2">
390
- {stillWorking ? null : (
391
- <button
392
- type="button"
393
- onClick={handleRetry}
394
- disabled={busyType !== "none"}
395
- className="inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md bg-foreground px-2.5 text-[11px] font-medium text-background transition-colors hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60"
396
- >
397
- {busyType === "retry" ? (
398
- <IconLoader2
399
- size={12}
400
- className="animate-spin"
401
- aria-hidden="true"
402
- />
403
- ) : null}
404
- Retry
405
- </button>
406
- )}
389
+ <button
390
+ type="button"
391
+ onClick={handleRetry}
392
+ disabled={busyType !== "none"}
393
+ className="inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md bg-foreground px-2.5 text-[11px] font-medium text-background transition-colors hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60"
394
+ >
395
+ {busyType === "retry" ? (
396
+ <IconLoader2
397
+ size={12}
398
+ className="animate-spin"
399
+ aria-hidden="true"
400
+ />
401
+ ) : null}
402
+ Retry
403
+ </button>
407
404
  <button
408
405
  type="button"
409
406
  onClick={handleCancel}
410
407
  disabled={busyType !== "none"}
411
- title={
412
- inFlightWork
413
- ? "Stop the in-progress run. Work that hasn't finished will be lost."
414
- : undefined
415
- }
416
408
  className="inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-[11px] font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-60"
417
409
  >
418
410
  {busyType === "cancel" ? (
@@ -0,0 +1,32 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { ACTION_CHAT_UI_INLINE_EXTENSION_RENDERER } from "../../action-ui.js";
4
+ import { cn } from "../utils.js";
5
+ import type { ToolRendererContext } from "./tool-render-registry.js";
6
+
7
+ export function ActionChatUiSurface({
8
+ context,
9
+ isBuiltinDataWidget,
10
+ children,
11
+ }: {
12
+ context: ToolRendererContext;
13
+ isBuiltinDataWidget: boolean;
14
+ children: ReactNode;
15
+ }) {
16
+ if (!context.chatUI || isBuiltinDataWidget) return <>{children}</>;
17
+
18
+ const containsPaddedIframe =
19
+ context.chatUI.renderer === ACTION_CHAT_UI_INLINE_EXTENSION_RENDERER;
20
+
21
+ return (
22
+ <div
23
+ data-agent-native-custom-ui=""
24
+ className={cn(
25
+ "my-3 overflow-hidden rounded-lg border border-border bg-card text-card-foreground shadow-sm empty:hidden",
26
+ !containsPaddedIframe && "p-3",
27
+ )}
28
+ >
29
+ {children}
30
+ </div>
31
+ );
32
+ }
@@ -122,6 +122,9 @@ interface FormattedMessageTimestamp {
122
122
  full: string;
123
123
  }
124
124
 
125
+ const messageFooterFadeClassName =
126
+ "opacity-0 transition-[color,opacity] duration-150 group-hover:opacity-100 group-focus-within:opacity-100";
127
+
125
128
  function coerceMessageDate(value: unknown): Date | null {
126
129
  if (value instanceof Date) {
127
130
  return Number.isNaN(value.getTime()) ? null : value;
@@ -793,7 +796,7 @@ export function UserMessage() {
793
796
  {timestamp && (
794
797
  <MessageTimestamp
795
798
  timestamp={timestamp}
796
- className="opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100"
799
+ className={messageFooterFadeClassName}
797
800
  />
798
801
  )}
799
802
  </div>
@@ -845,12 +848,33 @@ export function messageTextFromContent(content: unknown): string {
845
848
  .join("\n");
846
849
  }
847
850
 
848
- function latestUserMessageText(messages: readonly unknown[]): string {
851
+ export function latestUserMessageText(messages: readonly unknown[]): string {
849
852
  for (let index = messages.length - 1; index >= 0; index -= 1) {
850
853
  const message = messages[index];
851
854
  if (!message || typeof message !== "object") continue;
852
855
  const record = message as { role?: unknown; content?: unknown };
853
- if (record.role === "user") return messageTextFromContent(record.content);
856
+ if (record.role !== "user" || isHiddenUserMessage(message)) continue;
857
+ return displayableUserMessageText(messageTextFromContent(record.content));
858
+ }
859
+ return "";
860
+ }
861
+
862
+ export function userMessageTextBeforeAssistant(
863
+ messages: readonly unknown[],
864
+ assistantMessageId: string,
865
+ ): string {
866
+ const assistantIndex = messages.findIndex((message) => {
867
+ if (!message || typeof message !== "object") return false;
868
+ return (message as { id?: unknown }).id === assistantMessageId;
869
+ });
870
+ if (assistantIndex < 1) return "";
871
+
872
+ for (let index = assistantIndex - 1; index >= 0; index -= 1) {
873
+ const message = messages[index];
874
+ if (!message || typeof message !== "object") continue;
875
+ const record = message as { role?: unknown; content?: unknown };
876
+ if (record.role !== "user" || isHiddenUserMessage(message)) continue;
877
+ return displayableUserMessageText(messageTextFromContent(record.content));
854
878
  }
855
879
  return "";
856
880
  }
@@ -907,6 +931,22 @@ export function assistantMessageHasCompletedCustomUi(
907
931
  return hasCompletedTool && lastCompletedToolIsCustomUi;
908
932
  }
909
933
 
934
+ export function assistantMessageHasCustomUi(content: unknown): boolean {
935
+ if (!Array.isArray(content)) return false;
936
+ return content.some((part) => {
937
+ if (!part || typeof part !== "object") return false;
938
+ const record = part as {
939
+ type?: unknown;
940
+ chatUI?: unknown;
941
+ mcpApp?: unknown;
942
+ };
943
+ return (
944
+ record.type === "tool-call" &&
945
+ (record.chatUI !== undefined || record.mcpApp !== undefined)
946
+ );
947
+ });
948
+ }
949
+
910
950
  // Only the last assistant message may shimmer as "the currently running
911
951
  // tool" — an older message's dangling unresolved tool-call must never
912
952
  // shimmer once a later run is active.
@@ -1173,13 +1213,17 @@ export function AssistantMessage() {
1173
1213
  const hasCompletedCustomUi = assistantMessageHasCompletedCustomUi(
1174
1214
  msg.content,
1175
1215
  );
1216
+ const hasCustomUi = assistantMessageHasCustomUi(msg.content);
1176
1217
  const showMissingFinalResponse = shouldShowMissingFinalResponse({
1177
1218
  statusIsTerminal,
1178
1219
  hasAssistantText: responseConnectionText.trim().length > 0,
1179
1220
  hasUnresolvedTool,
1180
1221
  hasCompletedCustomUi,
1181
1222
  });
1182
- const responseConnectionContext = latestUserMessageText(thread.messages);
1223
+ const responseConnectionContext = userMessageTextBeforeAssistant(
1224
+ thread.messages,
1225
+ msg.id,
1226
+ );
1183
1227
  const isComplete = shouldShowAssistantMessageFooter({
1184
1228
  isLast,
1185
1229
  chatRunning,
@@ -1327,7 +1371,8 @@ export function AssistantMessage() {
1327
1371
  return (
1328
1372
  <WorkedForSummary
1329
1373
  durationMs={capturedDurationMs}
1330
- autoCollapse={animateCollapse}
1374
+ defaultOpen={hasCustomUi}
1375
+ autoCollapse={animateCollapse && !hasCustomUi}
1331
1376
  >
1332
1377
  {children}
1333
1378
  </WorkedForSummary>
@@ -1377,7 +1422,7 @@ export function AssistantMessage() {
1377
1422
  {isComplete && hasCodeAgentTools && msgContent && (
1378
1423
  <FilesChangedSummary parts={msgContent} />
1379
1424
  )}
1380
- {isComplete && isLast && (
1425
+ {isComplete && (
1381
1426
  <McpConnectionSuggestion
1382
1427
  text={responseConnectionText}
1383
1428
  contextText={responseConnectionContext}
@@ -1404,7 +1449,7 @@ export function AssistantMessage() {
1404
1449
  <button
1405
1450
  type="button"
1406
1451
  aria-label="Regenerate response"
1407
- className="flex h-6 w-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground/70 transition-colors duration-150 hover:bg-accent hover:text-foreground opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 disabled:cursor-not-allowed disabled:opacity-40"
1452
+ className={`flex h-6 w-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground ${messageFooterFadeClassName} disabled:cursor-not-allowed disabled:opacity-40`}
1408
1453
  >
1409
1454
  <IconRefresh className="h-3.5 w-3.5" />
1410
1455
  </button>
@@ -1420,7 +1465,7 @@ export function AssistantMessage() {
1420
1465
  {timestamp && (
1421
1466
  <MessageTimestamp
1422
1467
  timestamp={timestamp}
1423
- className="opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100"
1468
+ className={messageFooterFadeClassName}
1424
1469
  />
1425
1470
  )}
1426
1471
  </div>
@@ -48,6 +48,7 @@ import {
48
48
  isCallAgentToolCallShadowed,
49
49
  } from "../tool-display.js";
50
50
  import { cn } from "../utils.js";
51
+ import { ActionChatUiSurface } from "./action-chat-ui-surface.js";
51
52
  import {
52
53
  SmoothMarkdownText,
53
54
  HighlightedCodeBlock,
@@ -133,11 +134,10 @@ export function ToolActivityPresentation({
133
134
  animateEntry && "agent-tool-call--entering",
134
135
  )}
135
136
  data-running={isRunning ? "true" : undefined}
136
- data-active-tail={isActiveTail ? "true" : undefined}
137
137
  >
138
138
  {children}
139
139
  {isRunning && showLongRunningHint && (
140
- <div className="mt-0.5 px-2.5 text-[11px] leading-snug text-muted-foreground/80">
140
+ <div className="mt-0.5 px-2.5 pb-2 text-[11px] leading-snug text-muted-foreground/80">
141
141
  Still working. Large updates can take a minute or two.
142
142
  </div>
143
143
  )}
@@ -759,7 +759,16 @@ function ToolCallDisplayGeneric({
759
759
  (skipRegistryRenderer ? null : resolveToolRenderer(nativeToolContext)) ??
760
760
  resolveBuiltinFallbackToolRenderer(nativeToolContext));
761
761
  if (NativeToolRenderer) {
762
- return <NativeToolRenderer context={nativeToolContext} />;
762
+ return (
763
+ <ActionChatUiSurface
764
+ context={nativeToolContext}
765
+ isBuiltinDataWidget={isBuiltinDataWidgetActionRenderer(
766
+ nativeToolContext,
767
+ )}
768
+ >
769
+ <NativeToolRenderer context={nativeToolContext} />
770
+ </ActionChatUiSurface>
771
+ );
763
772
  }
764
773
 
765
774
  const inputPayload = hasArgs ? toolInputPayload(toolName, args) : null;
@@ -1252,22 +1261,28 @@ export function formatWorkedDuration(ms: number): string {
1252
1261
 
1253
1262
  export function WorkedForSummary({
1254
1263
  durationMs,
1264
+ defaultOpen = false,
1255
1265
  autoCollapse = false,
1256
1266
  children,
1257
1267
  }: {
1258
1268
  durationMs?: number | null;
1269
+ /** Keep completed work visible when the turn contains interactive UI. */
1270
+ defaultOpen?: boolean;
1259
1271
  /** When true, close the summary after a run has completed. */
1260
1272
  autoCollapse?: boolean;
1261
1273
  children: React.ReactNode;
1262
1274
  }) {
1263
- // Start closed so a remounted completed message never flashes its work
1264
- // details open while auto-collapse settles. If the summary was already
1265
- // open when autoCollapse changes, AnimatedCollapse still animates it shut.
1266
- const [open, setOpen] = useState(false);
1275
+ // Ordinary completed work starts closed so a remount never flashes details
1276
+ // while auto-collapse settles. Interactive UI opts into an open summary.
1277
+ const [open, setOpen] = useState(defaultOpen);
1267
1278
 
1268
1279
  useEffect(() => {
1269
- if (autoCollapse) setOpen(false);
1270
- }, [autoCollapse]);
1280
+ if (defaultOpen) {
1281
+ setOpen(true);
1282
+ } else if (autoCollapse) {
1283
+ setOpen(false);
1284
+ }
1285
+ }, [autoCollapse, defaultOpen]);
1271
1286
 
1272
1287
  const label =
1273
1288
  durationMs != null && durationMs >= 1000
@@ -17,7 +17,6 @@ export function InlineExtensionWidget({
17
17
 
18
18
  return (
19
19
  <InlineExtensionFrame
20
- className="my-1.5"
21
20
  extensionId={result.mode === "persisted" ? result.id : undefined}
22
21
  extension={{
23
22
  id: result.id,
@@ -126,11 +126,15 @@ function renderDataWidget(context: ToolRendererContext) {
126
126
  return null;
127
127
  }
128
128
 
129
- function BuiltinToolRendererSkeleton() {
129
+ function BuiltinToolRendererSkeleton({ framed = true }: { framed?: boolean }) {
130
130
  return (
131
131
  <div
132
132
  aria-label="Loading tool result"
133
- className="my-1.5 h-24 animate-pulse rounded-lg border border-border bg-muted/30"
133
+ className={
134
+ framed
135
+ ? "my-1.5 h-24 animate-pulse rounded-lg border border-border bg-muted/30"
136
+ : "h-24 animate-pulse bg-muted/30"
137
+ }
134
138
  />
135
139
  );
136
140
  }
@@ -140,7 +144,7 @@ const BuiltinDataWidgetRenderer: ToolRendererComponent = ({ context }) =>
140
144
 
141
145
  const BuiltinInlineExtensionRenderer: ToolRendererComponent = ({ context }) =>
142
146
  normalizeInlineExtensionToolResult(context) ? (
143
- <Suspense fallback={<BuiltinToolRendererSkeleton />}>
147
+ <Suspense fallback={<BuiltinToolRendererSkeleton framed={false} />}>
144
148
  <LazyInlineExtensionWidget context={context} />
145
149
  </Suspense>
146
150
  ) : null;