@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
@@ -30,7 +30,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
30
30
  useDbSync({ queryClient });
31
31
  ```
32
32
 
33
- For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries for ordinary domain events — that caused a request storm in production. The exception is `source: "action"`: a successful mutating action is the framework-wide "agent changed app data" signal, so `useDbSync` also refreshes active React Query observers as a compatibility safety net for custom apps that have not yet moved every read to `useActionQuery` or source-versioned query keys.
33
+ For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries — that caused request storms in production. A successful mutating action refreshes active `useActionQuery` observers under the `["action"]` prefix. Browser actions carry a tab id so their originating tab ignores the sync echo while other tabs refresh. Legacy apps can opt into broader compatibility with `actionInvalidatePredicate`, but first-party apps should use action-backed or source-versioned query keys. Idle fallback polling runs once per minute; active agent work temporarily uses the faster cadence.
34
34
 
35
35
  3. **Templates fold per-source counters into their query keys.** This is the pattern that makes "agent writes show up without a manual refresh" reliable:
36
36
 
@@ -117,7 +117,7 @@ useQuery({
117
117
  | UI not updating after agent writes | Is `useDbSync` called with the correct `queryClient`? Does the affected query have an active observer? |
118
118
  | Poll endpoint not responding | Is `/_agent-native/poll` accessible? Is the server running? |
119
119
  | SSE not connecting | Is `/_agent-native/events` accessible and authenticated? Polling should still keep the UI fresh as fallback. |
120
- | High CPU / event storms | The agent is writing rapidly. Add `staleTime` to queries to debounce refetches. |
120
+ | High CPU / event storms | Use targeted source keys, settle bursty list counters, and avoid broad action invalidation. |
121
121
 
122
122
  ## Jitter Prevention
123
123
 
@@ -230,6 +230,7 @@ export default function Root() {
230
230
  // Calendar aggressively refetches on focus because external
231
231
  // calendar events can change without a DB sync event (e.g. Google
232
232
  // Calendar webhooks with a processing delay).
233
+ // request-storm-allow: one user-driven focus refresh for provider data.
233
234
  refetchOnWindowFocus: true,
234
235
  // Flat retry: calendar data fetches don't need the auth-aware
235
236
  // retry function — auth errors surface through the booking flow.
@@ -30,7 +30,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
30
30
  useDbSync({ queryClient });
31
31
  ```
32
32
 
33
- For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries for ordinary domain events — that caused a request storm in production. The exception is `source: "action"`: a successful mutating action is the framework-wide "agent changed app data" signal, so `useDbSync` also refreshes active React Query observers as a compatibility safety net for custom apps that have not yet moved every read to `useActionQuery` or source-versioned query keys.
33
+ For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries — that caused request storms in production. A successful mutating action refreshes active `useActionQuery` observers under the `["action"]` prefix. Browser actions carry a tab id so their originating tab ignores the sync echo while other tabs refresh. Legacy apps can opt into broader compatibility with `actionInvalidatePredicate`, but first-party apps should use action-backed or source-versioned query keys. Idle fallback polling runs once per minute; active agent work temporarily uses the faster cadence.
34
34
 
35
35
  3. **Templates fold per-source counters into their query keys.** This is the pattern that makes "agent writes show up without a manual refresh" reliable:
36
36
 
@@ -117,7 +117,7 @@ useQuery({
117
117
  | UI not updating after agent writes | Is `useDbSync` called with the correct `queryClient`? Does the affected query have an active observer? |
118
118
  | Poll endpoint not responding | Is `/_agent-native/poll` accessible? Is the server running? |
119
119
  | SSE not connecting | Is `/_agent-native/events` accessible and authenticated? Polling should still keep the UI fresh as fallback. |
120
- | High CPU / event storms | The agent is writing rapidly. Add `staleTime` to queries to debounce refetches. |
120
+ | High CPU / event storms | Use targeted source keys, settle bursty list counters, and avoid broad action invalidation. |
121
121
 
122
122
  ## Jitter Prevention
123
123
 
@@ -1083,13 +1083,17 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
1083
1083
  const fullscreenMenuContainer = isFullscreen ? containerRef.current : null;
1084
1084
 
1085
1085
  const showThroughoutCta = cta && cta.placement === "throughout";
1086
+ // Mobile Safari may defer loadeddata/canplay until playback starts. Keep
1087
+ // the paused state actionable even when those readiness events have not
1088
+ // fired yet; once the user asks to play, the pending/buffering states give
1089
+ // them accurate loading feedback.
1086
1090
  const centerOverlayMode =
1087
1091
  activeVideoSrc &&
1088
1092
  !isLoomEmbed &&
1089
1093
  !unsupportedFormat &&
1090
1094
  !showEndCta &&
1091
1095
  (!isPlaying || isPlayPending || isBuffering)
1092
- ? isPreparing || isPlayPending || isBuffering || !canPlay
1096
+ ? isPlayPending || isBuffering
1093
1097
  ? "loading"
1094
1098
  : "ready"
1095
1099
  : null;
@@ -16,6 +16,7 @@ import {
16
16
  callAction,
17
17
  sendToAgentChat,
18
18
  type AgentChatMessage,
19
+ useChangeVersions,
19
20
  } from "@agent-native/core/client";
20
21
  import { fullVideoAiModelSelection } from "@shared/clips-ai-prefs";
21
22
  import { useEffect, useRef } from "react";
@@ -23,7 +24,6 @@ import { useEffect, useRef } from "react";
23
24
  import { useRecordings, type RecordingSummary } from "./use-library";
24
25
 
25
26
  const DEFAULT_TITLE = "Untitled recording";
26
- const POLL_INTERVAL_MS = 3000;
27
27
  const TWO_MINUTES_MS = 2 * 60 * 1000;
28
28
 
29
29
  /** True when `title` is blank or equal to the server-seeded default. */
@@ -99,8 +99,9 @@ async function clearRequest(recordingId: string): Promise<void> {
99
99
  }
100
100
 
101
101
  /**
102
- * Mount this once in the app shell. It polls the recording list and fires
103
- * `sendToAgentChat` for every pending request queued by a clips action.
102
+ * Mount this once in the app shell. It watches the exact application-state
103
+ * keys used for queued Clips AI work and fires `sendToAgentChat` for every
104
+ * pending request queued by a clips action.
104
105
  * Idempotent — a given (recordingId, kind, requestedAt) is only dispatched
105
106
  * once per tab session.
106
107
  */
@@ -119,13 +120,26 @@ export function useAutoTitleBridge(): void {
119
120
  `${r.id}:${r.titleSource ?? ""}:${r.title}:${r.updatedAt}:${r.transcriptStatus ?? ""}:${r.transcriptHasText ? "1" : "0"}`,
120
121
  )
121
122
  .join("|");
123
+ const aiRequestVersion = useChangeVersions(
124
+ readyRecordings.map(
125
+ (recording) => `app-state:clips-ai-request-${recording.id}`,
126
+ ),
127
+ );
122
128
 
123
129
  useEffect(() => {
124
130
  if (readyRecordings.length === 0) return;
125
131
  let cancelled = false;
132
+ let fallbackTimer: ReturnType<typeof setTimeout> | null = null;
126
133
 
127
134
  async function tick() {
128
- if (cancelled || inflight.current) return;
135
+ if (cancelled) return;
136
+ if (inflight.current) {
137
+ // A new request-state version can arrive while the previous list read
138
+ // is in flight. Recheck after it settles so that event is not the last
139
+ // chance to dispatch the queued work.
140
+ fallbackTimer = setTimeout(() => void tick(), 50);
141
+ return;
142
+ }
129
143
  inflight.current = true;
130
144
  try {
131
145
  const requestsById = await listRequests();
@@ -192,14 +206,66 @@ export function useAutoTitleBridge(): void {
192
206
  }
193
207
  }
194
208
 
195
- tick();
196
- const handle = setInterval(tick, POLL_INTERVAL_MS);
209
+ function scheduleNextFallback() {
210
+ if (cancelled) return;
211
+ const delay = nextAutoTitleFallbackDelay(
212
+ readyRecordings,
213
+ dispatched.current,
214
+ );
215
+ if (delay === null) return;
216
+ // Keep the timeout non-zero so a failed request cannot spin a tight loop.
217
+ fallbackTimer = setTimeout(
218
+ () => {
219
+ fallbackTimer = null;
220
+ void tick().finally(scheduleNextFallback);
221
+ },
222
+ Math.max(delay, 50),
223
+ );
224
+ }
225
+
226
+ // One initial read catches requests queued before this component mounted.
227
+ // Later reads are driven by the exact clips-ai-request application-state
228
+ // counters above. The only timer left is a one-shot wake-up when an old
229
+ // transcript-backed recording becomes eligible for the legacy fallback.
230
+ void tick().finally(scheduleNextFallback);
197
231
  return () => {
198
232
  cancelled = true;
199
- clearInterval(handle);
233
+ if (fallbackTimer) clearTimeout(fallbackTimer);
200
234
  };
235
+ // readyRecordingsKey is the stable snapshot consumed by tick; depending on
236
+ // the array itself would restart the effect on every query result object.
201
237
  // eslint-disable-next-line react-hooks/exhaustive-deps
202
- }, [readyRecordingsKey]);
238
+ }, [aiRequestVersion, readyRecordingsKey]);
239
+ }
240
+
241
+ export function nextAutoTitleFallbackDelay(
242
+ recordings: readonly RecordingSummary[],
243
+ dispatched: ReadonlySet<string>,
244
+ now = Date.now(),
245
+ ): number | null {
246
+ let nextDelay: number | null = null;
247
+
248
+ for (const recording of recordings) {
249
+ if (recording.status !== "ready") continue;
250
+ if (!isAutoTitleReplaceable(recording.title, recording.titleSource)) {
251
+ continue;
252
+ }
253
+ if (
254
+ recording.transcriptStatus !== "ready" ||
255
+ recording.transcriptHasText !== true ||
256
+ dispatched.has(`${recording.id}:fallback`)
257
+ ) {
258
+ continue;
259
+ }
260
+
261
+ const createdAt = new Date(recording.createdAt).getTime();
262
+ const delay = Number.isFinite(createdAt)
263
+ ? Math.max(0, TWO_MINUTES_MS - (now - createdAt))
264
+ : 0;
265
+ nextDelay = nextDelay === null ? delay : Math.min(nextDelay, delay);
266
+ }
267
+
268
+ return nextDelay;
203
269
  }
204
270
 
205
271
  function buildRequestContext(rec: RecordingSummary, request: AiRequest) {
@@ -44,24 +44,13 @@ export interface ListRecordingsArgs {
44
44
  offset?: number;
45
45
  }
46
46
 
47
- function isAwaitingAutoTitle(recording: RecordingSummary): boolean {
48
- const title = (recording.title ?? "").trim();
49
- const titleIsReplaceable =
50
- title === "" ||
51
- title === "Untitled recording" ||
52
- recording.titleSource === "default" ||
53
- recording.titleSource === "context";
54
- if (!titleIsReplaceable) return false;
55
-
56
- if (recording.transcriptStatus === "failed") return false;
57
- if (recording.transcriptStatus === "ready") {
58
- return recording.transcriptHasText === true;
59
- }
60
-
61
- return (
62
- recording.transcriptStatus === "pending" ||
63
- recording.transcriptStatus === "streaming"
64
- );
47
+ export function recordingsRefetchInterval(
48
+ recordings: readonly RecordingSummary[] | undefined,
49
+ ): number | false {
50
+ if (!recordings || recordings.length === 0) return false;
51
+ return recordings.some((recording) => isLiveRecordingUpload(recording))
52
+ ? 3000
53
+ : false;
65
54
  }
66
55
 
67
56
  export function useRecordings(args: ListRecordingsArgs = {}) {
@@ -74,17 +63,15 @@ export function useRecordings(args: ListRecordingsArgs = {}) {
74
63
  recordings: Array.isArray(data?.recordings) ? data.recordings : [],
75
64
  };
76
65
  },
77
- // Keep a short poll while uploads/processors are active so the library
78
- // card does not get stuck if the global refresh signal is missed.
79
- // Also poll for replaceable seed titles so the card upgrades promptly.
66
+ // Keep a short poll only while uploads/processors are active so the
67
+ // library card does not get stuck if the global refresh signal is
68
+ // missed. Generated titles arrive through the shared DB sync transport;
69
+ // polling completed recordings forever is both redundant and expensive.
80
70
  refetchInterval: (q) => {
81
71
  const recs = (q.state.data as any)?.recordings as
82
72
  | RecordingSummary[]
83
73
  | undefined;
84
- if (!recs || recs.length === 0) return false;
85
- const pendingUpload = recs.some((rec) => isLiveRecordingUpload(rec));
86
- const pendingTitle = recs.some(isAwaitingAutoTitle);
87
- return pendingUpload || pendingTitle ? 3000 : false;
74
+ return recordingsRefetchInterval(recs);
88
75
  },
89
76
  },
90
77
  );
@@ -734,7 +734,7 @@ export default function SettingsIndexRoute() {
734
734
  builderStatus.loading ||
735
735
  !builderConnect.hasFetchedStatus;
736
736
  const s3Configured = activeProviderId === "s3";
737
- const s3Collapsed = builderConnected && !s3Expanded;
737
+ const s3Collapsed = !s3Expanded;
738
738
  const configuredApiKeyCount = AI_PROVIDER_FIELDS.filter(
739
739
  (field) => apiKeyStatus[field.key],
740
740
  ).length;
@@ -908,7 +908,7 @@ export default function SettingsIndexRoute() {
908
908
  </div>
909
909
 
910
910
  <Collapsible
911
- open={builderConnected ? !s3Collapsed : true}
911
+ open={!s3Collapsed}
912
912
  onOpenChange={(open) => setS3Expanded(open)}
913
913
  >
914
914
  <div className="rounded-md border border-border">
@@ -939,26 +939,24 @@ export default function SettingsIndexRoute() {
939
939
  : t("settings.s3OwnBucketDescription")}
940
940
  </p>
941
941
  </div>
942
- {builderConnected ? (
943
- <CollapsibleTrigger asChild>
944
- <Button
945
- type="button"
946
- variant="ghost"
947
- size="sm"
948
- className="shrink-0"
949
- >
950
- {s3Collapsed
951
- ? t("settings.configureS3")
952
- : t("settings.hideS3")}
953
- <IconChevronDown
954
- className={cn(
955
- "h-4 w-4 transition-transform",
956
- !s3Collapsed && "rotate-180",
957
- )}
958
- />
959
- </Button>
960
- </CollapsibleTrigger>
961
- ) : null}
942
+ <CollapsibleTrigger asChild>
943
+ <Button
944
+ type="button"
945
+ variant="ghost"
946
+ size="sm"
947
+ className="shrink-0"
948
+ >
949
+ {s3Collapsed
950
+ ? t("settings.configureS3")
951
+ : t("settings.hideS3")}
952
+ <IconChevronDown
953
+ className={cn(
954
+ "h-4 w-4 transition-transform",
955
+ !s3Collapsed && "rotate-180",
956
+ )}
957
+ />
958
+ </Button>
959
+ </CollapsibleTrigger>
962
960
  </div>
963
961
 
964
962
  <CollapsibleContent>
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-11
4
+ ---
5
+
6
+ Clips no longer stay stuck on Preparing clip when they are ready to play on mobile.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-11
4
+ ---
5
+
6
+ Generated titles no longer cause continuous background refreshes after a recording is ready.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-11
4
+ ---
5
+
6
+ S3 storage setup stays collapsed until you choose it as the secondary storage option.
@@ -30,7 +30,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
30
30
  useDbSync({ queryClient });
31
31
  ```
32
32
 
33
- For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries for ordinary domain events — that caused a request storm in production. The exception is `source: "action"`: a successful mutating action is the framework-wide "agent changed app data" signal, so `useDbSync` also refreshes active React Query observers as a compatibility safety net for custom apps that have not yet moved every read to `useActionQuery` or source-versioned query keys.
33
+ For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries — that caused request storms in production. A successful mutating action refreshes active `useActionQuery` observers under the `["action"]` prefix. Browser actions carry a tab id so their originating tab ignores the sync echo while other tabs refresh. Legacy apps can opt into broader compatibility with `actionInvalidatePredicate`, but first-party apps should use action-backed or source-versioned query keys. Idle fallback polling runs once per minute; active agent work temporarily uses the faster cadence.
34
34
 
35
35
  3. **Templates fold per-source counters into their query keys.** This is the pattern that makes "agent writes show up without a manual refresh" reliable:
36
36
 
@@ -117,7 +117,7 @@ useQuery({
117
117
  | UI not updating after agent writes | Is `useDbSync` called with the correct `queryClient`? Does the affected query have an active observer? |
118
118
  | Poll endpoint not responding | Is `/_agent-native/poll` accessible? Is the server running? |
119
119
  | SSE not connecting | Is `/_agent-native/events` accessible and authenticated? Polling should still keep the UI fresh as fallback. |
120
- | High CPU / event storms | The agent is writing rapidly. Add `staleTime` to queries to debounce refetches. |
120
+ | High CPU / event storms | Use targeted source keys, settle bursty list counters, and avoid broad action invalidation. |
121
121
 
122
122
  ## Jitter Prevention
123
123
 
@@ -1188,8 +1188,8 @@ export function DocumentSidebar({
1188
1188
  </div>
1189
1189
  )}
1190
1190
 
1191
- <ScrollArea className="min-h-0 flex-1">
1192
- <div className="min-w-full w-max py-2 pe-2">
1191
+ <ScrollArea className="min-h-0 flex-1 [&_[data-radix-scroll-area-viewport]]:!overflow-x-hidden">
1192
+ <div className="w-full min-w-0 py-2 pe-2">
1193
1193
  {/* Search results */}
1194
1194
  {filteredDocuments ? (
1195
1195
  <>
@@ -65,7 +65,6 @@ export function useComments(documentId: string | null) {
65
65
  }
66
66
  return Array.from(threadMap.values());
67
67
  },
68
- refetchInterval: 5000,
69
68
  },
70
69
  );
71
70
  }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-11
4
+ ---
5
+
6
+ Comments now update from live collaboration events without continuous background requests
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-12
4
+ ---
5
+
6
+ The left sidebar stays fixed horizontally while scrolling on desktop and mobile.
@@ -88,7 +88,7 @@ export function Header() {
88
88
  </div>
89
89
  <div className="flex items-center gap-2 shrink-0">
90
90
  {actions}
91
- <RunsTray onOpenThread={openRunThread} />
91
+ <RunsTray pollMs={0} onOpenThread={openRunThread} />
92
92
  <AgentToggleButton />
93
93
  </div>
94
94
  </header>
@@ -30,7 +30,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
30
30
  useDbSync({ queryClient });
31
31
  ```
32
32
 
33
- For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries for ordinary domain events — that caused a request storm in production. The exception is `source: "action"`: a successful mutating action is the framework-wide "agent changed app data" signal, so `useDbSync` also refreshes active React Query observers as a compatibility safety net for custom apps that have not yet moved every read to `useActionQuery` or source-versioned query keys.
33
+ For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries — that caused request storms in production. A successful mutating action refreshes active `useActionQuery` observers under the `["action"]` prefix. Browser actions carry a tab id so their originating tab ignores the sync echo while other tabs refresh. Legacy apps can opt into broader compatibility with `actionInvalidatePredicate`, but first-party apps should use action-backed or source-versioned query keys. Idle fallback polling runs once per minute; active agent work temporarily uses the faster cadence.
34
34
 
35
35
  3. **Templates fold per-source counters into their query keys.** This is the pattern that makes "agent writes show up without a manual refresh" reliable:
36
36
 
@@ -117,7 +117,7 @@ useQuery({
117
117
  | UI not updating after agent writes | Is `useDbSync` called with the correct `queryClient`? Does the affected query have an active observer? |
118
118
  | Poll endpoint not responding | Is `/_agent-native/poll` accessible? Is the server running? |
119
119
  | SSE not connecting | Is `/_agent-native/events` accessible and authenticated? Polling should still keep the UI fresh as fallback. |
120
- | High CPU / event storms | The agent is writing rapidly. Add `staleTime` to queries to debounce refetches. |
120
+ | High CPU / event storms | Use targeted source keys, settle bursty list counters, and avoid broad action invalidation. |
121
121
 
122
122
  ## Jitter Prevention
123
123
 
@@ -80,7 +80,7 @@ export function AppLayout({ children }: { children: React.ReactNode }) {
80
80
  }).catch(() => {});
81
81
  }, [location.pathname, isAnalytics, isSettings]);
82
82
 
83
- // Poll for navigate commands from the agent
83
+ // useDbSync invalidates this key when the agent writes a navigate command.
84
84
  const { data: navCommand } = useQuery({
85
85
  queryKey: ["navigate-command"],
86
86
  queryFn: async () => {
@@ -94,7 +94,6 @@ export function AppLayout({ children }: { children: React.ReactNode }) {
94
94
  return null;
95
95
  }
96
96
  },
97
- refetchInterval: 2000,
98
97
  });
99
98
 
100
99
  useEffect(() => {
@@ -169,9 +169,6 @@ export default function Root() {
169
169
  createAgentNativeQueryClient({
170
170
  defaultOptions: {
171
171
  queries: {
172
- // Macros UI refetches on focus to pick up meals logged in other
173
- // browser tabs or mobile, which don't always arrive via DB sync.
174
- refetchOnWindowFocus: true,
175
172
  // Flat retry: macros data errors are usually transient network
176
173
  // issues, not auth failures, so a flat count is sufficient.
177
174
  retry: 1,
@@ -30,7 +30,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
30
30
  useDbSync({ queryClient });
31
31
  ```
32
32
 
33
- For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries for ordinary domain events — that caused a request storm in production. The exception is `source: "action"`: a successful mutating action is the framework-wide "agent changed app data" signal, so `useDbSync` also refreshes active React Query observers as a compatibility safety net for custom apps that have not yet moved every read to `useActionQuery` or source-versioned query keys.
33
+ For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries — that caused request storms in production. A successful mutating action refreshes active `useActionQuery` observers under the `["action"]` prefix. Browser actions carry a tab id so their originating tab ignores the sync echo while other tabs refresh. Legacy apps can opt into broader compatibility with `actionInvalidatePredicate`, but first-party apps should use action-backed or source-versioned query keys. Idle fallback polling runs once per minute; active agent work temporarily uses the faster cadence.
34
34
 
35
35
  3. **Templates fold per-source counters into their query keys.** This is the pattern that makes "agent writes show up without a manual refresh" reliable:
36
36
 
@@ -117,7 +117,7 @@ useQuery({
117
117
  | UI not updating after agent writes | Is `useDbSync` called with the correct `queryClient`? Does the affected query have an active observer? |
118
118
  | Poll endpoint not responding | Is `/_agent-native/poll` accessible? Is the server running? |
119
119
  | SSE not connecting | Is `/_agent-native/events` accessible and authenticated? Polling should still keep the UI fresh as fallback. |
120
- | High CPU / event storms | The agent is writing rapidly. Add `staleTime` to queries to debounce refetches. |
120
+ | High CPU / event storms | Use targeted source keys, settle bursty list counters, and avoid broad action invalidation. |
121
121
 
122
122
  ## Jitter Prevention
123
123
 
@@ -139,6 +139,7 @@ export function useComposeState() {
139
139
  return merged;
140
140
  },
141
141
  staleTime: 1_000,
142
+ // request-storm-allow: one focus refresh reconciles bounded compose drafts across tabs.
142
143
  refetchOnWindowFocus: true,
143
144
  });
144
145
 
@@ -419,18 +419,7 @@ function DbSyncSetup() {
419
419
  const MAIL_TOASTER = <Toaster richColors position="bottom-left" />;
420
420
 
421
421
  export default function Root() {
422
- const [queryClient] = useState(() =>
423
- createAgentNativeQueryClient({
424
- defaultOptions: {
425
- queries: {
426
- // Mail's VisibilityRefresh handles the focus-based refresh with a
427
- // 60 s throttle, so we also want React Query's focus refetch to
428
- // fire for other query keys (labels, settings, etc.).
429
- refetchOnWindowFocus: true,
430
- },
431
- },
432
- }),
433
- );
422
+ const [queryClient] = useState(() => createAgentNativeQueryClient());
434
423
  return (
435
424
  <AppToolkitProvider>
436
425
  <AppProviders
@@ -30,7 +30,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
30
30
  useDbSync({ queryClient });
31
31
  ```
32
32
 
33
- For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries for ordinary domain events — that caused a request storm in production. The exception is `source: "action"`: a successful mutating action is the framework-wide "agent changed app data" signal, so `useDbSync` also refreshes active React Query observers as a compatibility safety net for custom apps that have not yet moved every read to `useActionQuery` or source-versioned query keys.
33
+ For each non-own event, `useDbSync` bumps a per-source counter (e.g. `dashboards`, `analyses`, `settings`, `action`) and invalidates a small fixed list of framework-internal prefixes (`["action"]`, `["app-state"]`, `["__set_url__"]`, etc.). It does **not** blanket-invalidate templates' own data queries — that caused request storms in production. A successful mutating action refreshes active `useActionQuery` observers under the `["action"]` prefix. Browser actions carry a tab id so their originating tab ignores the sync echo while other tabs refresh. Legacy apps can opt into broader compatibility with `actionInvalidatePredicate`, but first-party apps should use action-backed or source-versioned query keys. Idle fallback polling runs once per minute; active agent work temporarily uses the faster cadence.
34
34
 
35
35
  3. **Templates fold per-source counters into their query keys.** This is the pattern that makes "agent writes show up without a manual refresh" reliable:
36
36
 
@@ -117,7 +117,7 @@ useQuery({
117
117
  | UI not updating after agent writes | Is `useDbSync` called with the correct `queryClient`? Does the affected query have an active observer? |
118
118
  | Poll endpoint not responding | Is `/_agent-native/poll` accessible? Is the server running? |
119
119
  | SSE not connecting | Is `/_agent-native/events` accessible and authenticated? Polling should still keep the UI fresh as fallback. |
120
- | High CPU / event storms | The agent is writing rapidly. Add `staleTime` to queries to debounce refetches. |
120
+ | High CPU / event storms | Use targeted source keys, settle bursty list counters, and avoid broad action invalidation. |
121
121
 
122
122
  ## Jitter Prevention
123
123
 
@@ -36,9 +36,9 @@ The local-files contract:
36
36
  — encode multiline code as JSON string attributes such as `code={"const x =\n y"}`
37
37
  (a static template literal is accepted only when it has no `${...}`
38
38
  interpolation). `plan local check` is a quick OFFLINE lint (a subset of the
39
- renderer schema), so a green `check` does not guarantee the plan renders;
40
- `plan local verify` is the authoritative validation against the real renderer
41
- schema.
39
+ renderer schema), so a green `check` does not guarantee the plan renders.
40
+ `plan local verify` also stays on-device: it uses the offline lint unless it
41
+ can reach a Plan renderer on an explicit loopback `--app-url`.
42
42
  - **Write a local MDX folder.** Use `plans/<slug>/` to check the artifact into the
43
43
  repo, or a repo-ignored/temporary folder such as `.agent-native/plans/<slug>/`
44
44
  or `/tmp/agent-native-plans/<slug>/` when it should not be checked in. The
@@ -53,7 +53,10 @@ The local-files contract:
53
53
  (use `--kind plan` for plans, `--kind recap` for recaps). Report the local
54
54
  bridge URL from stdout or `<plan-dir>/.plan-url`; treat `.plan-url` as a local
55
55
  token file and do not commit it. The URL opens the hosted Plan UI but reads from
56
- the localhost bridge on this machine, so it is not shareable across machines. On
56
+ the localhost bridge on this machine, so it is not shareable across machines.
57
+ The token is carried in the URL fragment (which is not sent to the hosted
58
+ origin), and the local-plan route disables DOM autocapture and session replay
59
+ while retaining sanitized pageviews and error monitoring. On
57
60
  macOS `--open` prefers Chromium browsers; if Safari opens, switch to
58
61
  Chrome/Chromium because Safari can block the hosted HTTPS page from fetching the
59
62
  HTTP localhost bridge. If the Plan app itself is running locally with the same
@@ -63,14 +66,16 @@ The local-files contract:
63
66
  running local Plan app.
64
67
  - **Headless verify.** Run
65
68
  `npx @agent-native/core@latest plan local verify --dir <plan-dir> --kind <plan|recap>`.
66
- It starts the bridge, checks the private-network preflight and JSON payload, AND
67
- validates the content against the real renderer schema via the Plan app's
68
- `validate-local-plan-source` action. A non-`ok` result with
69
+ It starts the bridge and checks the private-network preflight and JSON payload
70
+ entirely on loopback. It never sends MDX or assets to a remote validation
71
+ action. When `--app-url` points to a loopback Plan app, verify also validates
72
+ against that local app's real renderer schema via `validate-local-plan-source`.
73
+ A non-`ok` result with
69
74
  `validation.valid: false` lists the renderer's exact schema-path issues (e.g.
70
75
  `blocks[1].data.tabs[0]...`); fix those before handing off. If `validation.ran`
71
- is `false`, the Plan app did not expose the validate endpoint (older/unreachable
72
- deploy) point `--app-url` at a current Plan app (e.g. a local
73
- `http://localhost:8096`) for the authoritative check. If the browser hangs on
76
+ is `false`, verify used the offline lint because the app URL was remote or the
77
+ local Plan app was unavailable. Run a local Plan app and pass
78
+ `--app-url http://localhost:8096` for the authoritative check. If the browser hangs on
74
79
  "Loading plan", fetch the `bridgeUrl` from the verify/serve JSON to read the
75
80
  concrete validation error.
76
81
  - **Never call hosted tools for that plan/recap.** Do not call
@@ -86,8 +91,8 @@ The local-files contract:
86
91
  attachment, and publish/export receipts are unavailable until the user
87
92
  explicitly opts into publishing.
88
93
 
89
- Local-files mode only prevents plan/recap content from reaching the Agent-Native
90
- Plan database. It does not by itself make the coding agent's language model local;
94
+ Local-files mode prevents plan/recap content from being uploaded to the
95
+ Agent-Native Plan server or database. It does not by itself make the coding agent's language model local;
91
96
  for that stronger boundary the host agent/model must also be local or otherwise
92
97
  approved by the user.
93
98