@agent-native/core 0.69.0 → 0.70.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/README.md +15 -15
  2. package/corpus/README.md +2 -2
  3. package/corpus/core/CHANGELOG.md +109 -0
  4. package/corpus/core/docs/design/durable-agent-runs.md +217 -0
  5. package/corpus/core/package.json +1 -1
  6. package/corpus/core/src/action.ts +89 -0
  7. package/corpus/core/src/agent/model-config.ts +0 -2
  8. package/corpus/core/src/agent/run-loop-with-resume.ts +48 -0
  9. package/corpus/core/src/changelog/parse.ts +245 -0
  10. package/corpus/core/src/cli/changelog.ts +199 -0
  11. package/corpus/core/src/cli/index.ts +19 -0
  12. package/corpus/core/src/cli/recap.ts +24 -1
  13. package/corpus/core/src/cli/skills.ts +74 -47
  14. package/corpus/core/src/client/AgentPanel.tsx +5 -3
  15. package/corpus/core/src/client/AssistantChat.tsx +8 -0
  16. package/corpus/core/src/client/CommandMenu.tsx +183 -75
  17. package/corpus/core/src/client/agent-chat-adapter.ts +44 -7
  18. package/corpus/core/src/client/analytics.ts +181 -0
  19. package/corpus/core/src/client/changelog/Changelog.tsx +321 -0
  20. package/corpus/core/src/client/client-surface.ts +41 -0
  21. package/corpus/core/src/client/composer/TiptapComposer.tsx +123 -12
  22. package/corpus/core/src/client/feedback-context.ts +4 -0
  23. package/corpus/core/src/client/index.ts +12 -0
  24. package/corpus/core/src/client/mcp-apps/McpAppRenderer.tsx +54 -0
  25. package/corpus/core/src/client/settings/useBuilderStatus.ts +82 -20
  26. package/corpus/core/src/client/sse-event-processor.ts +7 -1
  27. package/corpus/core/src/mcp/build-server.ts +57 -1
  28. package/corpus/core/src/mcp/embed-app.ts +197 -7
  29. package/corpus/core/src/mcp/oauth-route.ts +109 -13
  30. package/corpus/core/src/server/attribution.ts +211 -0
  31. package/corpus/core/src/server/auth.ts +6 -0
  32. package/corpus/core/src/server/better-auth-instance.ts +49 -5
  33. package/corpus/core/src/server/builder-browser.ts +27 -1
  34. package/corpus/core/src/server/core-routes-plugin.ts +136 -0
  35. package/corpus/core/src/server/google-oauth.ts +19 -6
  36. package/corpus/core/src/server/onboarding-html.ts +35 -0
  37. package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
  38. package/corpus/core/src/styles/agent-conversation.css +21 -0
  39. package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
  40. package/corpus/core/src/templates/workspace-core/.agents/skills/reliable-mutations/SKILL.md +72 -0
  41. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
  42. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +22 -0
  43. package/corpus/templates/analytics/AGENTS.md +8 -1
  44. package/corpus/templates/analytics/CHANGELOG.md +10 -0
  45. package/corpus/templates/analytics/actions/install-dashboard-template.ts +99 -4
  46. package/corpus/templates/analytics/actions/open-traffic-dashboard.ts +1 -1
  47. package/corpus/templates/analytics/actions/update-dashboard.ts +39 -8
  48. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +30 -3
  49. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +180 -144
  50. package/corpus/templates/analytics/app/components/layout/Header.tsx +2 -3
  51. package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -5
  52. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +221 -215
  53. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +6 -6
  54. package/corpus/templates/analytics/app/lib/demo-dashboard-path.ts +1 -1
  55. package/corpus/templates/analytics/app/lib/last-opened.ts +2 -1
  56. package/corpus/templates/analytics/app/pages/Settings.tsx +4 -0
  57. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -3
  58. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +2 -2
  59. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +32 -2
  60. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +101 -99
  61. package/corpus/templates/analytics/app/pages/overview/OverviewPage.tsx +1 -1
  62. package/corpus/templates/analytics/app/routes/adhoc.$id.tsx +18 -5
  63. package/corpus/templates/analytics/app/routes/catalog.tsx +1 -1
  64. package/corpus/templates/analytics/app/routes/dashboards.$id.tsx +9 -0
  65. package/corpus/templates/analytics/app/routes/traffic.tsx +1 -1
  66. package/corpus/templates/analytics/changelog/2026-06-23-long-dashboard-and-analysis-names-in-the-sidebar-now-truncat.md +6 -0
  67. package/corpus/templates/analytics/changelog/2026-06-23-open-any-dashboard-chart-full-screen-in-a-modal-from-the-pan.md +6 -0
  68. package/corpus/templates/analytics/changelog/2026-06-23-the-dashboards-and-analyses-sidebar-settings-buttons-now-sta.md +6 -0
  69. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +145 -0
  70. package/corpus/templates/analytics/server/db/index.ts +1 -1
  71. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +9 -2
  72. package/corpus/templates/analytics/server/lib/demo-dashboards.ts +1 -1
  73. package/corpus/templates/analytics/server/plugins/agent-chat.ts +2 -2
  74. package/corpus/templates/analytics/server/plugins/core-routes.ts +6 -6
  75. package/corpus/templates/assets/CHANGELOG.md +10 -0
  76. package/corpus/templates/assets/actions/generate-image.ts +24 -0
  77. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +2 -2
  78. package/corpus/templates/assets/app/global.css +17 -1
  79. package/corpus/templates/assets/app/root.tsx +7 -1
  80. package/corpus/templates/assets/app/routes/_index.tsx +94 -14
  81. package/corpus/templates/assets/app/routes/settings.tsx +6 -0
  82. package/corpus/templates/assets/changelog/2026-06-23-chat-dates-in-the-sidebar-no-longer-wrap-onto-two-lines.md +6 -0
  83. package/corpus/templates/assets/changelog/2026-06-23-clicking-image-video-or-refine-on-the-start-screen-now-drops.md +6 -0
  84. package/corpus/templates/assets/changelog/2026-06-23-pick-your-image-generation-model-right-from-the-chat-model-m.md +6 -0
  85. package/corpus/templates/brain/CHANGELOG.md +10 -0
  86. package/corpus/templates/brain/app/root.tsx +7 -1
  87. package/corpus/templates/brain/app/routes/settings.tsx +8 -1
  88. package/corpus/templates/calendar/CHANGELOG.md +10 -0
  89. package/corpus/templates/calendar/app/pages/Settings.tsx +4 -0
  90. package/corpus/templates/calendar/app/root.tsx +7 -1
  91. package/corpus/templates/chat/CHANGELOG.md +10 -0
  92. package/corpus/templates/chat/app/root.tsx +7 -1
  93. package/corpus/templates/clips/CHANGELOG.md +10 -0
  94. package/corpus/templates/clips/app/components/library/library-grid.tsx +1 -20
  95. package/corpus/templates/clips/app/components/player/share-dialog.tsx +33 -7
  96. package/corpus/templates/clips/app/components/player/sign-in-prompt-dialog.tsx +8 -0
  97. package/corpus/templates/clips/app/components/player/video-player.tsx +150 -20
  98. package/corpus/templates/clips/app/components/recorder/countdown-overlay.tsx +72 -48
  99. package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +7 -11
  100. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +31 -0
  101. package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +71 -0
  102. package/corpus/templates/clips/app/lib/countdown-audio-cue.ts +35 -17
  103. package/corpus/templates/clips/app/root.tsx +7 -1
  104. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +15 -1
  105. package/corpus/templates/clips/app/routes/record.tsx +78 -5
  106. package/corpus/templates/clips/app/routes/share.$shareId.tsx +86 -5
  107. package/corpus/templates/clips/changelog/2026-06-23-clips-shared-in-slack-no-longer-show-a-could-not-start-playb.md +6 -0
  108. package/corpus/templates/clips/changelog/2026-06-23-made-the-play-button-on-shared-and-embedded-clips-scale-with.md +6 -0
  109. package/corpus/templates/clips/changelog/2026-06-23-public-clip-share-links-now-show-whether-they-ll-play-inline.md +6 -0
  110. package/corpus/templates/clips/changelog/2026-06-23-removed-select-button-from-library-hover-a-clip-to-select-it.md +6 -0
  111. package/corpus/templates/clips/changelog/2026-06-23-screen-camera-recordings-now-keep-the-presenter-s-face-in-th.md +6 -0
  112. package/corpus/templates/clips/changelog/2026-06-23-shared-video-links-now-play-for-anyone-without-signing-in.md +6 -0
  113. package/corpus/templates/clips/changelog/2026-06-23-skip-or-cancel-the-recording-countdown-with-buttons-beside-t.md +6 -0
  114. package/corpus/templates/clips/changelog/2026-06-23-the-desktop-camera-bubble-now-looks-sharp-the-instant-it-ope.md +6 -0
  115. package/corpus/templates/clips/changelog/2026-06-23-the-desktop-recording-widget-now-grows-downward-only-when-yo.md +6 -0
  116. package/corpus/templates/clips/changelog/2026-06-23-the-recording-start-sound-is-now-a-softer-more-modern-chime.md +6 -0
  117. package/corpus/templates/clips/chrome-extension/public/manifest.json +17 -8
  118. package/corpus/templates/clips/chrome-extension/src/background.ts +769 -180
  119. package/corpus/templates/clips/chrome-extension/src/content-script.ts +177 -0
  120. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +466 -329
  121. package/corpus/templates/clips/chrome-extension/src/overlay.css +377 -0
  122. package/corpus/templates/clips/chrome-extension/src/overlay.html +12 -0
  123. package/corpus/templates/clips/chrome-extension/src/overlay.ts +330 -0
  124. package/corpus/templates/clips/chrome-extension/src/permission.html +227 -0
  125. package/corpus/templates/clips/chrome-extension/src/permission.ts +105 -0
  126. package/corpus/templates/clips/chrome-extension/src/popup.html +3 -0
  127. package/corpus/templates/clips/chrome-extension/src/popup.ts +50 -2
  128. package/corpus/templates/clips/chrome-extension/src/styles.css +50 -0
  129. package/corpus/templates/clips/chrome-extension/vite.config.ts +3 -0
  130. package/corpus/templates/clips/desktop/src/lib/audio-cue.ts +41 -24
  131. package/corpus/templates/clips/desktop/src/lib/bubble-webrtc.ts +119 -2
  132. package/corpus/templates/clips/desktop/src/lib/recorder.ts +20 -0
  133. package/corpus/templates/clips/desktop/src/main.tsx +3 -0
  134. package/corpus/templates/clips/desktop/src/overlays/countdown.tsx +21 -2
  135. package/corpus/templates/clips/desktop/src/overlays/region-record-border.tsx +76 -0
  136. package/corpus/templates/clips/desktop/src/styles.css +119 -2
  137. package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +2 -1
  138. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +140 -1
  139. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
  140. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +4 -1
  141. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +85 -6
  142. package/corpus/templates/clips/shared/share-attribution.ts +79 -0
  143. package/corpus/templates/content/AGENTS.md +20 -3
  144. package/corpus/templates/content/CHANGELOG.md +10 -0
  145. package/corpus/templates/content/actions/_database-utils.ts +15 -0
  146. package/corpus/templates/content/actions/_property-utils.ts +371 -4
  147. package/corpus/templates/content/actions/configure-document-property.ts +35 -1
  148. package/corpus/templates/content/actions/create-content-database.ts +5 -1
  149. package/corpus/templates/content/actions/delete-document-property.ts +52 -2
  150. package/corpus/templates/content/actions/duplicate-document-property.ts +34 -17
  151. package/corpus/templates/content/actions/reorder-document-property.ts +79 -0
  152. package/corpus/templates/content/actions/set-document-property.ts +39 -0
  153. package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +806 -0
  154. package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +226 -68
  155. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +59 -30
  156. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +25 -1
  157. package/corpus/templates/content/app/components/editor/blockFieldSaveController.ts +180 -0
  158. package/corpus/templates/content/app/components/editor/blockFieldSaveRegistry.ts +179 -0
  159. package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +244 -0
  160. package/corpus/templates/content/app/components/editor/previewDocumentSaveRegistry.ts +132 -0
  161. package/corpus/templates/content/app/global.css +9 -0
  162. package/corpus/templates/content/app/hooks/use-document-properties.ts +21 -0
  163. package/corpus/templates/content/app/root.tsx +7 -1
  164. package/corpus/templates/content/server/db/schema.ts +30 -0
  165. package/corpus/templates/content/server/plugins/db.ts +87 -0
  166. package/corpus/templates/content/shared/api.ts +7 -0
  167. package/corpus/templates/content/shared/properties.ts +109 -0
  168. package/corpus/templates/design/CHANGELOG.md +10 -0
  169. package/corpus/templates/design/actions/generate-design.ts +4 -0
  170. package/corpus/templates/design/app/root.tsx +7 -1
  171. package/corpus/templates/design/app/routes/settings.tsx +10 -2
  172. package/corpus/templates/dispatch/CHANGELOG.md +10 -0
  173. package/corpus/templates/dispatch/app/root.tsx +7 -1
  174. package/corpus/templates/forms/.agents/skills/form-responses/SKILL.md +10 -0
  175. package/corpus/templates/forms/CHANGELOG.md +10 -0
  176. package/corpus/templates/forms/actions/export-responses.ts +6 -0
  177. package/corpus/templates/forms/actions/list-responses.ts +2 -0
  178. package/corpus/templates/forms/actions/response-insights.ts +2 -0
  179. package/corpus/templates/forms/app/pages/ResponsesPage.tsx +138 -1
  180. package/corpus/templates/forms/app/root.tsx +7 -1
  181. package/corpus/templates/forms/changelog/2026-06-23-response-tables-now-show-the-page-each-submission-came-from-.md +6 -0
  182. package/corpus/templates/forms/changelog/2026-06-23-response-tables-now-show-whether-feedback-came-from-the-web-.md +6 -0
  183. package/corpus/templates/forms/server/db/schema.ts +7 -0
  184. package/corpus/templates/forms/server/handlers/submissions.ts +19 -2
  185. package/corpus/templates/forms/server/lib/integrations.ts +76 -2
  186. package/corpus/templates/forms/server/plugins/db.ts +20 -0
  187. package/corpus/templates/forms/shared/types.ts +12 -0
  188. package/corpus/templates/macros/CHANGELOG.md +10 -0
  189. package/corpus/templates/macros/app/root.tsx +7 -1
  190. package/corpus/templates/mail/CHANGELOG.md +10 -0
  191. package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +3 -0
  192. package/corpus/templates/mail/app/pages/SettingsPage.tsx +27 -0
  193. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +31 -17
  194. package/corpus/templates/plan/.agents/skills/visual-plan/references/wireframe.md +7 -4
  195. package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +34 -24
  196. package/corpus/templates/plan/.agents/skills/visual-recap/references/wireframe.md +7 -4
  197. package/corpus/templates/plan/AGENTS.md +4 -0
  198. package/corpus/templates/plan/CHANGELOG.md +10 -0
  199. package/corpus/templates/plan/actions/view-screen.ts +5 -0
  200. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +98 -1
  201. package/corpus/templates/plan/app/components/plan/wireframe/html-artboard.css +3 -1
  202. package/corpus/templates/plan/app/pages/PlansPage.tsx +107 -7
  203. package/corpus/templates/plan/app/root.tsx +7 -1
  204. package/corpus/templates/plan/changelog/2026-06-23-large-diagrams-in-a-plan-now-scroll-within-their-block-inste.md +6 -0
  205. package/corpus/templates/plan/shared/share-attribution.ts +72 -0
  206. package/corpus/templates/slides/CHANGELOG.md +10 -0
  207. package/corpus/templates/slides/app/root.tsx +7 -1
  208. package/corpus/templates/videos/CHANGELOG.md +4 -151
  209. package/corpus/templates/videos/app/root.tsx +7 -1
  210. package/dist/action.js +87 -0
  211. package/dist/action.js.map +1 -1
  212. package/dist/agent/engine/builder-engine.d.ts +1 -1
  213. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  214. package/dist/agent/model-config.d.ts +2 -2
  215. package/dist/agent/model-config.d.ts.map +1 -1
  216. package/dist/agent/model-config.js +0 -2
  217. package/dist/agent/model-config.js.map +1 -1
  218. package/dist/agent/run-loop-with-resume.d.ts +13 -0
  219. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  220. package/dist/agent/run-loop-with-resume.js +44 -0
  221. package/dist/agent/run-loop-with-resume.js.map +1 -1
  222. package/dist/changelog/parse.d.ts +70 -0
  223. package/dist/changelog/parse.d.ts.map +1 -0
  224. package/dist/changelog/parse.js +200 -0
  225. package/dist/changelog/parse.js.map +1 -0
  226. package/dist/cli/changelog.d.ts +4 -0
  227. package/dist/cli/changelog.d.ts.map +1 -0
  228. package/dist/cli/changelog.js +166 -0
  229. package/dist/cli/changelog.js.map +1 -0
  230. package/dist/cli/index.js +18 -0
  231. package/dist/cli/index.js.map +1 -1
  232. package/dist/cli/recap.d.ts.map +1 -1
  233. package/dist/cli/recap.js +22 -1
  234. package/dist/cli/recap.js.map +1 -1
  235. package/dist/cli/skills.d.ts +3 -3
  236. package/dist/cli/skills.d.ts.map +1 -1
  237. package/dist/cli/skills.js +74 -47
  238. package/dist/cli/skills.js.map +1 -1
  239. package/dist/client/AgentPanel.d.ts.map +1 -1
  240. package/dist/client/AgentPanel.js +5 -3
  241. package/dist/client/AgentPanel.js.map +1 -1
  242. package/dist/client/AssistantChat.d.ts +6 -1
  243. package/dist/client/AssistantChat.d.ts.map +1 -1
  244. package/dist/client/AssistantChat.js +2 -2
  245. package/dist/client/AssistantChat.js.map +1 -1
  246. package/dist/client/CommandMenu.d.ts +17 -1
  247. package/dist/client/CommandMenu.d.ts.map +1 -1
  248. package/dist/client/CommandMenu.js +49 -13
  249. package/dist/client/CommandMenu.js.map +1 -1
  250. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  251. package/dist/client/agent-chat-adapter.js +43 -6
  252. package/dist/client/agent-chat-adapter.js.map +1 -1
  253. package/dist/client/analytics.d.ts +18 -0
  254. package/dist/client/analytics.d.ts.map +1 -1
  255. package/dist/client/analytics.js +177 -0
  256. package/dist/client/analytics.js.map +1 -1
  257. package/dist/client/changelog/Changelog.d.ts +47 -0
  258. package/dist/client/changelog/Changelog.d.ts.map +1 -0
  259. package/dist/client/changelog/Changelog.js +138 -0
  260. package/dist/client/changelog/Changelog.js.map +1 -0
  261. package/dist/client/client-surface.d.ts +17 -0
  262. package/dist/client/client-surface.d.ts.map +1 -0
  263. package/dist/client/client-surface.js +24 -0
  264. package/dist/client/client-surface.js.map +1 -0
  265. package/dist/client/composer/TiptapComposer.d.ts +26 -1
  266. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  267. package/dist/client/composer/TiptapComposer.js +27 -5
  268. package/dist/client/composer/TiptapComposer.js.map +1 -1
  269. package/dist/client/feedback-context.d.ts +3 -0
  270. package/dist/client/feedback-context.d.ts.map +1 -1
  271. package/dist/client/feedback-context.js +2 -0
  272. package/dist/client/feedback-context.js.map +1 -1
  273. package/dist/client/index.d.ts +3 -1
  274. package/dist/client/index.d.ts.map +1 -1
  275. package/dist/client/index.js +3 -1
  276. package/dist/client/index.js.map +1 -1
  277. package/dist/client/mcp-apps/McpAppRenderer.d.ts +1 -0
  278. package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  279. package/dist/client/mcp-apps/McpAppRenderer.js +42 -1
  280. package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
  281. package/dist/client/settings/useBuilderStatus.d.ts +2 -0
  282. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  283. package/dist/client/settings/useBuilderStatus.js +58 -10
  284. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  285. package/dist/client/sse-event-processor.d.ts.map +1 -1
  286. package/dist/client/sse-event-processor.js +7 -1
  287. package/dist/client/sse-event-processor.js.map +1 -1
  288. package/dist/mcp/build-server.d.ts +21 -0
  289. package/dist/mcp/build-server.d.ts.map +1 -1
  290. package/dist/mcp/build-server.js +43 -1
  291. package/dist/mcp/build-server.js.map +1 -1
  292. package/dist/mcp/embed-app.d.ts.map +1 -1
  293. package/dist/mcp/embed-app.js +197 -7
  294. package/dist/mcp/embed-app.js.map +1 -1
  295. package/dist/mcp/oauth-route.d.ts.map +1 -1
  296. package/dist/mcp/oauth-route.js +95 -12
  297. package/dist/mcp/oauth-route.js.map +1 -1
  298. package/dist/server/attribution.d.ts +83 -0
  299. package/dist/server/attribution.d.ts.map +1 -0
  300. package/dist/server/attribution.js +178 -0
  301. package/dist/server/attribution.js.map +1 -0
  302. package/dist/server/auth.d.ts.map +1 -1
  303. package/dist/server/auth.js +7 -0
  304. package/dist/server/auth.js.map +1 -1
  305. package/dist/server/better-auth-instance.d.ts +9 -1
  306. package/dist/server/better-auth-instance.d.ts.map +1 -1
  307. package/dist/server/better-auth-instance.js +32 -2
  308. package/dist/server/better-auth-instance.js.map +1 -1
  309. package/dist/server/builder-browser.d.ts +4 -0
  310. package/dist/server/builder-browser.d.ts.map +1 -1
  311. package/dist/server/builder-browser.js +20 -1
  312. package/dist/server/builder-browser.js.map +1 -1
  313. package/dist/server/core-routes-plugin.d.ts +25 -0
  314. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  315. package/dist/server/core-routes-plugin.js +101 -0
  316. package/dist/server/core-routes-plugin.js.map +1 -1
  317. package/dist/server/google-oauth.d.ts.map +1 -1
  318. package/dist/server/google-oauth.js +16 -2
  319. package/dist/server/google-oauth.js.map +1 -1
  320. package/dist/server/onboarding-html.d.ts.map +1 -1
  321. package/dist/server/onboarding-html.js +35 -0
  322. package/dist/server/onboarding-html.js.map +1 -1
  323. package/dist/shared/mcp-embed-headers.js +1 -1
  324. package/dist/shared/mcp-embed-headers.js.map +1 -1
  325. package/dist/styles/agent-conversation.css +21 -0
  326. package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
  327. package/dist/templates/workspace-core/.agents/skills/reliable-mutations/SKILL.md +72 -0
  328. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
  329. package/docs/design/durable-agent-runs.md +217 -0
  330. package/package.json +1 -1
  331. package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
  332. package/src/templates/workspace-core/.agents/skills/reliable-mutations/SKILL.md +72 -0
  333. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
  334. package/corpus/templates/analytics/app/pages/About.tsx +0 -108
  335. package/corpus/templates/analytics/app/routes/about.tsx +0 -9
  336. /package/corpus/templates/analytics/app/routes/{dashboards.tsx → dashboards._index.tsx} +0 -0
@@ -590,12 +590,15 @@ no labels or copy. The renderer drops borders, sketch, and color into the
590
590
  skeleton register automatically. Never escape to a \`custom-html\` document block
591
591
  to fake a loader.
592
592
 
593
- **Editing an existing mockup.** To change one element, text, or color in an
594
- existing html mockup, call \`update-visual-plan\`
595
- with \`contentPatches: [{ op: "patch-wireframe-html", blockId, edits: [{ find,
593
+ **Editing an existing mockup.** In hosted mode, to change one element, text, or
594
+ color in an existing html mockup, do not regenerate the frame — call
595
+ \`update-visual-plan\` with
596
+ \`contentPatches: [{ op: "patch-wireframe-html", blockId, edits: [{ find,
596
597
  replace }] }]\`. Each \`find\` is a unique snippet of the current html (read it
597
598
  first with \`get-visual-plan\`); set \`all: true\` on an edit to replace every
598
- occurrence. The result is re-sanitized.
599
+ occurrence. The result is re-sanitized. In local-files privacy mode, do not call
600
+ hosted Plan tools; edit the local MDX source directly and rerun the local
601
+ check/serve or verify command for \`<plan-dir>\`.
599
602
 
600
603
  **Treat the wireframe border as part of the visible design.** Always wrap HTML
601
604
  wireframe content in a root container with real inner padding before drawing
@@ -1239,13 +1242,14 @@ surface.
1239
1242
  approach and options in the plan. Ask a clarifying question only when an
1240
1243
  ambiguity would change the design and you cannot resolve it from the code; use
1241
1244
  the host agent's normal ask-user-question flow and batch 2-4 high-leverage
1242
- questions before finalizing. Do not call \`create-visual-questions\` from
1243
- \`/visual-plan\`. Otherwise state the assumption explicitly and proceed, and
1244
- keep anything unresolved in the plan's single bottom \`question-form\` Open
1245
- Questions block. For complex plans, do a final open-question pass before
1246
- handoff: if a decision would affect architecture, scope, UX, data shape, or
1247
- rollout, either decide it in the plan with rationale or put it in that bottom
1248
- form with a recommended default.
1245
+ questions before finalizing. Do not call \`create-visual-questions\` for
1246
+ ordinary clarification or preflight; reserve it for the visual-intake mode when
1247
+ the user explicitly asks for a visual intake questionnaire. Otherwise state the
1248
+ assumption explicitly and proceed, and keep anything unresolved in the plan's
1249
+ single bottom \`question-form\` Open Questions block. For complex plans, do a
1250
+ final open-question pass before handoff: if a decision would affect
1251
+ architecture, scope, UX, data shape, or rollout, either decide it in the plan
1252
+ with rationale or put it in that bottom form with a recommended default.
1249
1253
  - **The plan is the approval gate.** After surfacing it, ask the user to review
1250
1254
  and approve before you write code, and name which files/areas the work touches.
1251
1255
  Presenting the plan and requesting sign-off is the approval step — do not ask a
@@ -1290,6 +1294,11 @@ is reachable. Local-files privacy mode (after Tool Guidance) is the exception.
1290
1294
 
1291
1295
  ## Core Workflow
1292
1296
 
1297
+ This section describes the default hosted Plan MCP workflow. If
1298
+ \`AGENT_NATIVE_PLANS_MODE=local-files\` is set, or the user asks for fully local
1299
+ files/no hosted Plan writes, use **Local-Files Privacy Mode** instead; carry
1300
+ forward only the code-research and plan-composition guidance here.
1301
+
1293
1302
  1. Follow the host agent's normal planning flow: inspect the codebase, delegate
1294
1303
  wide exploration when useful, gather the info needed, and ask native
1295
1304
  clarifying questions as needed before generating the plan. If a source plan
@@ -1336,11 +1345,13 @@ is reachable. Local-files privacy mode (after Tool Guidance) is the exception.
1336
1345
  backend, data, multi-file, or risky), also kick off the self-review pass in
1337
1346
  **Self-Review Before Handoff** while the user reads, instead of blocking the
1338
1347
  handoff on it.
1339
- 5. Call \`get-plan-feedback\` before editing, after review, after any long pause,
1348
+ 5. For hosted plans, call \`get-plan-feedback\` before editing, after review,
1349
+ after any long pause,
1340
1350
  and before the final response. Treat \`anchorDetails\`, resolver intent, recent
1341
1351
  review events, and any focused screenshots from browser handoff as the source
1342
1352
  of truth for exactly what changed and exactly what each comment points at.
1343
- 6. Apply changes with \`update-visual-plan\`, preferring targeted \`contentPatches\`.
1353
+ 6. For hosted plans, apply changes with \`update-visual-plan\`, preferring
1354
+ targeted \`contentPatches\`.
1344
1355
  Treat the top-level \`content\` payload as a full replacement, not a merge; do
1345
1356
  not send a partial \`content\` object to add a canvas or one block. If a full
1346
1357
  replacement is unavoidable, first read the complete plan source/content, carry
@@ -1348,8 +1359,8 @@ is reachable. Local-files privacy mode (after Tool Guidance) is the exception.
1348
1359
  afterward so the document body was not truncated. When the user wants
1349
1360
  source-control friendly edits, use \`patch-visual-plan-source\` against the MDX
1350
1361
  files instead of regenerating the plan.
1351
- 7. Export with \`export-visual-plan\` only when the user wants a shareable receipt
1352
- or repo-check-in artifacts.
1362
+ 7. For hosted plans, export with \`export-visual-plan\` only when the user wants a
1363
+ shareable receipt or repo-check-in artifacts.
1353
1364
 
1354
1365
  ## Self-Review Before Handoff
1355
1366
 
@@ -1545,11 +1556,12 @@ The local-files contract is:
1545
1556
  wants the artifact checked into the repo, or use a repo-ignored/temporary
1546
1557
  folder such as \`.agent-native/plans/<slug>/\` or \`/tmp/agent-native-plans/<slug>/\`
1547
1558
  when it should not be checked in. The folder contains \`plan.mdx\`, optional
1548
- \`canvas.mdx\`, optional \`prototype.mdx\`, and optional \`.plan-state.json\`.
1549
- - Run \`npx @agent-native/core@latest plan local check --dir plans/<slug>\`
1550
- before serving, then run
1551
- \`npx @agent-native/core@latest plan local serve --dir plans/<slug> --kind plan --open\`.
1552
- Report the returned local bridge URL from stdout or \`plans/<slug>/.plan-url\`.
1559
+ \`canvas.mdx\`, optional \`prototype.mdx\`, and optional \`.plan-state.json\`. Use
1560
+ that exact chosen folder as \`<plan-dir>\` in every local CLI command below.
1561
+ - Run \`npx @agent-native/core@latest plan local check --dir <plan-dir>\` before
1562
+ serving, then run
1563
+ \`npx @agent-native/core@latest plan local serve --dir <plan-dir> --kind plan --open\`.
1564
+ Report the returned local bridge URL from stdout or \`<plan-dir>/.plan-url\`.
1553
1565
  Treat \`.plan-url\` as a local token file and do not commit it. The URL opens
1554
1566
  the hosted Plan UI but reads from the localhost bridge on this machine, so it
1555
1567
  is not shareable across machines. On macOS, \`--open\` prefers Chromium browsers;
@@ -1558,7 +1570,7 @@ The local-files contract is:
1558
1570
  running locally with the same \`PLAN_LOCAL_DIR\`, the \`/local-plans/<slug>\` route
1559
1571
  is also valid.
1560
1572
  - For headless verification, run
1561
- \`npx @agent-native/core@latest plan local verify --dir plans/<slug> --kind plan\`.
1573
+ \`npx @agent-native/core@latest plan local verify --dir <plan-dir> --kind plan\`.
1562
1574
  It starts the bridge, checks the private-network preflight and JSON payload,
1563
1575
  prints diagnostics, and exits. If the browser hangs on "Loading plan", fetch
1564
1576
  the \`bridgeUrl\` from the verify/serve JSON to read the concrete validation
@@ -1580,6 +1592,11 @@ otherwise approved by the user.
1580
1592
 
1581
1593
  ## Interpreting comment anchors
1582
1594
 
1595
+ This section applies to hosted plans with \`get-plan-feedback\` /
1596
+ \`update-visual-plan\`. In local-files mode, do not call hosted feedback or update
1597
+ tools; interpret file/chat feedback directly, edit the MDX files, rerun the
1598
+ local bridge check/serve/verify command, and report the new local URL.
1599
+
1583
1600
  \`get-plan-feedback\` returns rich anchors — read them before acting on any comment.
1584
1601
 
1585
1602
  - **Coordinate frames.** \`targetX\`/\`targetY\` are percentages *within* the
@@ -1703,8 +1720,9 @@ In local-files mode:
1703
1720
  \`npx @agent-native/core@latest plan blocks --out plan-blocks.md\` when the Plan
1704
1721
  MCP connector is not registered; it calls the public no-auth
1705
1722
  \`get-plan-blocks\` route and sends no recap content. If network access is
1706
- unavailable, use the bundled references and validate with
1707
- \`plan local check\` / \`plan local serve\`. For \`checklist\` and \`question-form\`,
1723
+ unavailable, use the bundled references and validate the MDX with
1724
+ \`plan local check\`; do not run \`plan local serve\` unless the hosted Plan UI is
1725
+ reachable or a local Plan app is already running. For \`checklist\` and \`question-form\`,
1708
1726
  copy the catalog examples verbatim: checklist items need \`id\` and \`label\`;
1709
1727
  question-form questions need \`id\`, \`title\`, and \`mode\`; and each option needs
1710
1728
  \`id\` and \`label\`. \`plan local check\` validates these required fields against
@@ -1714,21 +1732,24 @@ In local-files mode:
1714
1732
  folder such as \`.agent-native/plans/<slug>/\` or \`/tmp/agent-native-plans/<slug>/\`
1715
1733
  when it should not be checked in. The folder contains \`plan.mdx\`, optional
1716
1734
  \`canvas.mdx\`, optional \`prototype.mdx\`, and optional \`.plan-state.json\`. Set
1717
- \`kind: "recap"\` and \`localOnly: true\` in frontmatter/state when authoring
1718
- the source.
1719
- - Run \`npx @agent-native/core@latest plan local check --dir plans/<slug>\`
1720
- before serving, then run
1721
- \`npx @agent-native/core@latest plan local serve --dir plans/<slug> --kind recap --open\`.
1722
- Report the returned local bridge URL from stdout or \`plans/<slug>/.plan-url\`.
1735
+ \`kind: "recap"\` and \`localOnly: true\` in frontmatter/state when authoring the
1736
+ source. Use that exact chosen folder as \`<plan-dir>\` in every local CLI command
1737
+ below.
1738
+ - Run \`npx @agent-native/core@latest plan local check --dir <plan-dir>\` before
1739
+ any preview. When the hosted Plan UI is reachable, run
1740
+ \`npx @agent-native/core@latest plan local serve --dir <plan-dir> --kind recap --open\`.
1741
+ Report the returned local bridge URL from stdout or \`<plan-dir>/.plan-url\`.
1723
1742
  Treat \`.plan-url\` as a local token file and do not commit it. The URL opens
1724
1743
  the hosted Plan UI but reads from the localhost bridge on this machine, so it
1725
1744
  is not shareable across machines. On macOS, \`--open\` prefers Chromium browsers;
1726
1745
  if Safari opens, switch to Chrome/Chromium because Safari can block the hosted
1727
1746
  HTTPS page from fetching the HTTP localhost bridge. If the Plan app itself is
1728
1747
  running locally with the same \`PLAN_LOCAL_DIR\`, the \`/local-plans/<slug>\` route
1729
- is also valid.
1748
+ is also valid. In a truly offline environment, hand off the local \`<plan-dir>\`
1749
+ path after \`plan local check\` and note that interactive preview requires either
1750
+ network access to the hosted Plan UI or a running local Plan app.
1730
1751
  - For headless verification, run
1731
- \`npx @agent-native/core@latest plan local verify --dir plans/<slug> --kind recap\`.
1752
+ \`npx @agent-native/core@latest plan local verify --dir <plan-dir> --kind recap\`.
1732
1753
  It starts the bridge, checks the private-network preflight and JSON payload,
1733
1754
  prints diagnostics, and exits. If the browser hangs on "Loading plan", fetch
1734
1755
  the \`bridgeUrl\` from the verify/serve JSON to read the concrete validation
@@ -1739,7 +1760,9 @@ In local-files mode:
1739
1760
  \`set-resource-visibility\`, or any hosted Plan tool for that recap except the
1740
1761
  schema-only block catalog lookup above.
1741
1762
  - Treat review feedback as file or chat feedback: update the MDX files directly,
1742
- rerun the local bridge command, and summarize the new local bridge URL.
1763
+ rerun \`plan local check\`, and rerun \`serve\` or \`verify\` only when that preview
1764
+ path is available. Summarize the new local URL when one exists; otherwise
1765
+ summarize the checked local folder path.
1743
1766
  Hosted comments, sharing, screenshots, usage attachment, and PR sticky comment
1744
1767
  publishing are unavailable until the user explicitly opts into publishing.
1745
1768
 
@@ -1955,10 +1978,10 @@ and re-import before reporting the link. A text-match screenshot is not enough;
1955
1978
  visually inspect the captured image. When no browser is available (for example
1956
1979
  a headless CI agent), state that in the recap handoff instead.
1957
1980
 
1958
- ## Top Canvas Recaps — read \`../visual-plans/references/canvas.md\`
1981
+ ## Top Canvas Recaps — read \`../visual-plan/references/canvas.md\`
1959
1982
 
1960
1983
  When a recap includes a top canvas, storyboard, or flow view, READ
1961
- \`../visual-plans/references/canvas.md\` before authoring \`canvas.mdx\`. Recap
1984
+ \`../visual-plan/references/canvas.md\` before authoring \`canvas.mdx\`. Recap
1962
1985
  canvas artboards must use the same HTML wireframe path as good document-body
1963
1986
  wireframes: \`<Screen surface="..." html={...} />\` with a semantic HTML fragment.
1964
1987
  Do not author fresh kit-tree children such as \`<FrameScreen>\`, \`<Card>\`,
@@ -1972,8 +1995,8 @@ assume it used the legacy kit path and replace it with an HTML screen.
1972
1995
 
1973
1996
  In local-files privacy mode, run \`plan local check\` first, then report the local
1974
1997
  bridge URL from
1975
- \`npx @agent-native/core@latest plan local serve --dir plans/<slug> --kind recap --open\`
1976
- or from \`plans/<slug>/.plan-url\`. It opens the hosted Plan UI but reads from the
1998
+ \`npx @agent-native/core@latest plan local serve --dir <plan-dir> --kind recap --open\`
1999
+ or from \`<plan-dir>/.plan-url\`. It opens the hosted Plan UI but reads from the
1977
2000
  localhost bridge on this machine, so it is not shareable across machines. If the
1978
2001
  Plan app itself is running locally with the same \`PLAN_LOCAL_DIR\`, the
1979
2002
  \`/local-plans/<slug>\` route is also valid. Do not invent a hosted database URL
@@ -2138,7 +2161,8 @@ installed as plain text and no MCP tools are registered after discovery, run
2138
2161
  \`npx @agent-native/core@latest plan blocks --out plan-blocks.md\` and read that
2139
2162
  file first. The CLI command calls the public no-auth \`get-plan-blocks\` route and
2140
2163
  sends no plan/recap content. If network access is unavailable, use the bundled
2141
- references and validate with \`plan local check\` / \`plan local serve\`.
2164
+ references and validate with \`plan local check\`; run \`plan local serve\` only
2165
+ when the hosted Plan UI is reachable or a local Plan app is already running.
2142
2166
 
2143
2167
  The catalog returns the authoritative, always-current block vocabulary generated
2144
2168
  live from the app's own block registry — the same config the renderer and MDX
@@ -2246,14 +2270,17 @@ inferred (not extracted) as inferred in prose.
2246
2270
 
2247
2271
  ## Bidirectional Loop
2248
2272
 
2249
- Because a recap is a real, editable plan, the same review loop as forward plans
2250
- applies: a reviewer can annotate any block, and the coding agent reads
2251
- \`get-plan-feedback\` to drive fixes back into the code — annotation → agent →
2252
- diff, the same close-the-loop flow forward plans use. After a reviewer annotates
2253
- a block, call \`get-plan-feedback\` to read the structured feedback, then either
2254
- update the recap with \`create-visual-recap\` (passing the existing \`planId\` to
2255
- replace it in place) or apply targeted changes with \`update-visual-plan\`. The
2256
- loop is live and wired. The one thing not yet automatic is PR-comment-triggered
2273
+ In hosted mode, because a recap is a real, editable plan, the same review loop
2274
+ as forward plans applies: a reviewer can annotate any block, and the coding
2275
+ agent reads \`get-plan-feedback\` to drive fixes back into the code — annotation →
2276
+ agent → diff, the same close-the-loop flow forward plans use. After a reviewer
2277
+ annotates a block, call \`get-plan-feedback\` to read the structured feedback,
2278
+ then either update the recap with \`create-visual-recap\` (passing the existing
2279
+ \`planId\` to replace it in place) or apply targeted changes with
2280
+ \`update-visual-plan\`. The loop is live and wired. In local-files privacy mode,
2281
+ do not call those hosted tools; read review notes from chat or local files, edit
2282
+ \`<plan-dir>/*.mdx\` directly, and rerun \`plan local check\`, \`serve\`, or \`verify\`
2283
+ for \`<plan-dir>\`. The one thing not yet automatic is PR-comment-triggered
2257
2284
  re-runs: the GitHub Action creates an initial recap per PR, but it does not yet
2258
2285
  re-run automatically when new review feedback is posted in GitHub — that
2259
2286
  auto-re-run is the remaining fast-follow.
@@ -4006,8 +4033,8 @@ async function promptForPlanMode(
4006
4033
  options: [
4007
4034
  {
4008
4035
  value: "hosted",
4009
- label: "Hosted plans, shareable links",
4010
- hint: "Recommended. 100% free and open source. Stores plans at plan.agent-native.com with sharing, comments, and browser editor. Requires one-time browser sign-in.",
4036
+ label: "Hosted plans, shareable links (recommended)",
4037
+ hint: "100% free and open source. Supports comments, browser editor, and sharing. Requires one-time browser sign-in.",
4011
4038
  },
4012
4039
  {
4013
4040
  value: "local-files",
@@ -147,9 +147,11 @@ const SetupButton = lazy(() =>
147
147
  })),
148
148
  );
149
149
 
150
- // Setup/onboarding widget appears above chat until required setup is complete,
151
- // and can be reopened from the header after dismissal.
152
- const SHOW_ONBOARDING = true;
150
+ // The setup/onboarding checklist that used to appear above chat is disabled
151
+ // for every app setup (AI engine, image/video gen, asset storage, email,
152
+ // GitHub, etc.) is surfaced in better places (the settings panel and the
153
+ // per-feature setup affordances). Keep this off; do not re-enable globally.
154
+ const SHOW_ONBOARDING = false;
153
155
 
154
156
  const CLI_STORAGE_KEY = "agent-native-cli-command";
155
157
  const CLI_DEFAULT = "claude";
@@ -86,6 +86,7 @@ import { agentNativePath } from "./api-path.js";
86
86
  import {
87
87
  TiptapComposer,
88
88
  type ComposerSubmitIntent,
89
+ type ComposerImageModelMenu,
89
90
  type TiptapComposerHandle,
90
91
  } from "./composer/TiptapComposer.js";
91
92
  import { AgentComposerFrame } from "./composer/AgentComposerFrame.js";
@@ -712,6 +713,11 @@ export interface AssistantChatProps {
712
713
  onModelChange?: (model: string, engine: string) => void;
713
714
  /** Callback when user picks a reasoning effort from the picker */
714
715
  onEffortChange?: (effort: ReasoningEffort) => void;
716
+ /**
717
+ * Optional secondary model menu (e.g. an image-generation model) shown inside
718
+ * the composer's model picker. Opt-in; chat-only apps omit it.
719
+ */
720
+ imageModelMenu?: ComposerImageModelMenu;
715
721
  /** Callback when user clicks "Fork Chat" in the message actions menu */
716
722
  onForkChat?: () => void | boolean | Promise<void | boolean>;
717
723
  /** Override Builder/provider connect routing for embedded hosts. */
@@ -977,6 +983,7 @@ const AssistantChatInner = forwardRef<
977
983
  availableModels,
978
984
  onModelChange,
979
985
  onEffortChange,
986
+ imageModelMenu,
980
987
  onForkChat,
981
988
  onConnectProvider,
982
989
  plusMenuMode = "full",
@@ -3392,6 +3399,7 @@ const AssistantChatInner = forwardRef<
3392
3399
  availableModels={availableModels}
3393
3400
  onModelChange={onModelChange}
3394
3401
  onEffortChange={onEffortChange}
3402
+ imageModelMenu={imageModelMenu}
3395
3403
  onConnectProvider={onConnectProvider}
3396
3404
  toolbarSlot={composerToolbarSlot}
3397
3405
  contextItems={composerContextItems}
@@ -20,6 +20,7 @@ import React, {
20
20
  useCallback,
21
21
  useContext,
22
22
  useEffect,
23
+ useMemo,
23
24
  useRef,
24
25
  useState,
25
26
  type ReactNode,
@@ -29,9 +30,12 @@ import {
29
30
  IconExternalLink,
30
31
  IconSearch,
31
32
  IconMessage,
33
+ IconHistory,
32
34
  } from "@tabler/icons-react";
33
35
  import { sendToAgentChat } from "./agent-chat.js";
34
36
  import { cn } from "./utils.js";
37
+ import { ChangelogDialog, useChangelogSeen } from "./changelog/Changelog.js";
38
+ import { parseChangelog } from "../changelog/parse.js";
35
39
 
36
40
  // ─── Context ────────────────────────────────────────────────────────────────
37
41
 
@@ -248,6 +252,22 @@ export interface CommandMenuProps {
248
252
  showAgentFallback?: boolean;
249
253
  /** Custom class for the dialog content */
250
254
  className?: string;
255
+ /**
256
+ * Raw CHANGELOG.md contents. When provided, the menu shows a built-in
257
+ * "What's new" entry that opens an in-app changelog dialog (with an unseen
258
+ * dot for new releases). Pass your app's own file:
259
+ * import changelog from "../CHANGELOG.md?raw";
260
+ * <CommandMenu ... changelog={changelog} />
261
+ */
262
+ changelog?: string;
263
+ /** Label for the built-in changelog entry. Default: "What's new". */
264
+ changelogLabel?: string;
265
+ /**
266
+ * Stable key used to remember which release a user has already seen (for the
267
+ * unseen dot). Defaults to the document title's host app; set explicitly when
268
+ * multiple apps share an origin.
269
+ */
270
+ changelogKey?: string;
251
271
  }
252
272
 
253
273
  export function CommandMenu({
@@ -258,12 +278,36 @@ export function CommandMenu({
258
278
  emptyText: _emptyText = "No commands found.",
259
279
  showAgentFallback = true,
260
280
  className,
281
+ changelog,
282
+ changelogLabel = "What's new",
283
+ changelogKey,
261
284
  }: CommandMenuProps) {
262
285
  const [search, setSearch] = useState("");
263
286
  const [selectedIndex, setSelectedIndex] = useState(0);
264
287
  const inputRef = useRef<HTMLInputElement>(null);
265
288
  const containerRef = useRef<HTMLDivElement>(null);
266
289
 
290
+ // Built-in "What's new" changelog surface (only active when `changelog` is
291
+ // passed). The dialog is rendered alongside the menu so it survives the menu
292
+ // closing; the unseen dot persists per browser via localStorage.
293
+ const [changelogOpen, setChangelogOpen] = useState(false);
294
+ const hasChangelog =
295
+ typeof changelog === "string" && changelog.trim().length > 0;
296
+ const changelogEntries = useMemo(
297
+ () => (hasChangelog ? parseChangelog(changelog as string) : []),
298
+ [hasChangelog, changelog],
299
+ );
300
+ const latestChangelogId = changelogEntries[0]?.id;
301
+ const { unseen: changelogUnseen, markSeen: markChangelogSeen } =
302
+ useChangelogSeen(changelogKey ?? "app", latestChangelogId);
303
+
304
+ const openChangelog = useCallback(() => {
305
+ onOpenChange(false);
306
+ markChangelogSeen();
307
+ // Let the menu close before the dialog opens (avoids overlay flicker).
308
+ setTimeout(() => setChangelogOpen(true), 50);
309
+ }, [onOpenChange, markChangelogSeen]);
310
+
267
311
  // Focus input when opening
268
312
  useEffect(() => {
269
313
  if (open) {
@@ -361,7 +405,22 @@ export function CommandMenu({
361
405
  }
362
406
  };
363
407
 
364
- if (!open) return null;
408
+ // The built-in "What's new" row matches changelog-ish search terms.
409
+ const changelogRowMatches =
410
+ !search ||
411
+ [
412
+ changelogLabel,
413
+ "changelog",
414
+ "what's new",
415
+ "whats new",
416
+ "updates",
417
+ "release notes",
418
+ "changes",
419
+ ]
420
+ .join(" ")
421
+ .toLowerCase()
422
+ .includes(search.toLowerCase());
423
+ const showChangelogRow = hasChangelog && changelogRowMatches;
365
424
 
366
425
  // Filter children based on search
367
426
  const filterChildren = (nodes: ReactNode): ReactNode => {
@@ -423,82 +482,131 @@ export function CommandMenu({
423
482
  );
424
483
 
425
484
  return (
426
- <div className="fixed inset-0 z-50 bg-black/50">
427
- <div
428
- ref={containerRef}
429
- className={cn(
430
- "fixed left-1/2 top-[15vh] -translate-x-1/2 w-full max-w-lg",
431
- "rounded-lg border border-border bg-popover text-popover-foreground shadow-lg",
432
- className,
433
- )}
434
- >
435
- <CommandMenuContext.Provider
436
- value={{ search, onOpenChange, containerRef, setSelectedIndex }}
437
- >
438
- {/* Search input */}
439
- <div className="flex items-center border-b px-3">
440
- <IconSearch className="mr-2 h-4 w-4 shrink-0 opacity-50" />
441
- <input
442
- ref={inputRef}
443
- value={search}
444
- onChange={(e) => setSearch(e.target.value)}
445
- onKeyDown={handleKeyDown}
446
- placeholder={placeholder}
447
- className="flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
448
- />
449
- </div>
450
-
451
- {/* Command list */}
452
- <div className="max-h-[300px] overflow-y-auto overflow-x-hidden">
453
- {hasResults && filteredChildren}
454
-
455
- {/* Ask AI — always visible at the bottom */}
456
- {showAgentFallback && (
457
- <>
458
- {hasResults && <CommandSeparator />}
459
- <div className="p-1">
460
- <div
461
- className="relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-2 text-sm outline-none"
462
- onClick={handleSubmitToAgent}
463
- onMouseEnter={(e) => {
464
- const items =
465
- containerRef.current?.querySelectorAll(
466
- '[role="option"]',
467
- );
468
- if (!items) return;
469
- const index = Array.from(items).indexOf(e.currentTarget);
470
- if (index >= 0) setSelectedIndex(index);
471
- }}
472
- role="option"
473
- >
474
- <IconMessage className="h-4 w-4 text-muted-foreground" />
475
- <span>
476
- {search.trim() ? (
477
- <>
478
- Ask AI:{" "}
479
- <span className="text-muted-foreground">
480
- "{search}"
481
- </span>
482
- </>
483
- ) : (
484
- <span className="text-muted-foreground">
485
- Ask AI anything...
486
- </span>
487
- )}
488
- </span>
489
- {search.trim() && (
490
- <span className="ml-auto text-xs text-muted-foreground">
491
-
492
- </span>
493
- )}
494
- </div>
495
- </div>
496
- </>
485
+ <>
486
+ {open && (
487
+ <div className="fixed inset-0 z-50 bg-black/50">
488
+ <div
489
+ ref={containerRef}
490
+ className={cn(
491
+ "fixed left-1/2 top-[15vh] -translate-x-1/2 w-full max-w-lg",
492
+ "rounded-lg border border-border bg-popover text-popover-foreground shadow-lg",
493
+ className,
497
494
  )}
495
+ >
496
+ <CommandMenuContext.Provider
497
+ value={{ search, onOpenChange, containerRef, setSelectedIndex }}
498
+ >
499
+ {/* Search input */}
500
+ <div className="flex items-center border-b px-3">
501
+ <IconSearch className="mr-2 h-4 w-4 shrink-0 opacity-50" />
502
+ <input
503
+ ref={inputRef}
504
+ value={search}
505
+ onChange={(e) => setSearch(e.target.value)}
506
+ onKeyDown={handleKeyDown}
507
+ placeholder={placeholder}
508
+ className="flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
509
+ />
510
+ </div>
511
+
512
+ {/* Command list */}
513
+ <div className="max-h-[300px] overflow-y-auto overflow-x-hidden">
514
+ {hasResults && filteredChildren}
515
+
516
+ {/* What's new — built-in changelog entry */}
517
+ {showChangelogRow && (
518
+ <>
519
+ {hasResults && <CommandSeparator />}
520
+ <div className="p-1">
521
+ <div
522
+ className="relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-2 text-sm outline-none"
523
+ onClick={openChangelog}
524
+ onMouseEnter={(e) => {
525
+ const items =
526
+ containerRef.current?.querySelectorAll(
527
+ '[role="option"]',
528
+ );
529
+ if (!items) return;
530
+ const index = Array.from(items).indexOf(
531
+ e.currentTarget,
532
+ );
533
+ if (index >= 0) setSelectedIndex(index);
534
+ }}
535
+ role="option"
536
+ >
537
+ <IconHistory className="h-4 w-4 text-muted-foreground" />
538
+ <span>{changelogLabel}</span>
539
+ {changelogUnseen && (
540
+ <span
541
+ className="ml-auto h-2 w-2 rounded-full bg-primary"
542
+ aria-label="New updates available"
543
+ />
544
+ )}
545
+ </div>
546
+ </div>
547
+ </>
548
+ )}
549
+
550
+ {/* Ask AI — always visible at the bottom */}
551
+ {showAgentFallback && (
552
+ <>
553
+ {(hasResults || showChangelogRow) && <CommandSeparator />}
554
+ <div className="p-1">
555
+ <div
556
+ className="relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-2 text-sm outline-none"
557
+ onClick={handleSubmitToAgent}
558
+ onMouseEnter={(e) => {
559
+ const items =
560
+ containerRef.current?.querySelectorAll(
561
+ '[role="option"]',
562
+ );
563
+ if (!items) return;
564
+ const index = Array.from(items).indexOf(
565
+ e.currentTarget,
566
+ );
567
+ if (index >= 0) setSelectedIndex(index);
568
+ }}
569
+ role="option"
570
+ >
571
+ <IconMessage className="h-4 w-4 text-muted-foreground" />
572
+ <span>
573
+ {search.trim() ? (
574
+ <>
575
+ Ask AI:{" "}
576
+ <span className="text-muted-foreground">
577
+ "{search}"
578
+ </span>
579
+ </>
580
+ ) : (
581
+ <span className="text-muted-foreground">
582
+ Ask AI anything...
583
+ </span>
584
+ )}
585
+ </span>
586
+ {search.trim() && (
587
+ <span className="ml-auto text-xs text-muted-foreground">
588
+
589
+ </span>
590
+ )}
591
+ </div>
592
+ </div>
593
+ </>
594
+ )}
595
+ </div>
596
+ </CommandMenuContext.Provider>
498
597
  </div>
499
- </CommandMenuContext.Provider>
500
- </div>
501
- </div>
598
+ </div>
599
+ )}
600
+
601
+ {hasChangelog && (
602
+ <ChangelogDialog
603
+ open={changelogOpen}
604
+ onOpenChange={setChangelogOpen}
605
+ markdown={changelog as string}
606
+ title={changelogLabel}
607
+ />
608
+ )}
609
+ </>
502
610
  );
503
611
  }
504
612