@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
@@ -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
 
@@ -13,8 +13,8 @@ import { parsePlanMdxFolder, planMdxFileSchema } from "../server/plan-mdx.js";
13
13
  *
14
14
  * It is intentionally a pure parse: it accepts the posted MDX folder, never
15
15
  * reads `schema.plans`, never touches the filesystem, and never writes to the
16
- * database. That keeps it safe to expose without auth so the offline-friendly
17
- * `plan local verify` CLI can call it against a local or hosted Plan app.
16
+ * database. The local-files CLI calls it only on an explicit loopback Plan app;
17
+ * it never posts private source to this action on a hosted deployment.
18
18
  */
19
19
 
20
20
  // Covers the CLI's 10 MiB raw asset cap (~13.3 MiB base64) plus MDX text, so
@@ -63,7 +63,7 @@ function toValidationIssues(error: unknown): ValidationIssue[] {
63
63
 
64
64
  export default defineAction({
65
65
  description:
66
- "Validate a local plan MDX folder against the live Plan renderer schema (parsePlanMdxFolder + planContentSchema). Returns { valid, issues } where issues carry the renderer's exact schema path (e.g. blocks[1].data.items[0].id). Use this to confirm a plan will render before handing it off it is the authoritative check behind `plan local verify`. Pure parse: no database, filesystem, or schema.plans access.",
66
+ "Validate a plan MDX folder against this Plan app's renderer schema (parsePlanMdxFolder + planContentSchema). Returns { valid, issues } where issues carry the renderer's exact schema path (e.g. blocks[1].data.items[0].id). The local-files CLI calls this only on loopback Plan apps so private source stays on-device. Pure parse: no database, filesystem, or schema.plans access.",
67
67
  schema: z.object({
68
68
  mdx: planMdxFileSchema.describe(
69
69
  "The plan MDX folder: plan.mdx plus optional canvas.mdx, prototype.mdx, .plan-state.json, and assets/.",
@@ -81,7 +81,7 @@ export default defineAction({
81
81
  requiresAuth: false,
82
82
  title: "Validate Local Plan Source",
83
83
  description:
84
- "Validate a local plan MDX folder against the real renderer schema without touching the database.",
84
+ "Validate a plan MDX folder against this app's renderer schema without touching the database.",
85
85
  },
86
86
  run: async (args) => {
87
87
  let totalBytes = 0;
@@ -62,6 +62,7 @@ import {
62
62
  } from "@/components/ui/tooltip";
63
63
  import { usePlans } from "@/hooks/use-plans";
64
64
  import { APP_TITLE } from "@/lib/app-config";
65
+ import { planReturnPathFromLocation } from "@/lib/plan-local-bridge";
65
66
  import { cn } from "@/lib/utils";
66
67
 
67
68
  const PLAN_CHAT_STORAGE_KEY = "plans";
@@ -651,7 +652,7 @@ export function Sidebar({
651
652
  const location = useLocation();
652
653
  const { session, isLoading: sessionLoading } = useSession();
653
654
  const t = useT();
654
- const returnPath = `${location.pathname}${location.search}${location.hash}`;
655
+ const returnPath = planReturnPathFromLocation(location);
655
656
  const ToggleIcon = collapsed
656
657
  ? IconLayoutSidebarLeftExpand
657
658
  : IconLayoutSidebarLeftCollapse;
@@ -55,7 +55,10 @@ export function useNavigationState() {
55
55
  }).catch(() => {});
56
56
  }, [location.pathname, location.search]);
57
57
 
58
- // Listen for navigate commands from agent
58
+ // Listen for one-shot navigate commands from the agent. useDbSync
59
+ // invalidates this exact key when the shared SSE/poll transport receives an
60
+ // app-state:navigate event, so this stays idle between real commands instead
61
+ // of charging the host for a request every two seconds.
59
62
  const { data: navCommand } = useQuery({
60
63
  queryKey: ["navigate-command"],
61
64
  queryFn: async () => {
@@ -70,7 +73,7 @@ export function useNavigationState() {
70
73
  }
71
74
  return null;
72
75
  },
73
- refetchInterval: 2_000,
76
+ retry: false,
74
77
  structuralSharing: false,
75
78
  });
76
79
 
@@ -17,7 +17,6 @@ import type {
17
17
  PlanVersionListResponse,
18
18
  } from "@shared/types";
19
19
  import { useQueryClient, type UseQueryOptions } from "@tanstack/react-query";
20
- import type { RefObject } from "react";
21
20
  import { toast } from "sonner";
22
21
 
23
22
  import type { PlanMdxFolder } from "@/lib/desktop-plan-files";
@@ -337,23 +336,17 @@ export function localPlanBundleQueryKey(slug: string, path?: string | null) {
337
336
  ] as const;
338
337
  }
339
338
 
340
- export function usePlan(
341
- id?: string,
342
- pausePollRef?: RefObject<boolean> | { current: boolean },
343
- ) {
339
+ export function usePlan(id?: string) {
344
340
  return useActionQuery<PlanBundle & { html?: string }>(
345
341
  "get-visual-plan",
346
342
  planBundleQueryParams(id ?? ""),
347
343
  {
348
344
  enabled: !!id,
349
- // Pause the 3-second poll while a comment mutation is in-flight so
350
- // an optimistic comment inserted into the cache isn't evicted before
351
- // the server write commits (Issue 4a).
352
- refetchInterval: (query: { state: { status: string } }) => {
353
- if (query.state.status === "error") return false;
354
- if (pausePollRef?.current) return false;
355
- return 3_000;
356
- },
345
+ // Mutating actions and collaboration writes already arrive through the
346
+ // shared useDbSync SSE/poll transport, which invalidates active action
347
+ // reads. Keep the last bundle visible during that targeted refresh and
348
+ // avoid repeatedly downloading the full plan while nothing changed.
349
+ placeholderData: (previous) => previous,
357
350
  },
358
351
  );
359
352
  }
@@ -67,6 +67,47 @@ export class LocalPlanBridgePermissionError extends Error {
67
67
  }
68
68
  }
69
69
 
70
+ type LocalPlanBridgeSessionStorage = Pick<Storage, "getItem" | "setItem">;
71
+
72
+ function browserSessionStorage(): LocalPlanBridgeSessionStorage | null {
73
+ if (typeof window === "undefined") return null;
74
+ try {
75
+ return window.sessionStorage;
76
+ } catch {
77
+ return null;
78
+ }
79
+ }
80
+
81
+ export function localPlanBridgeUrlFromLocation(
82
+ hash: string,
83
+ slug: string,
84
+ storage: LocalPlanBridgeSessionStorage | null = browserSessionStorage(),
85
+ ): string | null {
86
+ const hashParams = hash.startsWith("#bridge=")
87
+ ? new URLSearchParams(hash.slice(1))
88
+ : null;
89
+ const bridgeUrl = hashParams?.get("bridge") ?? null;
90
+ const storageKey = `agent-native.local-plan-bridge.${slug}`;
91
+ try {
92
+ if (bridgeUrl) {
93
+ storage?.setItem(storageKey, bridgeUrl);
94
+ return bridgeUrl;
95
+ }
96
+ return storage?.getItem(storageKey) ?? null;
97
+ } catch {
98
+ return bridgeUrl;
99
+ }
100
+ }
101
+
102
+ export function planReturnPathFromLocation(location: {
103
+ pathname: string;
104
+ search: string;
105
+ hash: string;
106
+ }): string {
107
+ const safeHash = location.hash.startsWith("#bridge=") ? "" : location.hash;
108
+ return `${location.pathname}${location.search}${safeHash}`;
109
+ }
110
+
70
111
  export async function localNetworkAccessPermissionState(): Promise<
71
112
  Exclude<LocalNetworkAccessPermissionState, "checking">
72
113
  > {
@@ -0,0 +1,3 @@
1
+ export function shouldCapturePlanContent(pathname: string): boolean {
2
+ return !(pathname === "/local-plans" || pathname.startsWith("/local-plans/"));
3
+ }
@@ -273,11 +273,13 @@ import { planDocumentTitle } from "@/lib/plan-document-title";
273
273
  import {
274
274
  fetchLocalPlanBridgeBundle,
275
275
  localNetworkAccessPermissionState,
276
+ localPlanBridgeUrlFromLocation,
276
277
  localPlanBridgeQueryKey,
277
278
  localPlanBridgeRetryDelay,
278
279
  localPlanRoutePath,
279
280
  localPlanRouteUrl,
280
281
  mergeLocalBridgeComments,
282
+ planReturnPathFromLocation,
281
283
  shouldRetryLocalPlanBridgeBundle,
282
284
  shouldShowLocalPlanLoadError,
283
285
  shouldShowPlanLoadError,
@@ -2018,16 +2020,16 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
2018
2020
  // Ref that signals the 3-second poll to pause while a comment mutation is
2019
2021
  // in-flight. Prevents poll-driven cache replacement from evicting optimistic
2020
2022
  // comments before the server write commits (Issue 4a).
2021
- const commentMutationPendingRef = useRef(false);
2022
2023
  const { session, isLoading: sessionLoading } = useSession();
2023
2024
  const localPlanMode = Boolean(localPlanSlug);
2024
2025
  const routeSearchParams = useMemo(
2025
2026
  () => new URLSearchParams(location.search),
2026
2027
  [location.search],
2027
2028
  );
2028
- const localPlanBridgeUrl = localPlanMode
2029
- ? routeSearchParams.get("bridge")
2030
- : null;
2029
+ const localPlanBridgeUrl =
2030
+ localPlanMode && localPlanSlug
2031
+ ? localPlanBridgeUrlFromLocation(location.hash, localPlanSlug)
2032
+ : null;
2031
2033
  const localPlanRepoPath = localPlanMode
2032
2034
  ? routeSearchParams.get("path")
2033
2035
  : null;
@@ -2138,8 +2140,7 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
2138
2140
  // Redirect to sign-in, returning to wherever the guest currently is.
2139
2141
  const openSignIn = useCallback((returnOverride?: string) => {
2140
2142
  const returnPath =
2141
- returnOverride ??
2142
- window.location.pathname + window.location.search + window.location.hash;
2143
+ returnOverride ?? planReturnPathFromLocation(window.location);
2143
2144
  window.location.href = `${agentNativePath(
2144
2145
  "/_agent-native/sign-in",
2145
2146
  )}?return=${encodeURIComponent(returnPath)}`;
@@ -2217,10 +2218,7 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
2217
2218
  const immersiveReader = Boolean(
2218
2219
  selectedId && (planFullscreen || prototypeOnly),
2219
2220
  );
2220
- const planQuery = usePlan(
2221
- localPlanMode ? undefined : selectedId,
2222
- commentMutationPendingRef,
2223
- );
2221
+ const planQuery = usePlan(localPlanMode ? undefined : selectedId);
2224
2222
  const bundle = localPlanMode ? localPlanData : planQuery.data;
2225
2223
  const localPlanBundle =
2226
2224
  localPlanMode && bundle && "localOnly" in bundle
@@ -2296,8 +2294,7 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
2296
2294
  }
2297
2295
  }, [accessRequestSentPlanId, selectedId]);
2298
2296
  const startGoogleSignIn = useCallback(async () => {
2299
- const returnPath =
2300
- window.location.pathname + window.location.search + window.location.hash;
2297
+ const returnPath = planReturnPathFromLocation(window.location);
2301
2298
  try {
2302
2299
  const res = await fetch(
2303
2300
  `${agentNativePath("/_agent-native/google/auth-url")}?return=${encodeURIComponent(returnPath)}`,
@@ -4550,8 +4547,7 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4550
4547
  };
4551
4548
  clearPendingDocumentRestore();
4552
4549
  pendingDocumentRestoreRef.current = documentStateRef.current;
4553
- commentMutationPendingRef.current = true;
4554
- // Await the cancel so an in-flight 3s poll can't resolve *after* our
4550
+ // Await the cancel so an in-flight sync refresh can't resolve *after* our
4555
4551
  // optimistic write and revert it (the "comment lagged / didn't stick"
4556
4552
  // symptom). cancelQueries reverts outstanding fetches before we patch.
4557
4553
  await queryClient.cancelQueries({ queryKey: selectedPlanQueryKey });
@@ -4588,9 +4584,6 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4588
4584
  setInlineCommentPosition(
4589
4585
  getPositionFromAnchor(anchor) ?? capturedPosition,
4590
4586
  );
4591
- })
4592
- .finally(() => {
4593
- commentMutationPendingRef.current = false;
4594
4587
  });
4595
4588
  };
4596
4589
 
@@ -4606,7 +4599,6 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4606
4599
  annotation.anchor.resolutionTarget,
4607
4600
  ),
4608
4601
  };
4609
- commentMutationPendingRef.current = true;
4610
4602
  void writeComments(
4611
4603
  [
4612
4604
  {
@@ -4629,9 +4621,6 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4629
4621
  })
4630
4622
  .catch(() => {
4631
4623
  // The mutation hook surfaces the failure toast; just clear pending.
4632
- })
4633
- .finally(() => {
4634
- commentMutationPendingRef.current = false;
4635
4624
  });
4636
4625
  };
4637
4626
 
@@ -4669,8 +4658,7 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4669
4658
  createdAt: now,
4670
4659
  updatedAt: now,
4671
4660
  };
4672
- commentMutationPendingRef.current = true;
4673
- // Await the cancel so an in-flight 3s poll can't resolve *after* our
4661
+ // Await the cancel so an in-flight sync refresh can't resolve *after* our
4674
4662
  // optimistic write and revert it (the "comment lagged / didn't stick"
4675
4663
  // symptom). cancelQueries reverts outstanding fetches before we patch.
4676
4664
  await queryClient.cancelQueries({ queryKey: selectedPlanQueryKey });
@@ -4709,8 +4697,6 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4709
4697
  current ? removePlanCommentFromBundle(current, replyId) : current,
4710
4698
  );
4711
4699
  throw new Error("Could not send reply. Try again.");
4712
- } finally {
4713
- commentMutationPendingRef.current = false;
4714
4700
  }
4715
4701
  };
4716
4702
 
@@ -4729,8 +4715,7 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4729
4715
  // popover update without waiting for the server round-trip (Issue 3).
4730
4716
  const prevBundle =
4731
4717
  queryClient.getQueryData<PlanBundleWithHtml>(selectedPlanQueryKey);
4732
- commentMutationPendingRef.current = true;
4733
- // Await the cancel so an in-flight 3s poll can't resolve *after* our
4718
+ // Await the cancel so an in-flight sync refresh can't resolve *after* our
4734
4719
  // optimistic write and revert it (the "comment lagged / didn't stick"
4735
4720
  // symptom). cancelQueries reverts outstanding fetches before we patch.
4736
4721
  await queryClient.cancelQueries({ queryKey: selectedPlanQueryKey });
@@ -4777,9 +4762,6 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4777
4762
  if (prevBundle !== undefined) {
4778
4763
  queryClient.setQueryData(selectedPlanQueryKey, prevBundle);
4779
4764
  }
4780
- })
4781
- .finally(() => {
4782
- commentMutationPendingRef.current = false;
4783
4765
  });
4784
4766
  };
4785
4767
 
@@ -4802,8 +4784,7 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4802
4784
  const prevBundle =
4803
4785
  queryClient.getQueryData<PlanBundleWithHtml>(selectedPlanQueryKey);
4804
4786
  const commentId = request.commentId;
4805
- commentMutationPendingRef.current = true;
4806
- // Await the cancel so an in-flight 3s poll can't resolve *after* our
4787
+ // Await the cancel so an in-flight sync refresh can't resolve *after* our
4807
4788
  // optimistic write and revert it (the "comment lagged / didn't stick"
4808
4789
  // symptom). cancelQueries reverts outstanding fetches before we patch.
4809
4790
  await queryClient.cancelQueries({ queryKey: selectedPlanQueryKey });
@@ -4826,8 +4807,6 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
4826
4807
  queryClient.setQueryData(selectedPlanQueryKey, prevBundle);
4827
4808
  }
4828
4809
  setDeleteCommentRequest(request);
4829
- } finally {
4830
- commentMutationPendingRef.current = false;
4831
4810
  }
4832
4811
  };
4833
4812
 
@@ -6848,8 +6827,7 @@ function PlanLoadError({
6848
6827
  ? t("plansPage.loadError.orgTitle", { orgName })
6849
6828
  : null;
6850
6829
 
6851
- const returnPath = () =>
6852
- window.location.pathname + window.location.search + window.location.hash;
6830
+ const returnPath = () => planReturnPathFromLocation(window.location);
6853
6831
 
6854
6832
  const readAuthError = async (res: Response, fallback: string) => {
6855
6833
  const data = (await res.json().catch(() => null)) as {
@@ -20,7 +20,7 @@ import {
20
20
  } from "@tabler/icons-react";
21
21
  import { useQueryClient } from "@tanstack/react-query";
22
22
  import { useTheme } from "next-themes";
23
- import { useCallback, useState } from "react";
23
+ import { useCallback, useEffect, useState } from "react";
24
24
  import {
25
25
  Links,
26
26
  Meta,
@@ -44,13 +44,17 @@ import { useNavigationState } from "@/hooks/use-navigation-state";
44
44
  // their diagram/wireframe/api-spec blocks inline in the agent chat.
45
45
  import "@/lib/register-chat-renderers";
46
46
  import { APP_TITLE } from "@/lib/app-config";
47
+ import { shouldCapturePlanContent } from "@/lib/plan-tracking";
47
48
  import { TAB_ID } from "@/lib/tab-id";
48
49
 
49
50
  import changelog from "../CHANGELOG.md?raw";
50
51
  import { i18nCatalog } from "./i18n";
51
52
 
52
53
  import stylesheet from "./global.css?url";
54
+ // Keep standard pageviews, explicit analytics, and Sentry on local-plan routes,
55
+ // but disable DOM/session capture so rendered plan contents stay on-device.
53
56
  configureTracking({
57
+ contentCaptureForPath: shouldCapturePlanContent,
54
58
  getDefaultProps: (_name, properties) => ({
55
59
  ...properties,
56
60
  app: "plan",
@@ -221,6 +225,7 @@ export default function Root() {
221
225
  location.pathname.startsWith("/recaps/") ||
222
226
  location.pathname === "/local-plans" ||
223
227
  location.pathname.startsWith("/local-plans/");
228
+ const localPlanPrivacyRoute = !shouldCapturePlanContent(location.pathname);
224
229
  return (
225
230
  // Pass the plan-specific styled Toaster via `toaster` so only one sonner
226
231
  // instance renders (avoids the duplicate that would appear if AppProviders'
@@ -232,8 +237,13 @@ export default function Root() {
232
237
  toaster={<Toaster richColors position="bottom-left" />}
233
238
  i18n={{ catalog: i18nCatalog }}
234
239
  >
235
- <DbSyncSetup />
236
- <AppContent />
240
+ <div
241
+ data-an-mask={localPlanPrivacyRoute ? "" : undefined}
242
+ style={{ display: "contents" }}
243
+ >
244
+ <DbSyncSetup />
245
+ <AppContent />
246
+ </div>
237
247
  </AppProviders>
238
248
  </AppToolkitProvider>
239
249
  );
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-11
4
+ ---
5
+
6
+ Plan pages stay current while making far fewer background requests when nothing has changed.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: security
3
+ date: 2026-07-12
4
+ ---
5
+
6
+ Local plan source now stays on your device during verification and is excluded from content autocapture and session replay.
@@ -336,7 +336,10 @@ function ThreadCard({
336
336
  <TooltipTrigger asChild>
337
337
  <button
338
338
  onClick={() =>
339
- resolveComment.mutate({ id: rootComment.id })
339
+ resolveComment.mutate({
340
+ id: rootComment.id,
341
+ resolved: true,
342
+ })
340
343
  }
341
344
  className="p-0.5 rounded text-muted-foreground hover:text-green-400"
342
345
  >
@@ -1023,7 +1023,7 @@ graph TD
1023
1023
  </DropdownMenuContent>
1024
1024
  </DropdownMenu>
1025
1025
 
1026
- <RunsTray />
1026
+ <RunsTray pollMs={0} />
1027
1027
  <AgentToggleButton />
1028
1028
  </div>
1029
1029
  );
@@ -66,7 +66,7 @@ export function Header() {
66
66
  </div>
67
67
  <div className="flex items-center gap-2 shrink-0">
68
68
  {actions}
69
- <RunsTray />
69
+ <RunsTray pollMs={0} />
70
70
  <AgentToggleButton />
71
71
  </div>
72
72
  </header>
@@ -1452,6 +1452,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
1452
1452
  es.close();
1453
1453
  es = null;
1454
1454
  }
1455
+ // request-storm-allow: one deck-scoped SSE with backoff and unmount cleanup carries payloads sync events omit.
1455
1456
  const next = new EventSource(`${appBasePath()}/api/decks/events`);
1456
1457
  es = next;
1457
1458
  next.onmessage = handleMessage;
@@ -1,10 +1,8 @@
1
1
  import {
2
- appBasePath,
3
2
  emailToColor,
4
3
  useActionMutation,
5
4
  useActionQuery,
6
5
  } from "@agent-native/core/client";
7
- import { useMutation, useQueryClient } from "@tanstack/react-query";
8
6
 
9
7
  export interface SlideComment {
10
8
  id: string;
@@ -50,12 +48,6 @@ function groupIntoThreads(comments: SlideComment[]): CommentThread[] {
50
48
  return Array.from(map.values());
51
49
  }
52
50
 
53
- async function fetchJson<T>(url: string, init?: RequestInit): Promise<T> {
54
- const res = await fetch(url, init);
55
- if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
56
- return res.json();
57
- }
58
-
59
51
  export function useSlideComments(
60
52
  deckId: string | null,
61
53
  slideId: string | null,
@@ -71,7 +63,6 @@ export function useSlideComments(
71
63
  const comments: SlideComment[] = Array.isArray(raw) ? raw : [];
72
64
  return groupIntoThreads(comments);
73
65
  },
74
- refetchInterval: 3000,
75
66
  },
76
67
  );
77
68
  }
@@ -81,31 +72,16 @@ export function useCreateSlideComment() {
81
72
  }
82
73
 
83
74
  export function useResolveSlideComment() {
84
- const qc = useQueryClient();
85
- return useMutation({
86
- mutationFn: ({ id }: { id: string }) =>
87
- fetchJson<{ ok: boolean }>(`${appBasePath()}/api/comments/${id}`, {
88
- method: "PATCH",
89
- headers: { "Content-Type": "application/json" },
90
- body: JSON.stringify({ resolved: true }),
91
- }),
92
- onSuccess: () => {
93
- qc.invalidateQueries({ queryKey: ["action"] });
94
- },
95
- });
75
+ return useActionMutation<
76
+ { ok: boolean; resolved?: boolean },
77
+ { id: string; resolved?: boolean }
78
+ >("update-slide-comment");
96
79
  }
97
80
 
98
81
  export function useDeleteSlideComment() {
99
- const qc = useQueryClient();
100
- return useMutation({
101
- mutationFn: ({ id }: { id: string }) =>
102
- fetchJson<{ ok: boolean }>(`${appBasePath()}/api/comments/${id}`, {
103
- method: "DELETE",
104
- }),
105
- onSuccess: () => {
106
- qc.invalidateQueries({ queryKey: ["action"] });
107
- },
108
- });
82
+ return useActionMutation<{ ok: boolean }, { id: string }>(
83
+ "delete-slide-comment",
84
+ );
109
85
  }
110
86
 
111
87
  /** Derive a display color for an author email */
@@ -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
@@ -4,6 +4,7 @@ export interface ActionChangeTarget {
4
4
  actionName?: string;
5
5
  owner?: string;
6
6
  orgId?: string;
7
+ requestSource?: string;
7
8
  }
8
9
  export declare function actionChangeMarkerSession(target: ActionChangeTarget): string | null;
9
10
  export declare function actionChangeMarkerValue(target: ActionChangeTarget): Record<string, string>;
@@ -1 +1 @@
1
- {"version":3,"file":"action-change-marker.d.ts","sourceRoot":"","sources":["../src/action-change-marker.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,sBAAsB,CAAC;AAC5D,eAAO,MAAM,+BAA+B,aAAa,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,kBAAkB,GACzB,MAAM,GAAG,IAAI,CAIf;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,kBAAkB,GACzB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,OAAO,GACb,kBAAkB,GAAG,IAAI,CAmC3B"}
1
+ {"version":3,"file":"action-change-marker.d.ts","sourceRoot":"","sources":["../src/action-change-marker.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,sBAAsB,CAAC;AAC5D,eAAO,MAAM,+BAA+B,aAAa,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,kBAAkB,GACzB,MAAM,GAAG,IAAI,CAIf;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,kBAAkB,GACzB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,OAAO,GACb,kBAAkB,GAAG,IAAI,CAwC3B"}
@@ -13,6 +13,7 @@ export function actionChangeMarkerValue(target) {
13
13
  ...(target.actionName ? { actionName: target.actionName } : {}),
14
14
  ...(target.owner ? { owner: target.owner } : {}),
15
15
  ...(target.orgId ? { orgId: target.orgId } : {}),
16
+ ...(target.requestSource ? { requestSource: target.requestSource } : {}),
16
17
  };
17
18
  }
18
19
  export function parseActionChangeMarker(sessionId, value) {
@@ -28,12 +29,17 @@ export function parseActionChangeMarker(sessionId, value) {
28
29
  let actionName;
29
30
  let owner;
30
31
  let orgId;
32
+ let requestSource;
31
33
  if (parsed && typeof parsed === "object") {
32
34
  const record = parsed;
33
35
  actionName =
34
36
  typeof record.actionName === "string" ? record.actionName : undefined;
35
37
  owner = typeof record.owner === "string" ? record.owner : undefined;
36
38
  orgId = typeof record.orgId === "string" ? record.orgId : undefined;
39
+ requestSource =
40
+ typeof record.requestSource === "string"
41
+ ? record.requestSource
42
+ : undefined;
37
43
  }
38
44
  if (!owner && !orgId && typeof sessionId === "string" && sessionId) {
39
45
  if (sessionId.startsWith(ACTION_CHANGE_MARKER_ORG_PREFIX)) {
@@ -47,6 +53,6 @@ export function parseActionChangeMarker(sessionId, value) {
47
53
  }
48
54
  if (!actionName && !owner && !orgId)
49
55
  return null;
50
- return { actionName, owner, orgId };
56
+ return { actionName, owner, orgId, requestSource };
51
57
  }
52
58
  //# sourceMappingURL=action-change-marker.js.map