@agent-native/core 0.90.11 → 0.91.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 (315) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +22 -0
  3. package/corpus/core/docs/content/toolkit-settings.mdx +56 -3
  4. package/corpus/core/package.json +2 -1
  5. package/corpus/core/src/agent/run-ownership.ts +29 -1
  6. package/corpus/core/src/changelog/parse.ts +78 -0
  7. package/corpus/core/src/chat-threads/schema.ts +43 -0
  8. package/corpus/core/src/chat-threads/store.ts +144 -12
  9. package/corpus/core/src/cli/workspace-dev.ts +25 -5
  10. package/corpus/core/src/client/AgentPanel.tsx +79 -14
  11. package/corpus/core/src/client/AssistantChat.tsx +359 -425
  12. package/corpus/core/src/client/analytics-session.ts +70 -0
  13. package/corpus/core/src/client/analytics.ts +175 -49
  14. package/corpus/core/src/client/chat/message-components.tsx +22 -2
  15. package/corpus/core/src/client/components/ui/message-scroller.tsx +131 -0
  16. package/corpus/core/src/client/conversation/AgentConversation.tsx +63 -41
  17. package/corpus/core/src/client/error-capture.ts +616 -0
  18. package/corpus/core/src/client/index.ts +12 -0
  19. package/corpus/core/src/client/session-replay.ts +57 -7
  20. package/corpus/core/src/client/settings/SettingsPanel.tsx +123 -1
  21. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +292 -45
  22. package/corpus/core/src/client/settings/index.ts +1 -0
  23. package/corpus/core/src/client/sharing/ShareButton.tsx +14 -11
  24. package/corpus/core/src/client/sharing/ShareDialog.tsx +13 -10
  25. package/corpus/core/src/mcp/builtin-tools.ts +29 -2
  26. package/corpus/core/src/server/agent-chat-plugin.ts +174 -79
  27. package/corpus/core/src/server/onboarding-html.ts +28 -16
  28. package/corpus/core/src/sharing/actions/list-resource-shares.ts +45 -1
  29. package/corpus/core/src/sharing/actions/share-resource.ts +9 -0
  30. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  31. package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
  32. package/corpus/core/src/vite/client.ts +217 -35
  33. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +8 -7
  34. package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +14 -10
  35. package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +15 -15
  36. package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +1 -0
  37. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +38 -22
  38. package/corpus/templates/analytics/.agents/skills/data-programs/SKILL.md +114 -61
  39. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +1 -0
  40. package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +7 -7
  41. package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +1 -0
  42. package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +1 -1
  43. package/corpus/templates/analytics/.builder/skills/bigquery/SKILL.md +17 -17
  44. package/corpus/templates/analytics/.builder/skills/gcloud/SKILL.md +5 -5
  45. package/corpus/templates/analytics/.builder/skills/github/SKILL.md +7 -7
  46. package/corpus/templates/analytics/.builder/skills/gong/SKILL.md +12 -12
  47. package/corpus/templates/analytics/.builder/skills/grafana/SKILL.md +7 -7
  48. package/corpus/templates/analytics/.builder/skills/sentry/SKILL.md +7 -7
  49. package/corpus/templates/analytics/.builder/skills/slack/SKILL.md +6 -6
  50. package/corpus/templates/analytics/.builder/skills/stripe/SKILL.md +7 -7
  51. package/corpus/templates/analytics/AGENTS.md +47 -2
  52. package/corpus/templates/analytics/actions/add-status-page-monitor.ts +36 -0
  53. package/corpus/templates/analytics/actions/capture-test-error.ts +33 -0
  54. package/corpus/templates/analytics/actions/delete-monitor.ts +24 -0
  55. package/corpus/templates/analytics/actions/delete-status-page.ts +23 -0
  56. package/corpus/templates/analytics/actions/get-error-issue.ts +36 -0
  57. package/corpus/templates/analytics/actions/get-monitor-stats.ts +55 -0
  58. package/corpus/templates/analytics/actions/get-monitor.ts +27 -0
  59. package/corpus/templates/analytics/actions/get-public-status-page.ts +41 -0
  60. package/corpus/templates/analytics/actions/get-status-page.ts +29 -0
  61. package/corpus/templates/analytics/actions/list-error-issues.ts +40 -0
  62. package/corpus/templates/analytics/actions/list-monitors.ts +21 -0
  63. package/corpus/templates/analytics/actions/list-status-pages.ts +21 -0
  64. package/corpus/templates/analytics/actions/match-error-issues.ts +51 -0
  65. package/corpus/templates/analytics/actions/navigate.ts +58 -4
  66. package/corpus/templates/analytics/actions/remove-status-page-monitor.ts +22 -0
  67. package/corpus/templates/analytics/actions/reorder-status-page-monitors.ts +25 -0
  68. package/corpus/templates/analytics/actions/resolve-error-issue.ts +38 -0
  69. package/corpus/templates/analytics/actions/run-monitor-check.ts +23 -0
  70. package/corpus/templates/analytics/actions/save-analysis.ts +1 -0
  71. package/corpus/templates/analytics/actions/save-monitor.ts +145 -0
  72. package/corpus/templates/analytics/actions/save-status-page.ts +47 -0
  73. package/corpus/templates/analytics/actions/view-screen.ts +212 -0
  74. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
  75. package/corpus/templates/analytics/app/components/layout/Layout.tsx +10 -1
  76. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +134 -39
  77. package/corpus/templates/analytics/app/components/monitoring/PublicStatusView.tsx +351 -0
  78. package/corpus/templates/analytics/app/components/monitoring/ResponseTimeChart.tsx +174 -0
  79. package/corpus/templates/analytics/app/components/monitoring/UptimeStatCards.tsx +85 -0
  80. package/corpus/templates/analytics/app/components/monitoring/UptimeTimelineBars.tsx +106 -0
  81. package/corpus/templates/analytics/app/components/monitoring/chart-utils.ts +101 -0
  82. package/corpus/templates/analytics/app/components/monitoring/index.ts +28 -0
  83. package/corpus/templates/analytics/app/components/monitoring/types.ts +42 -0
  84. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +34 -0
  85. package/corpus/templates/analytics/app/i18n/zh-TW.ts +6 -0
  86. package/corpus/templates/analytics/app/i18n-data.ts +33 -0
  87. package/corpus/templates/analytics/app/pages/DataSources.tsx +28 -0
  88. package/corpus/templates/analytics/app/pages/Settings.tsx +77 -9
  89. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +3 -3
  90. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +7 -0
  91. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +205 -0
  92. package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +100 -0
  93. package/corpus/templates/analytics/app/pages/monitoring/UptimePanel.tsx +475 -0
  94. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +372 -0
  95. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +360 -0
  96. package/corpus/templates/analytics/app/pages/monitoring/errors/Sparkline.tsx +55 -0
  97. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +106 -0
  98. package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +75 -0
  99. package/corpus/templates/analytics/app/pages/monitoring/errors/utils.ts +132 -0
  100. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorDetail.tsx +535 -0
  101. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +1026 -0
  102. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorList.tsx +311 -0
  103. package/corpus/templates/analytics/app/pages/monitoring/uptime/i18n.ts +235 -0
  104. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPageEditor.tsx +661 -0
  105. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPagesView.tsx +355 -0
  106. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/i18n.ts +106 -0
  107. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/slug.ts +24 -0
  108. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/types.ts +20 -0
  109. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-summary.ts +87 -0
  110. package/corpus/templates/analytics/app/pages/monitoring/uptime/types.ts +161 -0
  111. package/corpus/templates/analytics/app/pages/monitoring/uptime/utils.ts +210 -0
  112. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +76 -1
  113. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +74 -9
  114. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +197 -20
  115. package/corpus/templates/analytics/app/root.tsx +33 -1
  116. package/corpus/templates/analytics/app/routes/monitoring._index.tsx +10 -0
  117. package/corpus/templates/analytics/app/routes/status.$slug.tsx +118 -0
  118. package/corpus/templates/analytics/changelog/2026-07-08-add-uptime-monitors-that-ping-your-urls-and-alert-you-when-t.md +6 -0
  119. package/corpus/templates/analytics/changelog/2026-07-08-analytics-chats-keep-large-data-dictionaries-compact-so-prov.md +6 -0
  120. package/corpus/templates/analytics/changelog/2026-07-08-create-public-status-pages-that-share-the-live-health-of-cho.md +6 -0
  121. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-extension-panels-use-clearer-open-copy.md +6 -0
  122. package/corpus/templates/analytics/changelog/2026-07-08-error-capture.md +6 -0
  123. package/corpus/templates/analytics/changelog/2026-07-08-fixed-single-panel-dashboard-drags-so-they-no-longer-rewrite.md +6 -0
  124. package/corpus/templates/analytics/changelog/2026-07-08-jump-straight-from-an-error-in-a-session-recording-to-its-fu.md +6 -0
  125. package/corpus/templates/analytics/changelog/2026-07-08-monitor-detail-and-list-now-show-colorful-uptime-timelines-r.md +6 -0
  126. package/corpus/templates/analytics/changelog/2026-07-08-pinned-ask-chats-now-show-a-pin-icon-in-the-sidebar.md +6 -0
  127. package/corpus/templates/analytics/changelog/2026-07-08-publish-a-public-uptime-status-page-with-colorful-uptime-tim.md +6 -0
  128. package/corpus/templates/analytics/changelog/2026-07-08-sessions-now-hide-visitor-emails-in-demo-mode-and-show-clean.md +6 -0
  129. package/corpus/templates/analytics/changelog/2026-07-08-settings-are-cleaner-searchable-and-alerts-have-their-own-tab.md +5 -0
  130. package/corpus/templates/analytics/changelog/2026-07-08-sidebar-sections-stay-collapsed-until-opened.md +5 -0
  131. package/corpus/templates/analytics/changelog/2026-07-08-the-uptime-monitor-list-now-has-a-current-status-overview-wi.md +6 -0
  132. package/corpus/templates/analytics/docs/error-capture.md +172 -0
  133. package/corpus/templates/analytics/docs/uptime-monitoring.md +150 -0
  134. package/corpus/templates/analytics/server/db/schema-errors.ts +150 -0
  135. package/corpus/templates/analytics/server/db/schema-monitoring.ts +177 -0
  136. package/corpus/templates/analytics/server/db/schema.ts +6 -0
  137. package/corpus/templates/analytics/server/jobs/uptime-monitors.ts +123 -0
  138. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +41 -0
  139. package/corpus/templates/analytics/server/lib/data-dictionary-context.ts +55 -12
  140. package/corpus/templates/analytics/server/lib/error-capture.ts +1331 -0
  141. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +47 -1
  142. package/corpus/templates/analytics/server/lib/monitor-stats.ts +494 -0
  143. package/corpus/templates/analytics/server/lib/status-pages.ts +798 -0
  144. package/corpus/templates/analytics/server/lib/uptime-monitors.ts +1665 -0
  145. package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -37
  146. package/corpus/templates/analytics/server/plugins/auth.ts +11 -1
  147. package/corpus/templates/analytics/server/plugins/db.ts +408 -0
  148. package/corpus/templates/analytics/server/plugins/uptime-monitor-jobs.ts +63 -0
  149. package/corpus/templates/assets/app/routes/_index.tsx +1 -1
  150. package/corpus/templates/assets/app/routes/settings.tsx +22 -1
  151. package/corpus/templates/assets/changelog/2026-07-08-recent-drafts-keep-comfortable-side-padding.md +6 -0
  152. package/corpus/templates/assets/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  153. package/corpus/templates/brain/app/routes/settings.tsx +43 -5
  154. package/corpus/templates/brain/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  155. package/corpus/templates/calendar/app/pages/Settings.tsx +44 -6
  156. package/corpus/templates/calendar/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  157. package/corpus/templates/chat/app/routes/settings.tsx +16 -1
  158. package/corpus/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  159. package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +79 -37
  160. package/corpus/templates/clips/app/components/player/player-controls.tsx +35 -0
  161. package/corpus/templates/clips/app/components/player/video-player.tsx +162 -18
  162. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +63 -6
  163. package/corpus/templates/clips/app/routes/record.tsx +18 -1
  164. package/corpus/templates/clips/changelog/2026-07-07-shared-clips-start-playback-reliably-from-the-first-play-click.md +6 -0
  165. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-camera-and-microphone-menus-now-show-which-.md +6 -0
  166. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-copies-new-clip-links-after-saving.md +6 -0
  167. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-recordings-now-continue-after-granting-came.md +6 -0
  168. package/corpus/templates/clips/changelog/2026-07-08-mobile-shared-clips-now-have-loom-style-tap-and-skip-controls.md +6 -0
  169. package/corpus/templates/clips/changelog/2026-07-08-recordings-and-uploads-copy-links-after-saving.md +6 -0
  170. package/corpus/templates/clips/changelog/2026-07-08-settings-are-cleaner-searchable-and-collapse-s3-with-builder.md +5 -0
  171. package/corpus/templates/clips/changelog/2026-07-08-transcripts-are-more-reliable-for-longer-desktop-recordings-.md +6 -0
  172. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -0
  173. package/corpus/templates/clips/chrome-extension/src/background.ts +162 -13
  174. package/corpus/templates/clips/chrome-extension/src/content-script.ts +14 -0
  175. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +36 -0
  176. package/corpus/templates/clips/chrome-extension/src/overlay.ts +99 -25
  177. package/corpus/templates/clips/chrome-extension/src/permission.ts +63 -14
  178. package/corpus/templates/clips/chrome-extension/src/popup.ts +123 -23
  179. package/corpus/templates/content/actions/_builder-cms-read-client.ts +47 -0
  180. package/corpus/templates/content/actions/_database-source-utils.ts +33 -4
  181. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +214 -29
  182. package/corpus/templates/content/actions/attach-content-database-source.ts +3 -0
  183. package/corpus/templates/content/actions/change-content-database-source-role.ts +1 -0
  184. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +42 -32
  185. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +352 -81
  186. package/corpus/templates/content/app/components/editor/database/settings.tsx +49 -24
  187. package/corpus/templates/content/app/routes/_app.settings.tsx +19 -1
  188. package/corpus/templates/content/changelog/2026-07-07-builder-source-tag-fields-now-import-as-multi-select.md +6 -0
  189. package/corpus/templates/content/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  190. package/corpus/templates/content/shared/api.ts +3 -0
  191. package/corpus/templates/content/shared/properties.ts +42 -0
  192. package/corpus/templates/design/actions/generate-design.ts +3 -0
  193. package/corpus/templates/design/actions/get-design-system.ts +147 -1
  194. package/corpus/templates/design/app/routes/settings.tsx +16 -1
  195. package/corpus/templates/design/changelog/2026-07-08-design-generation-now-follows-hydrated-builder-design-system.md +6 -0
  196. package/corpus/templates/design/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  197. package/corpus/templates/dispatch/app/routes/settings.tsx +23 -2
  198. package/corpus/templates/dispatch/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  199. package/corpus/templates/forms/app/routes/_app.settings.tsx +16 -1
  200. package/corpus/templates/forms/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  201. package/corpus/templates/macros/app/routes/settings.tsx +16 -1
  202. package/corpus/templates/macros/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  203. package/corpus/templates/mail/app/components/settings/GmailFiltersSection.tsx +1 -1
  204. package/corpus/templates/mail/app/components/settings/SnippetsSection.tsx +1 -1
  205. package/corpus/templates/mail/app/pages/SettingsPage.tsx +123 -105
  206. package/corpus/templates/mail/changelog/2026-07-08-settings-redesigned-with-a-consistent-searchable-layout.md +5 -0
  207. package/corpus/templates/plan/app/routes/settings.tsx +23 -2
  208. package/corpus/templates/plan/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  209. package/corpus/templates/slides/actions/add-slide.ts +1 -0
  210. package/corpus/templates/slides/actions/get-design-system.ts +147 -1
  211. package/corpus/templates/slides/app/pages/Index.tsx +46 -1
  212. package/corpus/templates/slides/app/routes/settings.tsx +16 -1
  213. package/corpus/templates/slides/changelog/2026-07-08-deck-generation-now-follows-hydrated-builder-design-system-g.md +6 -0
  214. package/corpus/templates/slides/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  215. package/dist/agent/run-ownership.d.ts +6 -0
  216. package/dist/agent/run-ownership.d.ts.map +1 -1
  217. package/dist/agent/run-ownership.js +11 -1
  218. package/dist/agent/run-ownership.js.map +1 -1
  219. package/dist/changelog/parse.d.ts +7 -0
  220. package/dist/changelog/parse.d.ts.map +1 -1
  221. package/dist/changelog/parse.js +64 -0
  222. package/dist/changelog/parse.js.map +1 -1
  223. package/dist/chat-threads/schema.d.ts +445 -0
  224. package/dist/chat-threads/schema.d.ts.map +1 -0
  225. package/dist/chat-threads/schema.js +39 -0
  226. package/dist/chat-threads/schema.js.map +1 -0
  227. package/dist/chat-threads/store.d.ts +12 -0
  228. package/dist/chat-threads/store.d.ts.map +1 -1
  229. package/dist/chat-threads/store.js +99 -10
  230. package/dist/chat-threads/store.js.map +1 -1
  231. package/dist/cli/workspace-dev.d.ts.map +1 -1
  232. package/dist/cli/workspace-dev.js +20 -5
  233. package/dist/cli/workspace-dev.js.map +1 -1
  234. package/dist/client/AgentPanel.d.ts.map +1 -1
  235. package/dist/client/AgentPanel.js +35 -7
  236. package/dist/client/AgentPanel.js.map +1 -1
  237. package/dist/client/AssistantChat.d.ts.map +1 -1
  238. package/dist/client/AssistantChat.js +105 -183
  239. package/dist/client/AssistantChat.js.map +1 -1
  240. package/dist/client/analytics-session.d.ts +3 -0
  241. package/dist/client/analytics-session.d.ts.map +1 -0
  242. package/dist/client/analytics-session.js +66 -0
  243. package/dist/client/analytics-session.js.map +1 -0
  244. package/dist/client/analytics.d.ts +32 -0
  245. package/dist/client/analytics.d.ts.map +1 -1
  246. package/dist/client/analytics.js +116 -46
  247. package/dist/client/analytics.js.map +1 -1
  248. package/dist/client/chat/message-components.d.ts +2 -1
  249. package/dist/client/chat/message-components.d.ts.map +1 -1
  250. package/dist/client/chat/message-components.js +16 -6
  251. package/dist/client/chat/message-components.js.map +1 -1
  252. package/dist/client/components/ui/message-scroller.d.ts +16 -0
  253. package/dist/client/components/ui/message-scroller.d.ts.map +1 -0
  254. package/dist/client/components/ui/message-scroller.js +25 -0
  255. package/dist/client/components/ui/message-scroller.js.map +1 -0
  256. package/dist/client/conversation/AgentConversation.d.ts +1 -1
  257. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  258. package/dist/client/conversation/AgentConversation.js +3 -8
  259. package/dist/client/conversation/AgentConversation.js.map +1 -1
  260. package/dist/client/error-capture.d.ts +99 -0
  261. package/dist/client/error-capture.d.ts.map +1 -0
  262. package/dist/client/error-capture.js +437 -0
  263. package/dist/client/error-capture.js.map +1 -0
  264. package/dist/client/index.d.ts +2 -2
  265. package/dist/client/index.d.ts.map +1 -1
  266. package/dist/client/index.js +3 -1
  267. package/dist/client/index.js.map +1 -1
  268. package/dist/client/session-replay.d.ts +22 -0
  269. package/dist/client/session-replay.d.ts.map +1 -1
  270. package/dist/client/session-replay.js +45 -4
  271. package/dist/client/session-replay.js.map +1 -1
  272. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  273. package/dist/client/settings/SettingsPanel.js +100 -5
  274. package/dist/client/settings/SettingsPanel.js.map +1 -1
  275. package/dist/client/settings/SettingsTabsPage.d.ts +49 -1
  276. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  277. package/dist/client/settings/SettingsTabsPage.js +131 -19
  278. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  279. package/dist/client/settings/index.d.ts +1 -1
  280. package/dist/client/settings/index.d.ts.map +1 -1
  281. package/dist/client/settings/index.js.map +1 -1
  282. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  283. package/dist/client/sharing/ShareButton.js +13 -8
  284. package/dist/client/sharing/ShareButton.js.map +1 -1
  285. package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
  286. package/dist/client/sharing/ShareDialog.js +12 -7
  287. package/dist/client/sharing/ShareDialog.js.map +1 -1
  288. package/dist/collab/struct-routes.d.ts +1 -1
  289. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  290. package/dist/mcp/builtin-tools.js +21 -2
  291. package/dist/mcp/builtin-tools.js.map +1 -1
  292. package/dist/notifications/routes.d.ts +1 -1
  293. package/dist/org/schema.d.ts +15 -15
  294. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  295. package/dist/resources/handlers.d.ts +3 -3
  296. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  297. package/dist/server/agent-chat-plugin.js +109 -73
  298. package/dist/server/agent-chat-plugin.js.map +1 -1
  299. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  300. package/dist/server/onboarding-html.d.ts.map +1 -1
  301. package/dist/server/onboarding-html.js +28 -16
  302. package/dist/server/onboarding-html.js.map +1 -1
  303. package/dist/sharing/actions/list-resource-shares.js +30 -1
  304. package/dist/sharing/actions/list-resource-shares.js.map +1 -1
  305. package/dist/sharing/actions/share-resource.js +6 -0
  306. package/dist/sharing/actions/share-resource.js.map +1 -1
  307. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  308. package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
  309. package/dist/vite/client.d.ts.map +1 -1
  310. package/dist/vite/client.js +192 -30
  311. package/dist/vite/client.js.map +1 -1
  312. package/docs/content/toolkit-settings.mdx +56 -3
  313. package/package.json +2 -1
  314. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  315. package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
@@ -6,6 +6,7 @@ import {
6
6
  useAui,
7
7
  useComposer,
8
8
  useComposerRuntime,
9
+ useMessageRuntime,
9
10
  ThreadPrimitive,
10
11
  } from "@assistant-ui/react";
11
12
  import type {
@@ -18,7 +19,6 @@ import {
18
19
  IconMessage,
19
20
  IconX,
20
21
  IconPlayerStop,
21
- IconChevronDown,
22
22
  IconTerminal,
23
23
  IconAlertTriangle,
24
24
  IconRefresh,
@@ -90,6 +90,7 @@ import {
90
90
  SelectionAttachedPill,
91
91
  RunningActivityStatus,
92
92
  displayableUserMessageText,
93
+ isHiddenUserMessage,
93
94
  } from "./chat/message-components.js";
94
95
  import {
95
96
  repoHasAssistantMessage,
@@ -121,6 +122,14 @@ import {
121
122
  type ApprovalContextValue,
122
123
  ReconnectStreamMessage,
123
124
  } from "./chat/tool-call-display.js";
125
+ import {
126
+ MessageScroller,
127
+ MessageScrollerButton,
128
+ MessageScrollerContent,
129
+ MessageScrollerItem,
130
+ MessageScrollerProvider,
131
+ MessageScrollerViewport,
132
+ } from "./components/ui/message-scroller.js";
124
133
  import {
125
134
  Tooltip,
126
135
  TooltipContent,
@@ -142,7 +151,6 @@ import type {
142
151
  Reference,
143
152
  } from "./composer/types.js";
144
153
  import { ContextMeter } from "./context-xray/ContextMeter.js";
145
- import { useNearBottomAutoscroll } from "./conversation/index.js";
146
154
  import {
147
155
  useAgentDynamicSuggestionsResult,
148
156
  type AgentDynamicSuggestionsOption,
@@ -198,6 +206,7 @@ function createUserMessageRunConfig(
198
206
  trackInRunsTray?: boolean,
199
207
  approvedToolCalls?: string[],
200
208
  queuedMessageId?: string,
209
+ hideUserMessage?: boolean,
201
210
  ) {
202
211
  const custom: {
203
212
  references?: Reference[];
@@ -223,14 +232,24 @@ function createUserMessageRunConfig(
223
232
  }
224
233
  const options: {
225
234
  runConfig?: { custom: typeof custom };
226
- metadata?: { custom: { agentNativeRecoveryAction: AgentRecoveryAction } };
235
+ metadata?: {
236
+ custom: {
237
+ agentNativeRecoveryAction?: AgentRecoveryAction;
238
+ agentNativeHiddenUserMessage?: boolean;
239
+ };
240
+ };
227
241
  } = {};
228
242
  if (Object.keys(custom).length > 0) {
229
243
  options.runConfig = { custom };
230
244
  }
231
- if (recoveryAction) {
245
+ if (recoveryAction || hideUserMessage) {
232
246
  options.metadata = {
233
- custom: { agentNativeRecoveryAction: recoveryAction },
247
+ custom: {
248
+ ...(recoveryAction
249
+ ? { agentNativeRecoveryAction: recoveryAction }
250
+ : {}),
251
+ ...(hideUserMessage ? { agentNativeHiddenUserMessage: true } : {}),
252
+ },
234
253
  };
235
254
  }
236
255
  return options;
@@ -535,72 +554,6 @@ function getMessageText(message: unknown): string {
535
554
  return typeof content === "string" ? displayableUserMessageText(content) : "";
536
555
  }
537
556
 
538
- function contentPartFollowKey(part: any): string {
539
- const type = typeof part?.type === "string" ? part.type : "unknown";
540
- if (type === "text") return `t:${String(part.text ?? "").length}`;
541
- if (type === "tool-call") {
542
- return [
543
- "tool",
544
- part.toolCallId ?? "",
545
- part.toolName ?? "",
546
- part.status?.type ?? "",
547
- String(part.argsText ?? "").length,
548
- String(part.result ?? "").length,
549
- part.mcpApp ? 1 : 0,
550
- part.chatUI?.renderer ?? "",
551
- ].join(":");
552
- }
553
- if (type === "image") return `image:${String(part.image ?? "").length}`;
554
- return `${type}:${String(part.text ?? part.result ?? "").length}`;
555
- }
556
-
557
- function contentFollowKey(content: unknown): string {
558
- if (typeof content === "string") return `t:${content.length}`;
559
- if (Array.isArray(content))
560
- return content.map(contentPartFollowKey).join("|");
561
- return "";
562
- }
563
-
564
- function messageFollowKey(message: unknown): string {
565
- const msg = ((message as { message?: unknown })?.message ?? message) as {
566
- id?: unknown;
567
- role?: unknown;
568
- status?: { type?: unknown; reason?: unknown };
569
- content?: unknown;
570
- };
571
- return [
572
- String(msg?.id ?? ""),
573
- String(msg?.role ?? ""),
574
- String(msg?.status?.type ?? ""),
575
- String(msg?.status?.reason ?? ""),
576
- contentFollowKey(msg?.content),
577
- ].join(",");
578
- }
579
-
580
- function queuedMessageFollowKey(message: {
581
- id: string;
582
- text: string;
583
- images?: string[];
584
- attachments?: QueuedAttachment[];
585
- references?: Reference[];
586
- requestMode?: AgentRequestMode;
587
- recoveryAction?: AgentRecoveryAction;
588
- }): string {
589
- return [
590
- message.id,
591
- message.text.length,
592
- message.images?.length ?? 0,
593
- message.attachments?.length ?? 0,
594
- message.references?.length ?? 0,
595
- message.requestMode ?? "",
596
- message.recoveryAction ?? "",
597
- ].join(":");
598
- }
599
-
600
- function reconnectContentFollowKey(content: ContentPart[]): string {
601
- return content.map(contentPartFollowKey).join("|");
602
- }
603
-
604
557
  export function reconnectActivityFallbackContent(
605
558
  toolName: string | null | undefined,
606
559
  ): ContentPart[] {
@@ -946,8 +899,30 @@ type QueuedMessage = {
946
899
  requestMode?: AgentRequestMode;
947
900
  recoveryAction?: AgentRecoveryAction;
948
901
  trackInRunsTray?: boolean;
902
+ hideUserMessage?: boolean;
949
903
  };
950
904
 
905
+ function AssistantChatUserMessageItem() {
906
+ const messageRuntime = useMessageRuntime();
907
+ const message = messageRuntime.getState();
908
+ if (isHiddenUserMessage(message)) return null;
909
+ return (
910
+ <MessageScrollerItem messageId={message.id} scrollAnchor>
911
+ <UserMessage />
912
+ </MessageScrollerItem>
913
+ );
914
+ }
915
+
916
+ function AssistantChatAssistantMessageItem() {
917
+ const messageRuntime = useMessageRuntime();
918
+ const message = messageRuntime.getState();
919
+ return (
920
+ <MessageScrollerItem messageId={message.id}>
921
+ <AssistantMessage />
922
+ </MessageScrollerItem>
923
+ );
924
+ }
925
+
951
926
  // ─── Main Component ─────────────────────────────────────────────────────────
952
927
 
953
928
  export interface AssistantChatHandle {
@@ -2347,9 +2322,8 @@ const AssistantChatInner = forwardRef<
2347
2322
  reconnectCanMaterializeRef.current = latestContent.length > 0;
2348
2323
  }
2349
2324
  const canAutoRecoverReconnect =
2350
- reconnectTerminalReason !== "run_timeout" &&
2351
2325
  reconnectAutoRecoveryCountRef.current <
2352
- MAX_RECONNECT_AUTO_RECOVERIES;
2326
+ MAX_RECONNECT_AUTO_RECOVERIES;
2353
2327
  if (canAutoRecoverReconnect) {
2354
2328
  reconnectAutoRecoveryCountRef.current += 1;
2355
2329
  setRunErrorInfo(null);
@@ -3106,6 +3080,7 @@ const AssistantChatInner = forwardRef<
3106
3080
  next.trackInRunsTray,
3107
3081
  undefined,
3108
3082
  next.id,
3083
+ next.hideUserMessage,
3109
3084
  ),
3110
3085
  } as Parameters<typeof threadRuntime.append>[0]);
3111
3086
  appended = true;
@@ -3341,6 +3316,7 @@ const AssistantChatInner = forwardRef<
3341
3316
  includeComposerContext = false,
3342
3317
  trackInRunsTray = false,
3343
3318
  preserveReconnectAutoRecoveryBudget = false,
3319
+ hideUserMessage = false,
3344
3320
  ) => {
3345
3321
  if (!(await ensureAgentEngineReadyForSubmit())) {
3346
3322
  return;
@@ -3358,12 +3334,9 @@ const AssistantChatInner = forwardRef<
3358
3334
  // Selection context attached via Cmd+I is one-shot — clear it as soon
3359
3335
  // as the user actually sends a message so it can't be re-used.
3360
3336
  clearPendingSelection();
3361
- // Sending a message is an explicit user action always anchor to the
3362
- // bottom so the new message and any reply land in view, even if the
3363
- // user had scrolled up to read history. The sticky-bottom override
3364
- // exists to stop streaming from yanking the viewport, not to swallow
3365
- // direct sends.
3366
- markNearBottom();
3337
+ // Sending a message is an explicit user action. The scroller anchors the
3338
+ // appended user turn so the new message and reply land in view without
3339
+ // re-pinning the viewport during ordinary streaming.
3367
3340
  const submitted = includeComposerContext
3368
3341
  ? buildComposerContextSubmission(text)
3369
3342
  : { text, includesContext: false };
@@ -3511,6 +3484,7 @@ const AssistantChatInner = forwardRef<
3511
3484
  requestMode: effectiveRequestMode,
3512
3485
  recoveryAction,
3513
3486
  trackInRunsTray,
3487
+ hideUserMessage,
3514
3488
  },
3515
3489
  ]);
3516
3490
  stopActiveRunRef.current();
@@ -3530,6 +3504,7 @@ const AssistantChatInner = forwardRef<
3530
3504
  requestMode: effectiveRequestMode,
3531
3505
  recoveryAction,
3532
3506
  trackInRunsTray,
3507
+ hideUserMessage,
3533
3508
  },
3534
3509
  ]);
3535
3510
  } else {
@@ -3546,6 +3521,9 @@ const AssistantChatInner = forwardRef<
3546
3521
  effectiveRequestMode,
3547
3522
  recoveryAction,
3548
3523
  trackInRunsTray,
3524
+ undefined,
3525
+ undefined,
3526
+ hideUserMessage,
3549
3527
  ),
3550
3528
  } as Parameters<typeof threadRuntime.append>[0]);
3551
3529
  } catch (error) {
@@ -3588,6 +3566,7 @@ const AssistantChatInner = forwardRef<
3588
3566
  false,
3589
3567
  false,
3590
3568
  true,
3569
+ true,
3591
3570
  );
3592
3571
  }, 0);
3593
3572
  return () => window.clearTimeout(timer);
@@ -3685,67 +3664,7 @@ const AssistantChatInner = forwardRef<
3685
3664
  () => dedupeReconnectContentAgainstMessages(reconnectContent, messages),
3686
3665
  [messages, reconnectContent],
3687
3666
  );
3688
-
3689
- const autoscrollFollowKey = useMemo(
3690
- () =>
3691
- [
3692
- messages.map(messageFollowKey).join(";"),
3693
- `q:${queuedMessages.map(queuedMessageFollowKey).join("|")}`,
3694
- `r:${reconnectContentFollowKey(visibleReconnectContent)}`,
3695
- ].join(";;"),
3696
- [messages, queuedMessages, visibleReconnectContent],
3697
- );
3698
-
3699
- const {
3700
- scrollRef,
3701
- isNearBottomRef,
3702
- showScrollToBottom,
3703
- markNearBottom,
3704
- scrollToBottom,
3705
- scrollToBottomAfterPaint,
3706
- } = useNearBottomAutoscroll<HTMLDivElement>({
3707
- followKey: autoscrollFollowKey,
3708
- streaming: textStreaming,
3709
- });
3710
-
3711
- const scrollToBottomWhileLayoutSettles = useCallback(() => {
3712
- scrollToBottomAfterPaint();
3713
- const el = scrollRef.current;
3714
- if (!el || typeof ResizeObserver === "undefined") return undefined;
3715
-
3716
- let stopped = false;
3717
- const observer = new ResizeObserver(() => {
3718
- if (!stopped && isNearBottomRef.current) scrollToBottom();
3719
- });
3720
- observer.observe(el);
3721
- const timeout = window.setTimeout(() => {
3722
- stopped = true;
3723
- observer.disconnect();
3724
- if (isNearBottomRef.current) scrollToBottom();
3725
- }, 1600);
3726
-
3727
- return () => {
3728
- stopped = true;
3729
- window.clearTimeout(timeout);
3730
- observer.disconnect();
3731
- };
3732
- }, [isNearBottomRef, scrollToBottom, scrollToBottomAfterPaint]);
3733
-
3734
- // Scroll to bottom when a restored thread finishes loading
3735
- const wasRestoringRef = useRef(isRestoring);
3736
- useEffect(() => {
3737
- const wasRestoring = wasRestoringRef.current;
3738
- wasRestoringRef.current = isRestoring;
3739
- if (wasRestoring && !isRestoring) {
3740
- return scrollToBottomWhileLayoutSettles();
3741
- }
3742
- }, [isRestoring, scrollToBottomWhileLayoutSettles]);
3743
-
3744
- useEffect(() => {
3745
- if (!textStreaming && isNearBottomRef.current) {
3746
- scrollToBottomAfterPaint();
3747
- }
3748
- }, [textStreaming, scrollToBottomAfterPaint]);
3667
+ const chatScrollResetKey = `${tabId ?? ""}:${threadId ?? ""}`;
3749
3668
 
3750
3669
  const { isDevMode: cpDevMode } = useDevMode(apiUrl);
3751
3670
  const checkpointCtx = useMemo(
@@ -3882,7 +3801,6 @@ const AssistantChatInner = forwardRef<
3882
3801
  showComposerSlot ||
3883
3802
  showCenteredEmptyThreadFooterSlot ||
3884
3803
  (guidedQuestions && guidedQuestions.length > 0) ||
3885
- showScrollToBottom ||
3886
3804
  composerContextItems.length > 0 ||
3887
3805
  showPlanModeCallout,
3888
3806
  );
@@ -3982,299 +3900,315 @@ const AssistantChatInner = forwardRef<
3982
3900
  )}
3983
3901
 
3984
3902
  {/* Messages area */}
3985
- <div
3986
- ref={scrollRef}
3987
- className="agent-chat-scroll flex-1 overflow-y-auto overflow-x-hidden min-h-0"
3988
- >
3989
- {authError ? (
3990
- <div className="flex flex-col items-center justify-center h-full px-4 gap-3">
3991
- <div className="flex h-10 w-10 items-center justify-center rounded-full bg-muted">
3992
- {authSessionAvailable ? (
3993
- <IconRefresh className="h-5 w-5 text-muted-foreground" />
3994
- ) : (
3995
- <IconMessage className="h-5 w-5 text-muted-foreground" />
3996
- )}
3997
- </div>
3998
- <div className="text-center max-w-[280px]">
3999
- <p className="text-sm font-medium text-foreground mb-1">
4000
- {authSessionAvailable
4001
- ? "Chat session needs refresh"
4002
- : authError.sessionExpired
4003
- ? "Session expired"
4004
- : "Authentication required"}
4005
- </p>
4006
- <p className="text-xs text-muted-foreground leading-relaxed">
4007
- {authSessionAvailable
4008
- ? "You're signed in, but this chat connection needs to reconnect."
4009
- : authError.sessionExpired
4010
- ? "Your session may have expired. Log out and log back in to reconnect."
4011
- : "You need to log in to use the agent."}
4012
- </p>
4013
- </div>
4014
- <div className="flex gap-2">
4015
- {!authError.sessionExpired && !authSessionAvailable && (
4016
- <button
4017
- onClick={() => {
4018
- const ret =
4019
- window.location.pathname +
4020
- window.location.search;
4021
- window.location.href =
4022
- agentNativePath("/_agent-native/sign-in") +
4023
- `?return=${encodeURIComponent(ret)}`;
4024
- }}
4025
- className="text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md"
4026
- >
4027
- Log in
4028
- </button>
4029
- )}
4030
- {authError.sessionExpired && !authSessionAvailable && (
4031
- <button
4032
- onClick={async () => {
4033
- try {
4034
- await fetch(
4035
- agentNativePath("/_agent-native/auth/logout"),
4036
- {
4037
- method: "POST",
4038
- },
4039
- );
4040
- } catch {}
4041
- window.location.reload();
4042
- }}
4043
- className="text-xs text-destructive hover:text-destructive/80 px-3 py-1.5 rounded-md border border-destructive/30 hover:bg-destructive/10"
4044
- >
4045
- Log out
4046
- </button>
4047
- )}
4048
- <button
4049
- onClick={() => {
4050
- setAuthError(null);
4051
- window.location.reload();
4052
- }}
4053
- className={
4054
- authSessionAvailable
4055
- ? "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md"
4056
- : "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent"
4057
- }
4058
- >
4059
- Refresh chat
4060
- </button>
4061
- </div>
4062
- </div>
4063
- ) : isRestoring && centeredRestoringState ? (
4064
- <div
4065
- className={cn(
4066
- "agent-empty-state",
4067
- emptyStateDisplay === "hidden"
4068
- ? "sr-only"
4069
- : "flex h-full flex-col items-center justify-center gap-4 px-4 py-16",
4070
- )}
4071
- aria-busy="true"
4072
- >
4073
- <div className="flex h-10 w-10 items-center justify-center rounded-full bg-muted">
4074
- <IconMessage className="h-5 w-5 text-muted-foreground" />
4075
- </div>
4076
- <p className="sr-only">
4077
- {emptyStateText ?? "Loading chat..."}
4078
- </p>
4079
- </div>
4080
- ) : isRestoring ? (
4081
- <div className="flex flex-col gap-3 p-4">
4082
- <div className="flex justify-end">
4083
- <div className="h-8 w-32 rounded-lg bg-muted animate-pulse" />
4084
- </div>
4085
- <div className="flex flex-col gap-1.5">
4086
- <div className="h-4 w-48 rounded bg-muted animate-pulse" />
4087
- <div className="h-4 w-64 rounded bg-muted animate-pulse" />
4088
- <div className="h-4 w-40 rounded bg-muted animate-pulse" />
4089
- </div>
4090
- </div>
4091
- ) : showEmptyState ? (
4092
- <div
4093
- className={cn(
4094
- "agent-empty-state",
4095
- emptyStateDisplay === "hidden"
4096
- ? "sr-only"
4097
- : "flex h-full flex-col items-center justify-center gap-4 px-4 py-16",
4098
- )}
4099
- >
4100
- <div className="flex h-10 w-10 items-center justify-center rounded-full bg-muted">
4101
- <IconMessage className="h-5 w-5 text-muted-foreground" />
4102
- </div>
4103
- <p className="sr-only">
4104
- {emptyStateText ?? "How can I help you?"}
4105
- </p>
4106
- {emptyStateAddon}
4107
- {resolvedSuggestions && resolvedSuggestions.length > 0 ? (
4108
- <div className="flex flex-col gap-1.5 w-full max-w-[280px]">
4109
- {resolvedSuggestions.map((suggestion) => (
3903
+ <MessageScrollerProvider key={chatScrollResetKey} autoScroll>
3904
+ <MessageScroller className="agent-chat-scroll">
3905
+ <MessageScrollerViewport>
3906
+ {authError ? (
3907
+ <div className="flex flex-col items-center justify-center h-full px-4 gap-3">
3908
+ <div className="flex h-10 w-10 items-center justify-center rounded-full bg-muted">
3909
+ {authSessionAvailable ? (
3910
+ <IconRefresh className="h-5 w-5 text-muted-foreground" />
3911
+ ) : (
3912
+ <IconMessage className="h-5 w-5 text-muted-foreground" />
3913
+ )}
3914
+ </div>
3915
+ <div className="text-center max-w-[280px]">
3916
+ <p className="text-sm font-medium text-foreground mb-1">
3917
+ {authSessionAvailable
3918
+ ? "Chat session needs refresh"
3919
+ : authError.sessionExpired
3920
+ ? "Session expired"
3921
+ : "Authentication required"}
3922
+ </p>
3923
+ <p className="text-xs text-muted-foreground leading-relaxed">
3924
+ {authSessionAvailable
3925
+ ? "You're signed in, but this chat connection needs to reconnect."
3926
+ : authError.sessionExpired
3927
+ ? "Your session may have expired. Log out and log back in to reconnect."
3928
+ : "You need to log in to use the agent."}
3929
+ </p>
3930
+ </div>
3931
+ <div className="flex gap-2">
3932
+ {!authError.sessionExpired &&
3933
+ !authSessionAvailable && (
3934
+ <button
3935
+ onClick={() => {
3936
+ const ret =
3937
+ window.location.pathname +
3938
+ window.location.search;
3939
+ window.location.href =
3940
+ agentNativePath(
3941
+ "/_agent-native/sign-in",
3942
+ ) + `?return=${encodeURIComponent(ret)}`;
3943
+ }}
3944
+ className="text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md"
3945
+ >
3946
+ Log in
3947
+ </button>
3948
+ )}
3949
+ {authError.sessionExpired &&
3950
+ !authSessionAvailable && (
3951
+ <button
3952
+ onClick={async () => {
3953
+ try {
3954
+ await fetch(
3955
+ agentNativePath(
3956
+ "/_agent-native/auth/logout",
3957
+ ),
3958
+ {
3959
+ method: "POST",
3960
+ },
3961
+ );
3962
+ } catch {}
3963
+ window.location.reload();
3964
+ }}
3965
+ className="text-xs text-destructive hover:text-destructive/80 px-3 py-1.5 rounded-md border border-destructive/30 hover:bg-destructive/10"
3966
+ >
3967
+ Log out
3968
+ </button>
3969
+ )}
4110
3970
  <button
4111
- key={suggestion}
4112
3971
  onClick={() => {
4113
- if (missingApiKey) {
4114
- setMissingKeyBouncePulse((p) => p + 1);
4115
- return;
4116
- }
4117
- void addToQueue(suggestion);
3972
+ setAuthError(null);
3973
+ window.location.reload();
4118
3974
  }}
4119
- className="w-full rounded-lg border border-border px-3 py-2 text-start text-[13px] text-muted-foreground hover:bg-accent hover:text-foreground"
3975
+ className={
3976
+ authSessionAvailable
3977
+ ? "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md"
3978
+ : "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent"
3979
+ }
4120
3980
  >
4121
- {suggestion}
3981
+ Refresh chat
4122
3982
  </button>
4123
- ))}
3983
+ </div>
4124
3984
  </div>
4125
- ) : null}
4126
- {showInlineEmptyThreadFooterSlot ? (
4127
- <div className="agent-thread-footer-slot agent-thread-footer-slot--empty">
4128
- {resolvedThreadFooterSlot}
3985
+ ) : isRestoring && centeredRestoringState ? (
3986
+ <div
3987
+ className={cn(
3988
+ "agent-empty-state",
3989
+ emptyStateDisplay === "hidden"
3990
+ ? "sr-only"
3991
+ : "flex h-full flex-col items-center justify-center gap-4 px-4 py-16",
3992
+ )}
3993
+ aria-busy="true"
3994
+ >
3995
+ <div className="flex h-10 w-10 items-center justify-center rounded-full bg-muted">
3996
+ <IconMessage className="h-5 w-5 text-muted-foreground" />
3997
+ </div>
3998
+ <p className="sr-only">
3999
+ {emptyStateText ?? "Loading chat..."}
4000
+ </p>
4129
4001
  </div>
4130
- ) : null}
4131
- </div>
4132
- ) : (
4133
- <div className="agent-thread-content flex flex-col gap-4 px-4 py-4">
4134
- <AssistantMessageListErrorBoundary
4135
- resetKey={messageListResetKey}
4136
- >
4137
- <ThreadPrimitive.Messages
4138
- components={{
4139
- UserMessage,
4140
- AssistantMessage,
4141
- }}
4142
- />
4143
- </AssistantMessageListErrorBoundary>
4144
- {visibleLoopLimit && !showRunningInUI && (
4145
- <LoopLimitContinueCard
4146
- info={visibleLoopLimit}
4147
- onContinue={() => {
4148
- setShowContinue(false);
4149
- setLoopLimitInfo(null);
4150
- addToQueue(
4151
- "Continue from where you left off.",
4152
- undefined,
4153
- undefined,
4154
- undefined,
4155
- undefined,
4156
- "queued",
4157
- "continue",
4158
- );
4159
- }}
4160
- />
4161
- )}
4162
- {shouldShowRunError && visibleRunError && (
4163
- <RunErrorRecoveryCard
4164
- info={visibleRunError}
4165
- onContinue={() => {
4166
- setRunErrorInfo(null);
4167
- addToQueue(
4168
- RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE,
4169
- undefined,
4170
- undefined,
4171
- undefined,
4172
- undefined,
4173
- "queued",
4174
- "continue",
4175
- );
4176
- }}
4177
- onRetry={() => {
4178
- setRunErrorInfo(null);
4179
- addToQueue(
4180
- lastUserText
4181
- ? `Retry the previous request from a clean approach. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. If a provider query failed because of schema, syntax, or type mismatch, diagnose the error and adjust the query first.\n\nOriginal request:\n\n${lastUserText}`
4182
- : "Retry the previous request from a clean approach. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. If a provider query failed because of schema, syntax, or type mismatch, diagnose the error and adjust the query first.",
4183
- undefined,
4184
- undefined,
4185
- undefined,
4186
- undefined,
4187
- "queued",
4188
- "retry",
4189
- );
4190
- }}
4191
- onFork={onForkChat}
4192
- onDismiss={() => {
4193
- if (visibleRunErrorKey) {
4194
- setDismissedRunErrorKey(visibleRunErrorKey);
4195
- }
4196
- setRunErrorInfo(null);
4197
- }}
4198
- />
4199
- )}
4200
- {(isReconnecting || reconnectFrozen) &&
4201
- visibleReconnectContent.length > 0 && (
4202
- <ReconnectStreamMessage
4203
- content={visibleReconnectContent}
4204
- />
4205
- )}
4206
- {(isReconnecting || reconnectFrozen) &&
4207
- visibleReconnectContent.length === 0 &&
4208
- reconnectContent.length === 0 &&
4209
- reconnectActivityContent.length > 0 && (
4210
- <ReconnectStreamMessage
4211
- content={reconnectActivityContent}
4212
- />
4213
- )}
4214
- {showRunningInUI && (
4215
- <RunningActivityStatus label={runningStatusLabel} />
4216
- )}
4217
- {queuedMessages.map((msg) => {
4218
- const displayText = displayableUserMessageText(
4219
- msg.text,
4220
- );
4221
- return (
4222
- <div
4223
- key={msg.id}
4224
- className="group flex items-start justify-end gap-1.5"
4225
- >
4226
- <button
4227
- type="button"
4228
- onClick={() =>
4229
- applyLocalQueuedMessages((prev) =>
4230
- prev.filter((m) => m.id !== msg.id),
4231
- )
4232
- }
4233
- aria-label="Remove from queue"
4234
- className="mt-1.5 flex h-5 w-5 items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 shadow-sm transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100"
4235
- >
4236
- <IconX className="h-3 w-3" />
4237
- </button>
4238
- <div className="max-w-[85%] rounded-lg bg-accent/50 px-3 py-2 text-sm leading-relaxed text-foreground/60 whitespace-pre-wrap break-words">
4239
- {displayText}
4240
- {msg.images && msg.images.length > 0 && (
4241
- <div className="flex flex-wrap gap-1.5 mt-1.5">
4242
- {msg.images.map((img, j) => (
4243
- <img
4244
- key={j}
4245
- src={img}
4246
- alt=""
4247
- className="h-12 w-12 rounded object-cover border border-border/50"
4248
- />
4249
- ))}
4250
- </div>
4251
- )}
4252
- </div>
4002
+ ) : isRestoring ? (
4003
+ <div className="flex flex-col gap-3 p-4">
4004
+ <div className="flex justify-end">
4005
+ <div className="h-8 w-32 rounded-lg bg-muted animate-pulse" />
4006
+ </div>
4007
+ <div className="flex flex-col gap-1.5">
4008
+ <div className="h-4 w-48 rounded bg-muted animate-pulse" />
4009
+ <div className="h-4 w-64 rounded bg-muted animate-pulse" />
4010
+ <div className="h-4 w-40 rounded bg-muted animate-pulse" />
4253
4011
  </div>
4254
- );
4255
- })}
4256
- {resolvedThreadFooterSlot ? (
4257
- <div className="agent-thread-footer-slot">
4258
- {resolvedThreadFooterSlot}
4259
4012
  </div>
4260
- ) : null}
4261
- </div>
4262
- )}
4263
- </div>
4264
-
4265
- {/* Scroll to bottom button */}
4266
- {showScrollToBottom && (
4267
- <div className="shrink-0 flex justify-center -mb-1">
4268
- <button
4269
- type="button"
4270
- onClick={scrollToBottom}
4271
- className="flex h-7 w-7 items-center justify-center rounded-full border border-border bg-background shadow-sm hover:bg-accent"
4272
- aria-label="Scroll to bottom"
4273
- >
4274
- <IconChevronDown className="h-3.5 w-3.5 text-muted-foreground" />
4275
- </button>
4276
- </div>
4277
- )}
4013
+ ) : showEmptyState ? (
4014
+ <div
4015
+ className={cn(
4016
+ "agent-empty-state",
4017
+ emptyStateDisplay === "hidden"
4018
+ ? "sr-only"
4019
+ : "flex h-full flex-col items-center justify-center gap-4 px-4 py-16",
4020
+ )}
4021
+ >
4022
+ <div className="flex h-10 w-10 items-center justify-center rounded-full bg-muted">
4023
+ <IconMessage className="h-5 w-5 text-muted-foreground" />
4024
+ </div>
4025
+ <p className="sr-only">
4026
+ {emptyStateText ?? "How can I help you?"}
4027
+ </p>
4028
+ {emptyStateAddon}
4029
+ {resolvedSuggestions &&
4030
+ resolvedSuggestions.length > 0 ? (
4031
+ <div className="flex flex-col gap-1.5 w-full max-w-[280px]">
4032
+ {resolvedSuggestions.map((suggestion) => (
4033
+ <button
4034
+ key={suggestion}
4035
+ onClick={() => {
4036
+ if (missingApiKey) {
4037
+ setMissingKeyBouncePulse((p) => p + 1);
4038
+ return;
4039
+ }
4040
+ void addToQueue(suggestion);
4041
+ }}
4042
+ className="w-full rounded-lg border border-border px-3 py-2 text-start text-[13px] text-muted-foreground hover:bg-accent hover:text-foreground"
4043
+ >
4044
+ {suggestion}
4045
+ </button>
4046
+ ))}
4047
+ </div>
4048
+ ) : null}
4049
+ {showInlineEmptyThreadFooterSlot ? (
4050
+ <div className="agent-thread-footer-slot agent-thread-footer-slot--empty">
4051
+ {resolvedThreadFooterSlot}
4052
+ </div>
4053
+ ) : null}
4054
+ </div>
4055
+ ) : (
4056
+ <MessageScrollerContent className="agent-thread-content gap-4 px-4 py-4">
4057
+ <AssistantMessageListErrorBoundary
4058
+ resetKey={messageListResetKey}
4059
+ >
4060
+ <ThreadPrimitive.Messages
4061
+ components={{
4062
+ UserMessage: AssistantChatUserMessageItem,
4063
+ AssistantMessage:
4064
+ AssistantChatAssistantMessageItem,
4065
+ }}
4066
+ />
4067
+ </AssistantMessageListErrorBoundary>
4068
+ {visibleLoopLimit && !showRunningInUI && (
4069
+ <MessageScrollerItem>
4070
+ <LoopLimitContinueCard
4071
+ info={visibleLoopLimit}
4072
+ onContinue={() => {
4073
+ setShowContinue(false);
4074
+ setLoopLimitInfo(null);
4075
+ addToQueue(
4076
+ "Continue from where you left off.",
4077
+ undefined,
4078
+ undefined,
4079
+ undefined,
4080
+ undefined,
4081
+ "queued",
4082
+ "continue",
4083
+ );
4084
+ }}
4085
+ />
4086
+ </MessageScrollerItem>
4087
+ )}
4088
+ {shouldShowRunError && visibleRunError && (
4089
+ <MessageScrollerItem>
4090
+ <RunErrorRecoveryCard
4091
+ info={visibleRunError}
4092
+ onContinue={() => {
4093
+ setRunErrorInfo(null);
4094
+ addToQueue(
4095
+ RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE,
4096
+ undefined,
4097
+ undefined,
4098
+ undefined,
4099
+ undefined,
4100
+ "queued",
4101
+ "continue",
4102
+ );
4103
+ }}
4104
+ onRetry={() => {
4105
+ setRunErrorInfo(null);
4106
+ addToQueue(
4107
+ lastUserText
4108
+ ? `Retry the previous request from a clean approach. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. If a provider query failed because of schema, syntax, or type mismatch, diagnose the error and adjust the query first.\n\nOriginal request:\n\n${lastUserText}`
4109
+ : "Retry the previous request from a clean approach. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. If a provider query failed because of schema, syntax, or type mismatch, diagnose the error and adjust the query first.",
4110
+ undefined,
4111
+ undefined,
4112
+ undefined,
4113
+ undefined,
4114
+ "queued",
4115
+ "retry",
4116
+ );
4117
+ }}
4118
+ onFork={onForkChat}
4119
+ onDismiss={() => {
4120
+ if (visibleRunErrorKey) {
4121
+ setDismissedRunErrorKey(visibleRunErrorKey);
4122
+ }
4123
+ setRunErrorInfo(null);
4124
+ }}
4125
+ />
4126
+ </MessageScrollerItem>
4127
+ )}
4128
+ {(isReconnecting || reconnectFrozen) &&
4129
+ visibleReconnectContent.length > 0 && (
4130
+ <MessageScrollerItem>
4131
+ <ReconnectStreamMessage
4132
+ content={visibleReconnectContent}
4133
+ />
4134
+ </MessageScrollerItem>
4135
+ )}
4136
+ {(isReconnecting || reconnectFrozen) &&
4137
+ visibleReconnectContent.length === 0 &&
4138
+ reconnectContent.length === 0 &&
4139
+ reconnectActivityContent.length > 0 && (
4140
+ <MessageScrollerItem>
4141
+ <ReconnectStreamMessage
4142
+ content={reconnectActivityContent}
4143
+ />
4144
+ </MessageScrollerItem>
4145
+ )}
4146
+ {showRunningInUI && (
4147
+ <MessageScrollerItem>
4148
+ <RunningActivityStatus
4149
+ label={runningStatusLabel}
4150
+ />
4151
+ </MessageScrollerItem>
4152
+ )}
4153
+ {queuedMessages
4154
+ .filter((msg) => !msg.hideUserMessage)
4155
+ .map((msg) => {
4156
+ const displayText = displayableUserMessageText(
4157
+ msg.text,
4158
+ );
4159
+ return (
4160
+ <MessageScrollerItem
4161
+ key={msg.id}
4162
+ messageId={msg.id}
4163
+ scrollAnchor
4164
+ >
4165
+ <div className="group flex items-start justify-end gap-1.5">
4166
+ <button
4167
+ type="button"
4168
+ onClick={() =>
4169
+ applyLocalQueuedMessages((prev) =>
4170
+ prev.filter((m) => m.id !== msg.id),
4171
+ )
4172
+ }
4173
+ aria-label="Remove from queue"
4174
+ className="mt-1.5 flex h-5 w-5 items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 shadow-sm transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100"
4175
+ >
4176
+ <IconX className="h-3 w-3" />
4177
+ </button>
4178
+ <div className="max-w-[85%] rounded-lg bg-accent/50 px-3 py-2 text-sm leading-relaxed text-foreground/60 whitespace-pre-wrap break-words">
4179
+ {displayText}
4180
+ {msg.images && msg.images.length > 0 && (
4181
+ <div className="flex flex-wrap gap-1.5 mt-1.5">
4182
+ {msg.images.map((img, j) => (
4183
+ <img
4184
+ key={j}
4185
+ src={img}
4186
+ alt=""
4187
+ className="h-12 w-12 rounded object-cover border border-border/50"
4188
+ />
4189
+ ))}
4190
+ </div>
4191
+ )}
4192
+ </div>
4193
+ </div>
4194
+ </MessageScrollerItem>
4195
+ );
4196
+ })}
4197
+ {resolvedThreadFooterSlot ? (
4198
+ <MessageScrollerItem>
4199
+ <div className="agent-thread-footer-slot">
4200
+ {resolvedThreadFooterSlot}
4201
+ </div>
4202
+ </MessageScrollerItem>
4203
+ ) : null}
4204
+ </MessageScrollerContent>
4205
+ )}
4206
+ </MessageScrollerViewport>
4207
+ {!authError && !isRestoring && !showEmptyState ? (
4208
+ <MessageScrollerButton />
4209
+ ) : null}
4210
+ </MessageScroller>
4211
+ </MessageScrollerProvider>
4278
4212
 
4279
4213
  {showComposerSlot ? composerSlot : null}
4280
4214
  {showCenteredEmptyThreadFooterSlot ? (