@agent-native/core 0.98.0 → 0.98.2

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 (345) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +32 -0
  3. package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +25 -1
  4. package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +1 -1
  5. package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +25 -1
  6. package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +1 -1
  7. package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +25 -1
  8. package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +1 -1
  9. package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +25 -1
  10. package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +1 -1
  11. package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +25 -1
  12. package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +1 -1
  13. package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +25 -1
  14. package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +1 -1
  15. package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +25 -1
  16. package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +1 -1
  17. package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +25 -1
  18. package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +1 -1
  19. package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +25 -1
  20. package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +1 -1
  21. package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +25 -1
  22. package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +1 -1
  23. package/corpus/core/docs/content/pr-visual-recap.mdx +50 -1
  24. package/corpus/core/docs/content/template-plan.mdx +1 -1
  25. package/corpus/core/package.json +2 -2
  26. package/corpus/core/src/action-change-marker.ts +8 -1
  27. package/corpus/core/src/changelog/parse.ts +8 -3
  28. package/corpus/core/src/cli/plan-local.ts +43 -11
  29. package/corpus/core/src/cli/pr-visual-recap-workflow.ts +2 -9
  30. package/corpus/core/src/cli/recap.ts +356 -4
  31. package/corpus/core/src/cli/skills-content/local-files.ts +17 -12
  32. package/corpus/core/src/client/AgentPanel.tsx +2 -3
  33. package/corpus/core/src/client/AssistantChat.tsx +83 -39
  34. package/corpus/core/src/client/analytics.ts +125 -14
  35. package/corpus/core/src/client/blocks/library/wireframe-kit.tsx +16 -2
  36. package/corpus/core/src/client/chat-model-groups.ts +28 -0
  37. package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +442 -85
  38. package/corpus/core/src/client/composer/TiptapComposer.tsx +46 -29
  39. package/corpus/core/src/client/composer/VoiceButton.tsx +2 -1
  40. package/corpus/core/src/client/composer/index.ts +5 -0
  41. package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +1206 -67
  42. package/corpus/core/src/client/index.ts +10 -0
  43. package/corpus/core/src/client/progress/RunsTray.tsx +13 -1
  44. package/corpus/core/src/client/session-replay.ts +10 -0
  45. package/corpus/core/src/client/settings/DemoModeSection.tsx +4 -28
  46. package/corpus/core/src/client/settings/SecretsSection.tsx +387 -266
  47. package/corpus/core/src/client/settings/SettingsPanel.tsx +117 -38
  48. package/corpus/core/src/client/url-scrub.ts +13 -0
  49. package/corpus/core/src/client/use-action.ts +12 -0
  50. package/corpus/core/src/client/use-agent-chat-home-handoff.ts +8 -1
  51. package/corpus/core/src/client/use-agent-engine-configured.ts +17 -3
  52. package/corpus/core/src/client/use-db-sync.ts +84 -34
  53. package/corpus/core/src/client/use-demo-mode-status.ts +44 -0
  54. package/corpus/core/src/client/use-pausing-interval.ts +14 -4
  55. package/corpus/core/src/integrations/scope-store.ts +1 -1
  56. package/corpus/core/src/integrations/usage-budget-store.ts +1 -1
  57. package/corpus/core/src/localization/default-messages.ts +44 -1
  58. package/corpus/core/src/mcp-client/workspace-servers.ts +4 -4
  59. package/corpus/core/src/secrets/crypto.ts +28 -8
  60. package/corpus/core/src/server/action-change.ts +5 -1
  61. package/corpus/core/src/server/action-routes.ts +8 -0
  62. package/corpus/core/src/server/poll.ts +1 -0
  63. package/corpus/core/src/server/realtime-voice.ts +299 -13
  64. package/corpus/core/src/styles/agent-native.css +2 -2
  65. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
  66. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
  67. package/corpus/core/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
  68. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
  69. package/corpus/core/src/vite/client.ts +9 -1
  70. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +2 -2
  71. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +10 -5
  72. package/corpus/templates/analytics/AGENTS.md +17 -13
  73. package/corpus/templates/analytics/actions/navigate.ts +59 -5
  74. package/corpus/templates/analytics/actions/view-screen.ts +3 -6
  75. package/corpus/templates/analytics/app/components/ProviderCorpusJobNotifier.tsx +20 -3
  76. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +20 -5
  77. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
  78. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -6
  79. package/corpus/templates/analytics/app/global.css +19 -20
  80. package/corpus/templates/analytics/app/lib/demo-chart-trend.ts +156 -0
  81. package/corpus/templates/analytics/app/lib/provider-corpus-job-sync.ts +26 -0
  82. package/corpus/templates/analytics/app/pages/Settings.tsx +35 -341
  83. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +38 -7
  84. package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +1 -1
  85. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +3 -0
  86. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +333 -272
  87. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +72 -17
  88. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +297 -108
  89. package/corpus/templates/analytics/app/root.tsx +28 -8
  90. package/corpus/templates/analytics/changelog/2026-06-24-first-party-signup-and-pageview-panels-now-honor-dashboard-filters.md +2 -1
  91. package/corpus/templates/analytics/changelog/2026-06-25-referrer-dashboard-panels-show-external-domains.md +2 -1
  92. package/corpus/templates/analytics/changelog/2026-07-06-mobile-chat-header-is-more-compact-and-the-menu-button-opens-navigation.md +1 -0
  93. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +1 -0
  94. package/corpus/templates/analytics/changelog/2026-07-08-settings-are-cleaner-searchable-and-alerts-have-their-own-tab.md +1 -0
  95. package/corpus/templates/analytics/changelog/2026-07-08-sidebar-sections-stay-collapsed-until-opened.md +1 -0
  96. package/corpus/templates/analytics/changelog/2026-07-11-analytics-no-longer-repeatedly-restarts-background-requests-.md +6 -0
  97. package/corpus/templates/analytics/changelog/2026-07-11-analytics-only-asks-for-replay-storage-when-you-enable-sessi.md +6 -0
  98. package/corpus/templates/analytics/changelog/2026-07-11-charts-now-show-their-loading-skeleton-while-refreshing.md +6 -0
  99. package/corpus/templates/analytics/changelog/2026-07-11-realtime-voice-now-shows-a-clear-connection-indicator-comple.md +6 -0
  100. package/corpus/templates/analytics/changelog/2026-07-11-replay-event-counts-stay-hidden-until-recordings-finish-load.md +6 -0
  101. package/corpus/templates/analytics/changelog/2026-07-11-replay-storage-key-mismatches-show-actionable-setup-guidance.md +6 -0
  102. package/corpus/templates/analytics/changelog/2026-07-11-replay-timelines-group-continuous-scrolling-and-dev-tools-co.md +6 -0
  103. package/corpus/templates/analytics/changelog/2026-07-11-session-filters-now-stay-compact-in-a-settings-menu-at-mediu.md +6 -0
  104. package/corpus/templates/analytics/changelog/2026-07-11-session-replay-console-errors-now-link-to-matching-issues-or.md +6 -0
  105. package/corpus/templates/analytics/changelog/2026-07-11-session-replays-load-large-recordings-faster-and-surface-fai.md +6 -0
  106. package/corpus/templates/analytics/changelog/2026-07-11-session-replays-preserve-recorded-styles-and-viewport-layout.md +6 -0
  107. package/corpus/templates/analytics/changelog/2026-07-11-session-replays-stay-centered-instead-of-clipping-wide-recor.md +6 -0
  108. package/corpus/templates/analytics/changelog/2026-07-12-daily-dashboard-emails-reliably-include-the-complete-dashboa.md +6 -0
  109. package/corpus/templates/analytics/changelog/2026-07-12-demo-mode-charts-trend-upward.md +6 -0
  110. package/corpus/templates/analytics/package.json +1 -1
  111. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +1 -303
  112. package/corpus/templates/analytics/server/handlers/session-replay.ts +57 -0
  113. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +2 -0
  114. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +1 -1
  115. package/corpus/templates/analytics/server/lib/dashboard-report.ts +17 -33
  116. package/corpus/templates/analytics/server/lib/demo-dashboards.ts +16 -3
  117. package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +12 -0
  118. package/corpus/templates/analytics/server/lib/session-replay.ts +208 -2
  119. package/corpus/templates/analytics/server/plugins/onboarding.ts +7 -79
  120. package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/chunks.get.ts +1 -0
  121. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +2 -2
  122. package/corpus/templates/assets/app/global.css +4 -4
  123. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +0 -1
  124. package/corpus/templates/assets/app/routes/library.tsx +0 -1
  125. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +2 -2
  126. package/corpus/templates/brain/app/global.css +5 -5
  127. package/corpus/templates/brain/app/root.tsx +0 -3
  128. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +2 -2
  129. package/corpus/templates/calendar/app/root.tsx +1 -0
  130. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +2 -2
  131. package/corpus/templates/clips/app/components/player/video-player.tsx +5 -1
  132. package/corpus/templates/clips/app/hooks/use-auto-title.ts +74 -8
  133. package/corpus/templates/clips/app/hooks/use-library.ts +12 -25
  134. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +20 -22
  135. package/corpus/templates/clips/changelog/2026-07-11-clips-no-longer-stay-stuck-on-preparing-clip-when-they-are-r.md +6 -0
  136. package/corpus/templates/clips/changelog/2026-07-11-generated-titles-no-longer-cause-continuous-background-refreshes.md +6 -0
  137. package/corpus/templates/clips/changelog/2026-07-11-s3-storage-setup-stays-collapsed-until-you-choose-it-as-the-.md +6 -0
  138. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +2 -2
  139. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +2 -2
  140. package/corpus/templates/content/app/hooks/use-comments.ts +0 -1
  141. package/corpus/templates/content/changelog/2026-07-11-comments-now-update-from-live-collaboration-events-without-c.md +6 -0
  142. package/corpus/templates/content/changelog/2026-07-12-the-left-sidebar-stays-fixed-horizontally-while-scrolling-on.md +6 -0
  143. package/corpus/templates/design/app/components/layout/Header.tsx +1 -1
  144. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +2 -2
  145. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +1 -2
  146. package/corpus/templates/macros/app/root.tsx +0 -3
  147. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +2 -2
  148. package/corpus/templates/mail/app/hooks/use-compose-state.ts +1 -0
  149. package/corpus/templates/mail/app/root.tsx +1 -12
  150. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +2 -2
  151. package/corpus/templates/plan/.agents/skills/visual-plan/references/local-files.md +17 -12
  152. package/corpus/templates/plan/.agents/skills/visual-recap/references/local-files.md +17 -12
  153. package/corpus/templates/plan/actions/validate-local-plan-source.ts +4 -4
  154. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +2 -1
  155. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +5 -2
  156. package/corpus/templates/plan/app/hooks/use-plans.ts +6 -13
  157. package/corpus/templates/plan/app/lib/plan-local-bridge.ts +41 -0
  158. package/corpus/templates/plan/app/lib/plan-tracking.ts +3 -0
  159. package/corpus/templates/plan/app/pages/PlansPage.tsx +14 -36
  160. package/corpus/templates/plan/app/root.tsx +13 -3
  161. package/corpus/templates/plan/changelog/2026-07-11-plan-refreshes-only-when-content-changes.md +6 -0
  162. package/corpus/templates/plan/changelog/2026-07-12-local-plan-source-now-stays-on-device.md +6 -0
  163. package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +4 -1
  164. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +1 -1
  165. package/corpus/templates/slides/app/components/layout/Header.tsx +1 -1
  166. package/corpus/templates/slides/app/context/DeckContext.tsx +1 -0
  167. package/corpus/templates/slides/app/hooks/use-slide-comments.ts +7 -31
  168. package/corpus/templates/slides/changelog/2026-07-11-comments-now-update-from-live-collaboration-events-without-c.md +6 -0
  169. package/dist/action-change-marker.d.ts +1 -0
  170. package/dist/action-change-marker.d.ts.map +1 -1
  171. package/dist/action-change-marker.js +7 -1
  172. package/dist/action-change-marker.js.map +1 -1
  173. package/dist/changelog/parse.d.ts +4 -2
  174. package/dist/changelog/parse.d.ts.map +1 -1
  175. package/dist/changelog/parse.js +5 -3
  176. package/dist/changelog/parse.js.map +1 -1
  177. package/dist/cli/plan-local.d.ts +6 -6
  178. package/dist/cli/plan-local.d.ts.map +1 -1
  179. package/dist/cli/plan-local.js +36 -7
  180. package/dist/cli/plan-local.js.map +1 -1
  181. package/dist/cli/pr-visual-recap-workflow.d.ts +2 -8
  182. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  183. package/dist/cli/pr-visual-recap-workflow.js +2 -8
  184. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  185. package/dist/cli/recap.d.ts +22 -1
  186. package/dist/cli/recap.d.ts.map +1 -1
  187. package/dist/cli/recap.js +286 -2
  188. package/dist/cli/recap.js.map +1 -1
  189. package/dist/cli/skills-content/local-files.d.ts +1 -1
  190. package/dist/cli/skills-content/local-files.d.ts.map +1 -1
  191. package/dist/cli/skills-content/local-files.js +17 -12
  192. package/dist/cli/skills-content/local-files.js.map +1 -1
  193. package/dist/client/AgentPanel.d.ts.map +1 -1
  194. package/dist/client/AgentPanel.js +2 -3
  195. package/dist/client/AgentPanel.js.map +1 -1
  196. package/dist/client/AssistantChat.d.ts +7 -0
  197. package/dist/client/AssistantChat.d.ts.map +1 -1
  198. package/dist/client/AssistantChat.js +62 -40
  199. package/dist/client/AssistantChat.js.map +1 -1
  200. package/dist/client/analytics.d.ts +8 -0
  201. package/dist/client/analytics.d.ts.map +1 -1
  202. package/dist/client/analytics.js +103 -13
  203. package/dist/client/analytics.js.map +1 -1
  204. package/dist/client/blocks/library/wireframe-kit.d.ts +2 -0
  205. package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
  206. package/dist/client/blocks/library/wireframe-kit.js +9 -2
  207. package/dist/client/blocks/library/wireframe-kit.js.map +1 -1
  208. package/dist/client/chat-model-groups.d.ts.map +1 -1
  209. package/dist/client/chat-model-groups.js +24 -0
  210. package/dist/client/chat-model-groups.js.map +1 -1
  211. package/dist/client/composer/RealtimeVoiceMode.d.ts +40 -4
  212. package/dist/client/composer/RealtimeVoiceMode.d.ts.map +1 -1
  213. package/dist/client/composer/RealtimeVoiceMode.js +172 -42
  214. package/dist/client/composer/RealtimeVoiceMode.js.map +1 -1
  215. package/dist/client/composer/TiptapComposer.d.ts +4 -0
  216. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  217. package/dist/client/composer/TiptapComposer.js +47 -29
  218. package/dist/client/composer/TiptapComposer.js.map +1 -1
  219. package/dist/client/composer/VoiceButton.d.ts.map +1 -1
  220. package/dist/client/composer/VoiceButton.js +2 -2
  221. package/dist/client/composer/VoiceButton.js.map +1 -1
  222. package/dist/client/composer/index.d.ts +2 -2
  223. package/dist/client/composer/index.d.ts.map +1 -1
  224. package/dist/client/composer/index.js +1 -1
  225. package/dist/client/composer/index.js.map +1 -1
  226. package/dist/client/composer/useRealtimeVoiceMode.d.ts +100 -3
  227. package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +1 -1
  228. package/dist/client/composer/useRealtimeVoiceMode.js +952 -51
  229. package/dist/client/composer/useRealtimeVoiceMode.js.map +1 -1
  230. package/dist/client/index.d.ts +3 -2
  231. package/dist/client/index.d.ts.map +1 -1
  232. package/dist/client/index.js +3 -2
  233. package/dist/client/index.js.map +1 -1
  234. package/dist/client/progress/RunsTray.d.ts.map +1 -1
  235. package/dist/client/progress/RunsTray.js +10 -1
  236. package/dist/client/progress/RunsTray.js.map +1 -1
  237. package/dist/client/session-replay.d.ts +2 -0
  238. package/dist/client/session-replay.d.ts.map +1 -1
  239. package/dist/client/session-replay.js +7 -0
  240. package/dist/client/session-replay.js.map +1 -1
  241. package/dist/client/settings/DemoModeSection.d.ts.map +1 -1
  242. package/dist/client/settings/DemoModeSection.js +4 -23
  243. package/dist/client/settings/DemoModeSection.js.map +1 -1
  244. package/dist/client/settings/SecretsSection.d.ts +2 -3
  245. package/dist/client/settings/SecretsSection.d.ts.map +1 -1
  246. package/dist/client/settings/SecretsSection.js +46 -22
  247. package/dist/client/settings/SecretsSection.js.map +1 -1
  248. package/dist/client/settings/SettingsPanel.d.ts +9 -0
  249. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  250. package/dist/client/settings/SettingsPanel.js +46 -12
  251. package/dist/client/settings/SettingsPanel.js.map +1 -1
  252. package/dist/client/url-scrub.d.ts.map +1 -1
  253. package/dist/client/url-scrub.js +14 -0
  254. package/dist/client/url-scrub.js.map +1 -1
  255. package/dist/client/use-action.d.ts +2 -0
  256. package/dist/client/use-action.d.ts.map +1 -1
  257. package/dist/client/use-action.js +10 -0
  258. package/dist/client/use-action.js.map +1 -1
  259. package/dist/client/use-agent-chat-home-handoff.d.ts +2 -0
  260. package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
  261. package/dist/client/use-agent-chat-home-handoff.js +7 -1
  262. package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
  263. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  264. package/dist/client/use-agent-engine-configured.js +17 -3
  265. package/dist/client/use-agent-engine-configured.js.map +1 -1
  266. package/dist/client/use-db-sync.d.ts +8 -2
  267. package/dist/client/use-db-sync.d.ts.map +1 -1
  268. package/dist/client/use-db-sync.js +57 -32
  269. package/dist/client/use-db-sync.js.map +1 -1
  270. package/dist/client/use-demo-mode-status.d.ts +12 -0
  271. package/dist/client/use-demo-mode-status.d.ts.map +1 -0
  272. package/dist/client/use-demo-mode-status.js +30 -0
  273. package/dist/client/use-demo-mode-status.js.map +1 -0
  274. package/dist/client/use-pausing-interval.d.ts.map +1 -1
  275. package/dist/client/use-pausing-interval.js +16 -4
  276. package/dist/client/use-pausing-interval.js.map +1 -1
  277. package/dist/collab/struct-routes.d.ts +1 -1
  278. package/dist/integrations/scope-store.js +1 -1
  279. package/dist/integrations/scope-store.js.map +1 -1
  280. package/dist/integrations/usage-budget-store.js +1 -1
  281. package/dist/integrations/usage-budget-store.js.map +1 -1
  282. package/dist/localization/default-messages.d.ts +41 -1
  283. package/dist/localization/default-messages.d.ts.map +1 -1
  284. package/dist/localization/default-messages.js +41 -1
  285. package/dist/localization/default-messages.js.map +1 -1
  286. package/dist/mcp-client/workspace-servers.js +4 -4
  287. package/dist/mcp-client/workspace-servers.js.map +1 -1
  288. package/dist/notifications/routes.d.ts +3 -3
  289. package/dist/progress/routes.d.ts +1 -1
  290. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  291. package/dist/resources/handlers.d.ts +3 -3
  292. package/dist/secrets/crypto.d.ts +7 -6
  293. package/dist/secrets/crypto.d.ts.map +1 -1
  294. package/dist/secrets/crypto.js +30 -11
  295. package/dist/secrets/crypto.js.map +1 -1
  296. package/dist/server/action-change.d.ts +1 -0
  297. package/dist/server/action-change.d.ts.map +1 -1
  298. package/dist/server/action-change.js +4 -1
  299. package/dist/server/action-change.js.map +1 -1
  300. package/dist/server/action-routes.d.ts.map +1 -1
  301. package/dist/server/action-routes.js +5 -0
  302. package/dist/server/action-routes.js.map +1 -1
  303. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  304. package/dist/server/poll.d.ts.map +1 -1
  305. package/dist/server/poll.js +1 -0
  306. package/dist/server/poll.js.map +1 -1
  307. package/dist/server/realtime-voice.d.ts +7 -0
  308. package/dist/server/realtime-voice.d.ts.map +1 -1
  309. package/dist/server/realtime-voice.js +222 -12
  310. package/dist/server/realtime-voice.js.map +1 -1
  311. package/dist/styles/agent-native.css +2 -2
  312. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
  313. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
  314. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
  315. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
  316. package/dist/vite/client.d.ts.map +1 -1
  317. package/dist/vite/client.js +6 -1
  318. package/dist/vite/client.js.map +1 -1
  319. package/docs/content/locales/ar-SA/pr-visual-recap.mdx +25 -1
  320. package/docs/content/locales/ar-SA/template-plan.mdx +1 -1
  321. package/docs/content/locales/de-DE/pr-visual-recap.mdx +25 -1
  322. package/docs/content/locales/de-DE/template-plan.mdx +1 -1
  323. package/docs/content/locales/es-ES/pr-visual-recap.mdx +25 -1
  324. package/docs/content/locales/es-ES/template-plan.mdx +1 -1
  325. package/docs/content/locales/fr-FR/pr-visual-recap.mdx +25 -1
  326. package/docs/content/locales/fr-FR/template-plan.mdx +1 -1
  327. package/docs/content/locales/hi-IN/pr-visual-recap.mdx +25 -1
  328. package/docs/content/locales/hi-IN/template-plan.mdx +1 -1
  329. package/docs/content/locales/ja-JP/pr-visual-recap.mdx +25 -1
  330. package/docs/content/locales/ja-JP/template-plan.mdx +1 -1
  331. package/docs/content/locales/ko-KR/pr-visual-recap.mdx +25 -1
  332. package/docs/content/locales/ko-KR/template-plan.mdx +1 -1
  333. package/docs/content/locales/pt-BR/pr-visual-recap.mdx +25 -1
  334. package/docs/content/locales/pt-BR/template-plan.mdx +1 -1
  335. package/docs/content/locales/zh-CN/pr-visual-recap.mdx +25 -1
  336. package/docs/content/locales/zh-CN/template-plan.mdx +1 -1
  337. package/docs/content/locales/zh-TW/pr-visual-recap.mdx +25 -1
  338. package/docs/content/locales/zh-TW/template-plan.mdx +1 -1
  339. package/docs/content/pr-visual-recap.mdx +50 -1
  340. package/docs/content/template-plan.mdx +1 -1
  341. package/package.json +2 -2
  342. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
  343. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
  344. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
  345. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
@@ -170,6 +170,7 @@ import {
170
170
  GuidedQuestionFlow,
171
171
  useGuidedQuestionFlow,
172
172
  } from "./guided-questions.js";
173
+ import { useT } from "./i18n.js";
173
174
  import {
174
175
  AgentAutoContinueSignal,
175
176
  type ContentPart,
@@ -388,6 +389,63 @@ function isAssistantUiDuplicateMessageIdError(error: unknown): boolean {
388
389
  );
389
390
  }
390
391
 
392
+ type AssistantUiMessageRepository = {
393
+ addOrUpdateMessage: (parentId: unknown, message: unknown) => unknown;
394
+ __agentNativePatched?: boolean;
395
+ head?: { current?: { id?: string } } | null;
396
+ };
397
+
398
+ type AssistantUiThreadBinding = {
399
+ getState?: () => { repository?: AssistantUiMessageRepository };
400
+ outerSubscribe?: (callback: () => void) => void | (() => void);
401
+ };
402
+
403
+ /**
404
+ * Keep the assistant-ui repository race recovery installed across runtime-core
405
+ * replacements. The public ThreadRuntime object stays stable when its binding
406
+ * swaps to another local runtime (thread activation, reconnect, history load),
407
+ * but each core owns a different MessageRepository instance.
408
+ */
409
+ export function installAssistantUiMessageRepositoryRecovery(
410
+ threadRuntime: unknown,
411
+ ): () => void {
412
+ const binding = (
413
+ threadRuntime as {
414
+ __internal_threadBinding?: AssistantUiThreadBinding;
415
+ }
416
+ )?.__internal_threadBinding;
417
+ if (!binding?.getState) return () => {};
418
+
419
+ const patchCurrentRepository = () => {
420
+ const repo = binding.getState?.()?.repository;
421
+ if (!repo || typeof repo.addOrUpdateMessage !== "function") return;
422
+ if (repo.__agentNativePatched) return;
423
+ repo.__agentNativePatched = true;
424
+ const original = repo.addOrUpdateMessage.bind(repo);
425
+ repo.addOrUpdateMessage = function (parentId: unknown, message: unknown) {
426
+ try {
427
+ return original(parentId, message);
428
+ } catch (error) {
429
+ const errorMessage =
430
+ error instanceof Error ? error.message : String(error);
431
+ if (parentId && errorMessage.includes("Parent message not found")) {
432
+ const fallbackParent = this.head?.current?.id ?? null;
433
+ if (fallbackParent && fallbackParent !== parentId) {
434
+ return original(fallbackParent, message);
435
+ }
436
+ return original(null, message);
437
+ }
438
+ if (errorMessage.includes("same id already exists")) return;
439
+ throw error;
440
+ }
441
+ };
442
+ };
443
+
444
+ patchCurrentRepository();
445
+ const unsubscribe = binding.outerSubscribe?.(patchCurrentRepository);
446
+ return typeof unsubscribe === "function" ? unsubscribe : () => {};
447
+ }
448
+
391
449
  function cloneContentParts(content: ContentPart[]): ContentPart[] {
392
450
  return content.map((part) =>
393
451
  part.type === "text" || part.type === "reasoning"
@@ -1885,6 +1943,7 @@ const AssistantChatInner = forwardRef<
1885
1943
  ) {
1886
1944
  const thread = useThread();
1887
1945
  const threadRuntime = useThreadRuntime();
1946
+ const t = useT();
1888
1947
  const composerRuntime = useComposerRuntime();
1889
1948
  const isRuntimeRunning = thread.isRunning;
1890
1949
  // Latest-value ref so long-lived async closures (the reconnect reader, its
@@ -1993,41 +2052,19 @@ const AssistantChatInner = forwardRef<
1993
2052
  // assets.agent-native.com prompt composer (AGENT-NATIVE-BROWSER-18). Fix
1994
2053
  // it by relinking to the current head whenever the requested parent has
1995
2054
  // gone missing instead of throwing.
1996
- useEffect(() => {
1997
- const repo = (threadRuntime as any)?.__internal_threadBinding?.getState?.()
1998
- ?.repository as
1999
- | { addOrUpdateMessage?: (parentId: any, message: any) => void }
2000
- | undefined;
2001
- if (!repo || typeof repo.addOrUpdateMessage !== "function") return;
2002
- const patched = repo as any;
2003
- if (patched.__agentNativePatched) return;
2004
- patched.__agentNativePatched = true;
2005
- const original = repo.addOrUpdateMessage.bind(repo);
2006
- repo.addOrUpdateMessage = function (parentId: any, message: any) {
2007
- try {
2008
- return original(parentId, message);
2009
- } catch (err) {
2010
- const msg = err instanceof Error ? err.message : String(err);
2011
- if (parentId && msg.includes("Parent message not found")) {
2012
- const fallbackParent = (this as any).head?.current?.id ?? null;
2013
- if (fallbackParent && fallbackParent !== parentId) {
2014
- return original(fallbackParent, message);
2015
- }
2016
- return original(null, message);
2017
- }
2018
- if (msg.includes("same id already exists")) {
2019
- return;
2020
- }
2021
- throw err;
2022
- }
2023
- };
2024
- }, [threadRuntime]);
2055
+ useEffect(
2056
+ () => installAssistantUiMessageRepositoryRecovery(threadRuntime),
2057
+ [threadRuntime],
2058
+ );
2025
2059
  const agentEngineConfigured = useAgentEngineConfigured(
2026
2060
  providerStatusChecksEnabled,
2027
2061
  { tabId, threadId },
2028
2062
  );
2029
2063
  const missingApiKey = agentEngineConfigured.missing;
2030
- const isComposerDisabled = missingApiKey || composerDisabled;
2064
+ const isProviderStatusChecking =
2065
+ providerStatusChecksEnabled && agentEngineConfigured.state === "unknown";
2066
+ const isComposerDisabled =
2067
+ missingApiKey || isProviderStatusChecking || composerDisabled;
2031
2068
  const [missingKeySetupOpen, setMissingKeySetupOpen] = useState(false);
2032
2069
  const requestMissingKeySetup = useCallback(() => {
2033
2070
  setMissingKeySetupOpen(true);
@@ -2043,7 +2080,12 @@ const AssistantChatInner = forwardRef<
2043
2080
  : await fetchAgentEngineConfiguredState(providerStatusChecksEnabled, {
2044
2081
  timeoutMs: SUBMIT_ENGINE_STATUS_TIMEOUT_MS,
2045
2082
  });
2046
- if (state !== "missing") return true;
2083
+ if (state === "configured") return true;
2084
+
2085
+ // Unknown means the readiness endpoint is unavailable or still resolving.
2086
+ // Do not start a run optimistically: that recreates the long failure path
2087
+ // this preflight exists to prevent. The mounted hook retries automatically.
2088
+ if (state === "unknown") return false;
2047
2089
 
2048
2090
  requestMissingKeySetup();
2049
2091
  if (typeof window !== "undefined") {
@@ -5150,14 +5192,16 @@ const AssistantChatInner = forwardRef<
5150
5192
  placeholder={
5151
5193
  missingApiKey
5152
5194
  ? "Connect AI to start chatting..."
5153
- : composerDisabled
5154
- ? (composerDisabledPlaceholder ??
5155
- "Open Desktop to use this chat.")
5156
- : isRunning
5157
- ? queuedMessages.length > 0
5158
- ? `${queuedMessages.length} queued — send a follow-up...`
5159
- : "Send a follow-up..."
5160
- : composerPlaceholder
5195
+ : isProviderStatusChecking
5196
+ ? t("agentPanel.checkingAiConnection")
5197
+ : composerDisabled
5198
+ ? (composerDisabledPlaceholder ??
5199
+ "Open Desktop to use this chat.")
5200
+ : isRunning
5201
+ ? queuedMessages.length > 0
5202
+ ? `${queuedMessages.length} queued — send a follow-up...`
5203
+ : "Send a follow-up..."
5204
+ : composerPlaceholder
5161
5205
  }
5162
5206
  onSubmit={
5163
5207
  isRunning || composerContextItems.length > 0
@@ -89,6 +89,13 @@ export type ConfigureTrackingOptions = {
89
89
  /** First-party analytics track endpoint. */
90
90
  endpoint?: string;
91
91
  getDefaultProps?: GetDefaultProps;
92
+ /**
93
+ * Disable content-capturing analytics such as interaction autocapture and
94
+ * session replay while retaining pageviews, explicit events, and Sentry.
95
+ */
96
+ contentCapture?: boolean;
97
+ /** Resolve content capture synchronously for each browser pathname. */
98
+ contentCaptureForPath?: (pathname: string) => boolean;
92
99
  sessionReplay?: boolean | SessionReplayOptions;
93
100
  /**
94
101
  * First-party, Sentry-style error capture. Auto-captures uncaught errors
@@ -132,6 +139,8 @@ let _errorCaptureDisposer: (() => void) | null = null;
132
139
  let _sessionReplayModuleForCapture:
133
140
  | typeof import("./session-replay.js")
134
141
  | null = null;
142
+ let _trackingContentCaptureEnabled = true;
143
+ let _contentCaptureForPath: ((pathname: string) => boolean) | null = null;
135
144
  // Buffer for setSentryUser calls made before Sentry has initialized.
136
145
  // `undefined` means "no pending update"; `null` means "pending clear".
137
146
  let _pendingSentryUser: SentryUser | null | undefined = undefined;
@@ -575,7 +584,10 @@ function ensureAmplitude(): boolean {
575
584
  const key = (import.meta.env as Record<string, string | undefined>)
576
585
  ?.VITE_AMPLITUDE_API_KEY;
577
586
  if (!key) return false;
578
- amplitude.init(key, { autocapture: true });
587
+ // Standard pageviews and explicit events are emitted below. Keep SDK-level
588
+ // DOM/network autocapture off so rendered user content is never collected as
589
+ // an implicit analytics side effect.
590
+ amplitude.init(key, { autocapture: false });
579
591
  _amplitudeInitialized = true;
580
592
  return true;
581
593
  }
@@ -618,12 +630,41 @@ function isAgentNativeDocsUrl(url: string): boolean {
618
630
  }
619
631
  }
620
632
 
633
+ function isSessionReplayUrl(url: string): boolean {
634
+ if (!url) return false;
635
+ try {
636
+ const parsed = new URL(url);
637
+ return /^\/sessions\/[^/]+\/?$/.test(parsed.pathname);
638
+ } catch {
639
+ return false;
640
+ }
641
+ }
642
+
621
643
  function shouldDropBrowserSentryNoise(event: Sentry.Event): boolean {
622
644
  const exceptionValues = event.exception?.values ?? [];
623
645
  const taggedUrl =
624
646
  typeof event.tags?.url === "string" ? event.tags.url : undefined;
625
647
  const requestUrl = (event.request?.url ?? taggedUrl ?? "").toLowerCase();
626
648
  const isDocsPage = isAgentNativeDocsUrl(requestUrl);
649
+ // rrweb 2.1.0 replays recorded media interactions with `void media.play()`.
650
+ // Browsers may reject that promise when the recorded media was unmuted and
651
+ // no user activation is still active, which becomes a source-less unhandled
652
+ // rejection even though the replay player keeps working. Keep this scoped to
653
+ // the replay detail route and the exact browser autoplay-policy message.
654
+ if (
655
+ isSessionReplayUrl(requestUrl) &&
656
+ exceptionValues.some((value) => {
657
+ const exceptionValue = String(value.value ?? "")
658
+ .trim()
659
+ .toLowerCase();
660
+ return (
661
+ exceptionValue.includes("notallowederror: play() failed") &&
662
+ exceptionValue.includes("user didn't interact with the document first")
663
+ );
664
+ })
665
+ ) {
666
+ return true;
667
+ }
627
668
  // AgentAutoContinueSignal is a control-flow sentinel thrown to bubble
628
669
  // out of the SSE stream parser when the agent run needs to be
629
670
  // auto-continued. It's caught by the chat adapter and is never a real
@@ -867,7 +908,11 @@ export function setSentryUser(
867
908
  clearTrackingIdentity();
868
909
  }
869
910
  _trackingIdentityResolved = true;
870
- if (shouldRetryReplay && _sessionReplayOptions?.requireSignedInUser) {
911
+ if (
912
+ shouldRetryReplay &&
913
+ _trackingContentCaptureEnabled &&
914
+ _sessionReplayOptions?.requireSignedInUser
915
+ ) {
871
916
  void startConfiguredSessionReplay(_sessionReplayOptions);
872
917
  }
873
918
  if (_sentryInitialized) {
@@ -975,6 +1020,11 @@ export function configureTracking(options: ConfigureTrackingOptions): void {
975
1020
  if (options.getDefaultProps) {
976
1021
  _getDefaultProps = options.getDefaultProps;
977
1022
  }
1023
+ _contentCaptureForPath = options.contentCaptureForPath ?? null;
1024
+ _trackingContentCaptureEnabled =
1025
+ _contentCaptureForPath && typeof window !== "undefined"
1026
+ ? _contentCaptureForPath(window.location.pathname)
1027
+ : options.contentCapture !== false;
978
1028
  if (typeof window !== "undefined") {
979
1029
  ensureSentry();
980
1030
  ensureAmplitude();
@@ -982,14 +1032,37 @@ export function configureTracking(options: ConfigureTrackingOptions): void {
982
1032
  installLlmConnectionRefresh();
983
1033
  installTrackingAuthSessionRefresh();
984
1034
  installPageviewTracking();
985
- maybeInstallSessionReplay(options.sessionReplay, {
986
- endpoint: options.endpoint,
987
- publicKey,
988
- });
1035
+ maybeInstallSessionReplay(
1036
+ options.sessionReplay,
1037
+ {
1038
+ endpoint: options.endpoint,
1039
+ publicKey,
1040
+ },
1041
+ _trackingContentCaptureEnabled,
1042
+ );
989
1043
  maybeInstallErrorCapture(options.errorCapture);
990
1044
  }
991
1045
  }
992
1046
 
1047
+ export function setTrackingContentCaptureEnabled(enabled: boolean): void {
1048
+ if (_trackingContentCaptureEnabled === enabled) return;
1049
+ _trackingContentCaptureEnabled = enabled;
1050
+ if (enabled) {
1051
+ if (_sessionReplayOptions) {
1052
+ void startConfiguredSessionReplay(_sessionReplayOptions);
1053
+ }
1054
+ } else {
1055
+ void stopSessionReplay("content-capture-disabled");
1056
+ }
1057
+ }
1058
+
1059
+ function syncTrackingContentCaptureForLocation(): void {
1060
+ if (!_contentCaptureForPath) return;
1061
+ setTrackingContentCaptureEnabled(
1062
+ _contentCaptureForPath(window.location.pathname),
1063
+ );
1064
+ }
1065
+
993
1066
  /**
994
1067
  * Lazily load the session-replay module so error capture can read the active
995
1068
  * replay id and surface manual captures on the replay timeline without a
@@ -1225,11 +1298,12 @@ function replayEndpointFromTrackingEndpoint(value: string): string | undefined {
1225
1298
  function maybeInstallSessionReplay(
1226
1299
  config: boolean | SessionReplayOptions | undefined,
1227
1300
  tracking?: { endpoint?: string; publicKey?: string },
1301
+ start = true,
1228
1302
  ): void {
1229
1303
  if (typeof window === "undefined") return;
1230
1304
  const options = configuredSessionReplayOptions(config, tracking);
1231
- if (!options) return;
1232
1305
  _sessionReplayOptions = options;
1306
+ if (!options || !start) return;
1233
1307
  void startConfiguredSessionReplay(options);
1234
1308
  }
1235
1309
 
@@ -1255,11 +1329,24 @@ async function startConfiguredSessionReplay(
1255
1329
  ): Promise<SessionReplayStartResult | null> {
1256
1330
  if (_sessionReplayStartPromise) return _sessionReplayStartPromise;
1257
1331
  _sessionReplayStartPromise = (async () => {
1332
+ if (!_trackingContentCaptureEnabled) {
1333
+ return { started: false, reason: "disabled" as const };
1334
+ }
1258
1335
  if (!(await waitForSessionReplayAuthIfRequired(options))) {
1259
1336
  return { started: false, reason: "missing-user-id" as const };
1260
1337
  }
1338
+ if (!_trackingContentCaptureEnabled) {
1339
+ return { started: false, reason: "disabled" as const };
1340
+ }
1261
1341
  const mod = await import("./session-replay.js");
1262
- return mod.startSessionReplay(options);
1342
+ if (!_trackingContentCaptureEnabled) {
1343
+ return { started: false, reason: "disabled" as const };
1344
+ }
1345
+ return mod.startSessionReplay({
1346
+ ...options,
1347
+ shouldStart: () =>
1348
+ _trackingContentCaptureEnabled && (options.shouldStart?.() ?? true),
1349
+ });
1263
1350
  })()
1264
1351
  .catch(() => ({ started: false, reason: "import-failed" as const }))
1265
1352
  .finally(() => {
@@ -1271,23 +1358,37 @@ async function startConfiguredSessionReplay(
1271
1358
  export async function startSessionReplay(
1272
1359
  options: SessionReplayOptions = {},
1273
1360
  ): Promise<SessionReplayStartResult> {
1361
+ if (!_trackingContentCaptureEnabled) {
1362
+ return { started: false, reason: "disabled" };
1363
+ }
1274
1364
  const configured = configuredSessionReplayOptions(options) ?? options;
1275
1365
  if (!(await waitForSessionReplayAuthIfRequired(configured))) {
1276
1366
  return { started: false, reason: "missing-user-id" };
1277
1367
  }
1278
1368
  const mod = await import("./session-replay.js");
1279
- return mod.startSessionReplay(configured);
1369
+ return mod.startSessionReplay({
1370
+ ...configured,
1371
+ shouldStart: () =>
1372
+ _trackingContentCaptureEnabled && (configured.shouldStart?.() ?? true),
1373
+ });
1280
1374
  }
1281
1375
 
1282
1376
  export async function maybeStartSessionReplay(
1283
1377
  options: SessionReplayOptions = {},
1284
1378
  ): Promise<SessionReplayStartResult> {
1379
+ if (!_trackingContentCaptureEnabled) {
1380
+ return { started: false, reason: "disabled" };
1381
+ }
1285
1382
  const configured = configuredSessionReplayOptions(options) ?? options;
1286
1383
  if (!(await waitForSessionReplayAuthIfRequired(configured))) {
1287
1384
  return { started: false, reason: "missing-user-id" };
1288
1385
  }
1289
1386
  const mod = await import("./session-replay.js");
1290
- return mod.maybeStartSessionReplay(configured);
1387
+ return mod.maybeStartSessionReplay({
1388
+ ...configured,
1389
+ shouldStart: () =>
1390
+ _trackingContentCaptureEnabled && (configured.shouldStart?.() ?? true),
1391
+ });
1291
1392
  }
1292
1393
 
1293
1394
  export async function stopSessionReplay(reason = "manual"): Promise<void> {
@@ -1342,15 +1443,17 @@ function pageviewKey(): string {
1342
1443
 
1343
1444
  function pageviewProperties(reason: string): Record<string, unknown> {
1344
1445
  const properties: Record<string, unknown> = {
1345
- url: scrubUrl(window.location.href),
1446
+ url: !_trackingContentCaptureEnabled
1447
+ ? window.location.origin + window.location.pathname
1448
+ : scrubUrl(window.location.href),
1346
1449
  path: window.location.pathname,
1347
1450
  hostname: window.location.hostname,
1348
1451
  navigation_type: reason,
1349
1452
  };
1350
- if (window.location.search) {
1453
+ if (_trackingContentCaptureEnabled && window.location.search) {
1351
1454
  properties.search = scrubUrl(window.location.search);
1352
1455
  }
1353
- if (typeof document !== "undefined") {
1456
+ if (_trackingContentCaptureEnabled && typeof document !== "undefined") {
1354
1457
  if (document.referrer) {
1355
1458
  properties.referrer = scrubUrl(document.referrer);
1356
1459
  }
@@ -1371,6 +1474,9 @@ function emitPageview(reason: string): void {
1371
1474
  }
1372
1475
 
1373
1476
  function schedulePageview(reason: string): void {
1477
+ if (!_trackingContentCaptureEnabled) {
1478
+ void stopSessionReplay("local-plan-privacy");
1479
+ }
1374
1480
  const run = () => emitPageview(reason);
1375
1481
  const pendingStartupContext: Array<Promise<void>> = [];
1376
1482
  if (_llmConnectionRefresh && !_llmConnectionStatus) {
@@ -1407,17 +1513,22 @@ function installPageviewTracking(): void {
1407
1513
 
1408
1514
  window.history.pushState = function pushState(...args) {
1409
1515
  const result = originalPushState.apply(this, args);
1516
+ syncTrackingContentCaptureForLocation();
1410
1517
  schedulePageview("pushState");
1411
1518
  return result;
1412
1519
  };
1413
1520
 
1414
1521
  window.history.replaceState = function replaceState(...args) {
1415
1522
  const result = originalReplaceState.apply(this, args);
1523
+ syncTrackingContentCaptureForLocation();
1416
1524
  schedulePageview("replaceState");
1417
1525
  return result;
1418
1526
  };
1419
1527
 
1420
- window.addEventListener("popstate", () => schedulePageview("popstate"));
1528
+ window.addEventListener("popstate", () => {
1529
+ syncTrackingContentCaptureForLocation();
1530
+ schedulePageview("popstate");
1531
+ });
1421
1532
  }
1422
1533
 
1423
1534
  function sendAgentNativeAnalytics(
@@ -1511,6 +1511,20 @@ function roundedRectPath(
1511
1511
  ].join(" ");
1512
1512
  }
1513
1513
 
1514
+ /** Rough.js cannot safely render paths whose inset consumes the whole box. */
1515
+ export function hasDrawableRoughBounds(
1516
+ width: number,
1517
+ height: number,
1518
+ inset: number,
1519
+ ): boolean {
1520
+ return (
1521
+ Number.isFinite(width) &&
1522
+ Number.isFinite(height) &&
1523
+ width > inset * 2 &&
1524
+ height > inset * 2
1525
+ );
1526
+ }
1527
+
1514
1528
  function elementStroke(node: Element, fallback: string): string {
1515
1529
  const explicit = readVar(node, "--rough-stroke");
1516
1530
  if (explicit) return explicit;
@@ -1623,7 +1637,7 @@ function build(
1623
1637
  preserveVertices: true,
1624
1638
  });
1625
1639
 
1626
- if (opts.drawFrame) {
1640
+ if (opts.drawFrame && hasDrawableRoughBounds(layoutW, layoutH, 2)) {
1627
1641
  const sw = 2;
1628
1642
  push(
1629
1643
  gen.path(
@@ -1647,7 +1661,7 @@ function build(
1647
1661
  const y = (r.top - base.top) / zoom;
1648
1662
  const w = r.width / zoom;
1649
1663
  const h = r.height / zoom;
1650
- if (w < 2 || h < 2) return;
1664
+ if (!hasDrawableRoughBounds(w, h, 1)) return;
1651
1665
  const kind = inferRoughKind(node);
1652
1666
  const rawStroke = elementStroke(node, sketch);
1653
1667
  const stroke =
@@ -21,6 +21,12 @@ export interface BuildChatModelGroupsOptions {
21
21
  currentModel?: string;
22
22
  }
23
23
 
24
+ const HIDDEN_CHAT_MODEL_ENGINES = new Set([
25
+ "ai-sdk:groq",
26
+ "ai-sdk:mistral",
27
+ "ai-sdk:cohere",
28
+ ]);
29
+
24
30
  function addCurrentModel(
25
31
  models: readonly string[],
26
32
  engineName: string,
@@ -93,6 +99,15 @@ function shouldShowDirectEngine(
93
99
  engine: ChatModelEngineEntry,
94
100
  currentEngineName?: string,
95
101
  ): boolean {
102
+ // Keep a persisted selection usable after an engine is hidden from the
103
+ // picker; users can choose a supported replacement instead of landing on a
104
+ // model that no longer has a rendered group.
105
+ if (
106
+ HIDDEN_CHAT_MODEL_ENGINES.has(engine.name) &&
107
+ engine.name !== currentEngineName
108
+ ) {
109
+ return false;
110
+ }
96
111
  if (engine.name === currentEngineName) return true;
97
112
  if (engine.name === "builder") return false;
98
113
  if (engine.name === "ai-sdk:anthropic") return false;
@@ -100,6 +115,18 @@ function shouldShowDirectEngine(
100
115
  return true;
101
116
  }
102
117
 
118
+ function putOpenRouterLast(
119
+ a: ChatModelEngineEntry,
120
+ b: ChatModelEngineEntry,
121
+ ): number {
122
+ const aIsOpenRouter = a.name === "ai-sdk:openrouter";
123
+ const bIsOpenRouter = b.name === "ai-sdk:openrouter";
124
+ if (aIsOpenRouter === bIsOpenRouter) return 0;
125
+ if (aIsOpenRouter) return 1;
126
+ if (bIsOpenRouter) return -1;
127
+ return 0;
128
+ }
129
+
103
130
  export function buildChatModelGroups({
104
131
  engines,
105
132
  configuredKeys,
@@ -123,6 +150,7 @@ export function buildChatModelGroups({
123
150
  return engines
124
151
  .filter((engine) => engine.packageInstalled !== false)
125
152
  .filter((engine) => shouldShowDirectEngine(engine, currentEngineName))
153
+ .sort(putOpenRouterLast)
126
154
  .map((engine) => {
127
155
  const requiredEnvVars = engine.requiredEnvVars ?? [];
128
156
  return {