@agent-native/core 0.79.27 → 0.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +26 -0
  3. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +41 -0
  4. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +51 -0
  5. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +50 -0
  6. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +49 -0
  7. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +44 -0
  8. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +46 -0
  9. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +44 -0
  10. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +48 -0
  11. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +36 -0
  12. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +38 -0
  13. package/corpus/core/docs/content/template-design.mdx +45 -0
  14. package/corpus/core/package.json +2 -1
  15. package/corpus/core/src/agent/engine/index.ts +1 -0
  16. package/corpus/core/src/agent/engine/registry.ts +40 -0
  17. package/corpus/core/src/agent/production-agent.ts +6 -2
  18. package/corpus/core/src/cli/design-connect.ts +490 -0
  19. package/corpus/core/src/cli/index.ts +16 -0
  20. package/corpus/core/src/cli/skills.ts +126 -3
  21. package/corpus/core/src/client/AssistantChat.tsx +43 -7
  22. package/corpus/core/src/client/agent-chat.ts +27 -3
  23. package/corpus/core/src/client/blocks/library/MermaidBlock.tsx +1 -1
  24. package/corpus/core/src/client/blocks/library/diagram.tsx +2 -2
  25. package/corpus/core/src/client/blocks/library/wireframe.tsx +1 -1
  26. package/corpus/core/src/client/chat/message-components.tsx +1 -1
  27. package/corpus/core/src/client/chat-model-groups.ts +1 -2
  28. package/corpus/core/src/client/components/LiveCursorOverlay.tsx +33 -66
  29. package/corpus/core/src/client/composer/TiptapComposer.tsx +99 -24
  30. package/corpus/core/src/client/composer/useVoiceDictation.ts +429 -260
  31. package/corpus/core/src/client/frame-protocol.ts +17 -2
  32. package/corpus/core/src/client/rich-markdown-editor/RegistryBlockNode.tsx +2 -2
  33. package/corpus/core/src/client/sharing/ShareButton.tsx +20 -15
  34. package/corpus/core/src/client/use-agent-engine-configured.ts +80 -28
  35. package/corpus/core/src/server/transcribe-voice.ts +57 -22
  36. package/corpus/core/src/shared/mcp-embed-headers.ts +23 -1
  37. package/corpus/core/src/styles/agent-native.css +56 -7
  38. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  39. package/corpus/core/src/vite/client.ts +2 -0
  40. package/corpus/core/src/voice/index.ts +18 -0
  41. package/corpus/core/src/voice/voice-cleanup-prompt.ts +38 -0
  42. package/corpus/core/src/voice/voice-context.ts +217 -0
  43. package/corpus/core/src/voice/voice-replacements.ts +75 -0
  44. package/corpus/templates/analytics/AGENTS.md +4 -3
  45. package/corpus/templates/analytics/actions/list-session-recordings.ts +6 -1
  46. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +557 -400
  47. package/corpus/templates/analytics/app/global.css +0 -4
  48. package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
  49. package/corpus/templates/analytics/app/i18n-data.ts +20 -0
  50. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +33 -8
  51. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +7 -0
  52. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +7 -0
  53. package/corpus/templates/analytics/changelog/2026-06-28-ask-tab-now-matches-the-darker-app-background.md +6 -0
  54. package/corpus/templates/analytics/changelog/2026-06-28-dashboard-email-reports-now-use-cleaner-light-mode-snapshots.md +6 -0
  55. package/corpus/templates/analytics/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  56. package/corpus/templates/analytics/changelog/2026-06-28-sessions-now-show-only-signed-in-recordings-with-playable-re.md +6 -0
  57. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +3 -3
  58. package/corpus/templates/analytics/server/lib/dashboard-report.ts +29 -7
  59. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +5 -2
  60. package/corpus/templates/analytics/server/lib/session-replay.ts +24 -4
  61. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +4 -4
  62. package/corpus/templates/assets/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  63. package/corpus/templates/brain/app/components/layout/Layout.tsx +29 -2
  64. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +131 -42
  65. package/corpus/templates/brain/app/i18n/zh-TW.ts +2 -0
  66. package/corpus/templates/brain/app/i18n-data.ts +20 -0
  67. package/corpus/templates/brain/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  68. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +29 -1
  69. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +417 -299
  70. package/corpus/templates/calendar/app/i18n/zh-TW.ts +2 -0
  71. package/corpus/templates/calendar/app/i18n-data.ts +20 -0
  72. package/corpus/templates/calendar/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  73. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +6 -19
  74. package/corpus/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  75. package/corpus/templates/clips/AGENTS.md +4 -0
  76. package/corpus/templates/clips/actions/cleanup-transcript.ts +39 -9
  77. package/corpus/templates/clips/actions/finalize-meeting.ts +81 -12
  78. package/corpus/templates/clips/actions/lib/agents-md-context.ts +4 -1
  79. package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -3
  80. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +1 -1
  81. package/corpus/templates/clips/app/components/player/share-dialog.tsx +2 -2
  82. package/corpus/templates/clips/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
  83. package/corpus/templates/clips/desktop/src/lib/personal-vocabulary.ts +13 -8
  84. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +60 -1
  85. package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +1 -1
  86. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +1 -1
  87. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +5 -5
  88. package/corpus/templates/content/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  89. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +137 -0
  90. package/corpus/templates/design/AGENTS.md +95 -5
  91. package/corpus/templates/design/DESIGN.md +82 -0
  92. package/corpus/templates/design/DEVELOPING.md +43 -0
  93. package/corpus/templates/design/actions/add-localhost-screens.ts +426 -0
  94. package/corpus/templates/design/actions/apply-shader.ts +277 -0
  95. package/corpus/templates/design/actions/apply-visual-edit.ts +303 -0
  96. package/corpus/templates/design/actions/connect-localhost.ts +183 -0
  97. package/corpus/templates/design/actions/edit-design.ts +195 -42
  98. package/corpus/templates/design/actions/generate-design.ts +71 -1
  99. package/corpus/templates/design/actions/generate-screens.ts +193 -0
  100. package/corpus/templates/design/actions/get-code-layer-projection.ts +191 -0
  101. package/corpus/templates/design/actions/get-shader.ts +119 -0
  102. package/corpus/templates/design/actions/list-localhost-connections.ts +95 -0
  103. package/corpus/templates/design/actions/navigate.ts +55 -2
  104. package/corpus/templates/design/actions/view-screen.ts +68 -1
  105. package/corpus/templates/design/agent-native.app-skill.json +10 -0
  106. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +761 -0
  107. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +2057 -103
  108. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +74 -38
  109. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +399 -0
  110. package/corpus/templates/design/app/components/design/EditPanel.tsx +3185 -439
  111. package/corpus/templates/design/app/components/design/LayersPanel.tsx +1124 -0
  112. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +3116 -147
  113. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +700 -13
  114. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +107 -63
  115. package/corpus/templates/design/app/components/design/index.ts +0 -5
  116. package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +286 -0
  117. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +699 -0
  118. package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +461 -0
  119. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +166 -0
  120. package/corpus/templates/design/app/components/design/inspector/FigmaColorPicker.tsx +1420 -0
  121. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +420 -0
  122. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +215 -0
  123. package/corpus/templates/design/app/components/design/inspector/ShaderControls.stories.tsx +71 -0
  124. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +518 -0
  125. package/corpus/templates/design/app/components/design/inspector/ShaderEffectRow.tsx +106 -0
  126. package/corpus/templates/design/app/components/design/inspector/figma-icons.tsx +361 -0
  127. package/corpus/templates/design/app/components/design/inspector/index.ts +60 -0
  128. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +201 -0
  129. package/corpus/templates/design/app/components/design/types.ts +23 -0
  130. package/corpus/templates/design/app/components/layout/Layout.tsx +24 -13
  131. package/corpus/templates/design/app/components/layout/Sidebar.tsx +4 -4
  132. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +474 -36
  133. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +22 -5
  134. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +24 -11
  135. package/corpus/templates/design/app/global.css +121 -3
  136. package/corpus/templates/design/app/hooks/use-agent-generating.ts +4 -0
  137. package/corpus/templates/design/app/hooks/use-navigation-state.ts +130 -8
  138. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +329 -0
  139. package/corpus/templates/design/app/i18n/zh-TW.ts +264 -0
  140. package/corpus/templates/design/app/i18n-data.ts +2790 -1
  141. package/corpus/templates/design/app/pages/DesignEditor.tsx +5108 -851
  142. package/corpus/templates/design/changelog/2026-06-28-annotate-mode-now-combines-drawing-and-comment-pins-in-one-c.md +6 -0
  143. package/corpus/templates/design/changelog/2026-06-28-design-editor-panel-borders-are-cleaner-so-the-canvas-edge-s.md +6 -0
  144. package/corpus/templates/design/changelog/2026-06-28-drawing-prompts-now-reliably-open-and-submit-to-the-design-a.md +6 -0
  145. package/corpus/templates/design/changelog/2026-06-28-editor-app-menus-now-use-an-outline-agent-native-mark-with-b.md +6 -0
  146. package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +6 -0
  147. package/corpus/templates/design/changelog/2026-06-28-layer-selection-now-updates-chat-context-without-opening-the.md +6 -0
  148. package/corpus/templates/design/changelog/2026-06-28-layer-selections-now-preserve-hidden-and-locked-canvas-state.md +6 -0
  149. package/corpus/templates/design/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  150. package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +6 -0
  151. package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +6 -0
  152. package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-handles-zooming-drawing-opening-and-dele.md +6 -0
  153. package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-selects-screens-on-click-and-opens-them-.md +6 -0
  154. package/corpus/templates/design/changelog/2026-06-28-screen-overview-zooms-into-the-active-screen-with-smoother-e.md +6 -0
  155. package/corpus/templates/design/changelog/2026-06-28-selected-element-chips-in-chat-are-shorter-and-easier-to-sca.md +6 -0
  156. package/corpus/templates/design/changelog/2026-06-28-the-design-editor-toolbar-is-more-compact-and-the-app-menu-m.md +6 -0
  157. package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-at-the-top-of-the-design-sidebar-instead-of-.md +6 -0
  158. package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-in-the-right-inspector-beside-the-design-tab.md +6 -0
  159. package/corpus/templates/design/changelog/2026-06-29-active-sidebar-rows-use-soft-highlights.md +6 -0
  160. package/corpus/templates/design/changelog/2026-06-29-agents-can-now-open-screen-overview-focus-screens-and-add.md +6 -0
  161. package/corpus/templates/design/changelog/2026-06-29-design-agents-now-edit-broad-copy-changes-more-reliably.md +6 -0
  162. package/corpus/templates/design/changelog/2026-06-29-design-editor-extensions-now-run-inline-beside-the-artboard.md +6 -0
  163. package/corpus/templates/design/changelog/2026-06-29-sidebars-use-darker-chrome-and-chat-warns-immediately.md +6 -0
  164. package/corpus/templates/design/changelog/2026-06-29-visual-edit-can-open-localhost-routes-as-url-backed-screens.md +6 -0
  165. package/corpus/templates/design/package.json +1 -0
  166. package/corpus/templates/design/server/db/schema.ts +26 -0
  167. package/corpus/templates/design/server/lib/design-snapshot.ts +1 -1
  168. package/corpus/templates/design/server/plugins/agent-chat.ts +3 -0
  169. package/corpus/templates/design/shared/api.ts +27 -0
  170. package/corpus/templates/design/shared/canvas-frames.ts +103 -0
  171. package/corpus/templates/design/shared/canvas-math.ts +1058 -0
  172. package/corpus/templates/design/shared/code-layer.ts +2212 -0
  173. package/corpus/templates/design/shared/color-utils.ts +180 -0
  174. package/corpus/templates/design/shared/generation-session.ts +61 -0
  175. package/corpus/templates/design/shared/shader-presets.ts +782 -0
  176. package/corpus/templates/design/shared/shader-safety.ts +137 -0
  177. package/corpus/templates/design/shared/source-mode.ts +237 -0
  178. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +149 -6
  179. package/corpus/templates/forms/app/i18n/ar-SA.ts +2 -0
  180. package/corpus/templates/forms/app/i18n/de-DE.ts +2 -0
  181. package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
  182. package/corpus/templates/forms/app/i18n/es-ES.ts +2 -0
  183. package/corpus/templates/forms/app/i18n/fr-FR.ts +2 -0
  184. package/corpus/templates/forms/app/i18n/hi-IN.ts +2 -0
  185. package/corpus/templates/forms/app/i18n/ja-JP.ts +2 -0
  186. package/corpus/templates/forms/app/i18n/ko-KR.ts +2 -0
  187. package/corpus/templates/forms/app/i18n/pt-BR.ts +2 -0
  188. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  189. package/corpus/templates/forms/app/i18n/zh-TW.ts +2 -0
  190. package/corpus/templates/forms/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  191. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +2 -2
  192. package/corpus/templates/macros/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
  193. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +408 -247
  194. package/corpus/templates/mail/app/i18n/ar-SA.ts +4 -0
  195. package/corpus/templates/mail/app/i18n/de-DE.ts +4 -0
  196. package/corpus/templates/mail/app/i18n/en-US.ts +4 -0
  197. package/corpus/templates/mail/app/i18n/es-ES.ts +4 -0
  198. package/corpus/templates/mail/app/i18n/fr-FR.ts +4 -0
  199. package/corpus/templates/mail/app/i18n/hi-IN.ts +4 -0
  200. package/corpus/templates/mail/app/i18n/ja-JP.ts +4 -0
  201. package/corpus/templates/mail/app/i18n/ko-KR.ts +4 -0
  202. package/corpus/templates/mail/app/i18n/pt-BR.ts +4 -0
  203. package/corpus/templates/mail/app/i18n/zh-CN.ts +4 -0
  204. package/corpus/templates/mail/app/i18n/zh-TW.ts +4 -0
  205. package/corpus/templates/mail/changelog/2026-06-28-pinned-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  206. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +6 -8
  207. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +1 -1
  208. package/corpus/templates/plan/app/global.css +61 -78
  209. package/corpus/templates/plan/app/pages/PlansPage.tsx +8 -0
  210. package/corpus/templates/plan/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  211. package/corpus/templates/plan/changelog/2026-06-28-plans-use-the-shared-neutral-light-and-dark-theme.md +6 -0
  212. package/corpus/templates/plan/changelog/2026-06-28-sending-open-feedback-from-a-plan-now-opens-the-inline-plan-.md +6 -0
  213. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +5 -5
  214. package/corpus/templates/slides/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  215. package/corpus/templates/videos/app/components/Sidebar.tsx +2 -2
  216. package/corpus/templates/videos/app/components/layout/Layout.tsx +29 -2
  217. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +113 -30
  218. package/corpus/templates/videos/app/i18n/ar-SA.ts +2 -0
  219. package/corpus/templates/videos/app/i18n/de-DE.ts +2 -0
  220. package/corpus/templates/videos/app/i18n/en-US.ts +2 -0
  221. package/corpus/templates/videos/app/i18n/es-ES.ts +2 -0
  222. package/corpus/templates/videos/app/i18n/fr-FR.ts +2 -0
  223. package/corpus/templates/videos/app/i18n/hi-IN.ts +2 -0
  224. package/corpus/templates/videos/app/i18n/ja-JP.ts +2 -0
  225. package/corpus/templates/videos/app/i18n/ko-KR.ts +2 -0
  226. package/corpus/templates/videos/app/i18n/pt-BR.ts +2 -0
  227. package/corpus/templates/videos/app/i18n/zh-CN.ts +2 -0
  228. package/corpus/templates/videos/app/i18n/zh-TW.ts +2 -0
  229. package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  230. package/dist/agent/engine/index.d.ts +1 -1
  231. package/dist/agent/engine/index.d.ts.map +1 -1
  232. package/dist/agent/engine/index.js +1 -1
  233. package/dist/agent/engine/index.js.map +1 -1
  234. package/dist/agent/engine/registry.d.ts +9 -0
  235. package/dist/agent/engine/registry.d.ts.map +1 -1
  236. package/dist/agent/engine/registry.js +37 -0
  237. package/dist/agent/engine/registry.js.map +1 -1
  238. package/dist/agent/production-agent.d.ts.map +1 -1
  239. package/dist/agent/production-agent.js +4 -3
  240. package/dist/agent/production-agent.js.map +1 -1
  241. package/dist/cli/design-connect.d.ts +52 -0
  242. package/dist/cli/design-connect.d.ts.map +1 -0
  243. package/dist/cli/design-connect.js +409 -0
  244. package/dist/cli/design-connect.js.map +1 -0
  245. package/dist/cli/index.js +15 -0
  246. package/dist/cli/index.js.map +1 -1
  247. package/dist/cli/skills.d.ts +3 -0
  248. package/dist/cli/skills.d.ts.map +1 -1
  249. package/dist/cli/skills.js +121 -3
  250. package/dist/cli/skills.js.map +1 -1
  251. package/dist/client/AssistantChat.d.ts.map +1 -1
  252. package/dist/client/AssistantChat.js +38 -8
  253. package/dist/client/AssistantChat.js.map +1 -1
  254. package/dist/client/agent-chat.d.ts +6 -0
  255. package/dist/client/agent-chat.d.ts.map +1 -1
  256. package/dist/client/agent-chat.js +17 -3
  257. package/dist/client/agent-chat.js.map +1 -1
  258. package/dist/client/blocks/library/MermaidBlock.js +1 -1
  259. package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
  260. package/dist/client/blocks/library/diagram.js +1 -1
  261. package/dist/client/blocks/library/diagram.js.map +1 -1
  262. package/dist/client/blocks/library/wireframe.js +1 -1
  263. package/dist/client/blocks/library/wireframe.js.map +1 -1
  264. package/dist/client/chat/message-components.js +1 -1
  265. package/dist/client/chat/message-components.js.map +1 -1
  266. package/dist/client/chat-model-groups.d.ts.map +1 -1
  267. package/dist/client/chat-model-groups.js +1 -2
  268. package/dist/client/chat-model-groups.js.map +1 -1
  269. package/dist/client/components/LiveCursorOverlay.d.ts +1 -2
  270. package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
  271. package/dist/client/components/LiveCursorOverlay.js +19 -40
  272. package/dist/client/components/LiveCursorOverlay.js.map +1 -1
  273. package/dist/client/composer/TiptapComposer.d.ts +3 -1
  274. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  275. package/dist/client/composer/TiptapComposer.js +86 -24
  276. package/dist/client/composer/TiptapComposer.js.map +1 -1
  277. package/dist/client/composer/useVoiceDictation.d.ts +9 -0
  278. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  279. package/dist/client/composer/useVoiceDictation.js +154 -32
  280. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  281. package/dist/client/frame-protocol.d.ts +17 -2
  282. package/dist/client/frame-protocol.d.ts.map +1 -1
  283. package/dist/client/frame-protocol.js.map +1 -1
  284. package/dist/client/rich-markdown-editor/RegistryBlockNode.js +2 -2
  285. package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
  286. package/dist/client/sharing/ShareButton.d.ts +2 -0
  287. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  288. package/dist/client/sharing/ShareButton.js +7 -6
  289. package/dist/client/sharing/ShareButton.js.map +1 -1
  290. package/dist/client/use-agent-engine-configured.d.ts +5 -0
  291. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  292. package/dist/client/use-agent-engine-configured.js +51 -25
  293. package/dist/client/use-agent-engine-configured.js.map +1 -1
  294. package/dist/collab/awareness.d.ts +2 -2
  295. package/dist/collab/awareness.d.ts.map +1 -1
  296. package/dist/collab/routes.d.ts +1 -1
  297. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  298. package/dist/notifications/routes.d.ts +3 -3
  299. package/dist/observability/routes.d.ts +8 -8
  300. package/dist/progress/routes.d.ts +1 -1
  301. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  302. package/dist/server/transcribe-voice.d.ts.map +1 -1
  303. package/dist/server/transcribe-voice.js +40 -24
  304. package/dist/server/transcribe-voice.js.map +1 -1
  305. package/dist/shared/mcp-embed-headers.d.ts +1 -0
  306. package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
  307. package/dist/shared/mcp-embed-headers.js +20 -1
  308. package/dist/shared/mcp-embed-headers.js.map +1 -1
  309. package/dist/styles/agent-native.css +56 -7
  310. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  311. package/dist/vite/client.d.ts.map +1 -1
  312. package/dist/vite/client.js +2 -0
  313. package/dist/vite/client.js.map +1 -1
  314. package/dist/voice/index.d.ts +5 -0
  315. package/dist/voice/index.d.ts.map +1 -0
  316. package/dist/voice/index.js +4 -0
  317. package/dist/voice/index.js.map +1 -0
  318. package/dist/voice/voice-cleanup-prompt.d.ts +6 -0
  319. package/dist/voice/voice-cleanup-prompt.d.ts.map +1 -0
  320. package/dist/voice/voice-cleanup-prompt.js +26 -0
  321. package/dist/voice/voice-cleanup-prompt.js.map +1 -0
  322. package/dist/voice/voice-context.d.ts +25 -0
  323. package/dist/voice/voice-context.d.ts.map +1 -0
  324. package/dist/voice/voice-context.js +156 -0
  325. package/dist/voice/voice-context.js.map +1 -0
  326. package/dist/voice/voice-replacements.d.ts +4 -0
  327. package/dist/voice/voice-replacements.d.ts.map +1 -0
  328. package/dist/voice/voice-replacements.js +52 -0
  329. package/dist/voice/voice-replacements.js.map +1 -0
  330. package/docs/content/locales/ar-SA/template-design.mdx +41 -0
  331. package/docs/content/locales/de-DE/template-design.mdx +51 -0
  332. package/docs/content/locales/es-ES/template-design.mdx +50 -0
  333. package/docs/content/locales/fr-FR/template-design.mdx +49 -0
  334. package/docs/content/locales/hi-IN/template-design.mdx +44 -0
  335. package/docs/content/locales/ja-JP/template-design.mdx +46 -0
  336. package/docs/content/locales/ko-KR/template-design.mdx +44 -0
  337. package/docs/content/locales/pt-BR/template-design.mdx +48 -0
  338. package/docs/content/locales/zh-CN/template-design.mdx +36 -0
  339. package/docs/content/locales/zh-TW/template-design.mdx +38 -0
  340. package/docs/content/template-design.mdx +45 -0
  341. package/package.json +2 -1
  342. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  343. package/corpus/templates/design/app/components/design/DesignToolbar.tsx +0 -339
  344. package/corpus/templates/design/app/components/design/PresentMode.tsx +0 -68
  345. package/corpus/templates/design/app/components/design/ViewportTabs.tsx +0 -149
  346. package/corpus/templates/design/app/components/design/ZoomControls.tsx +0 -157
@@ -146,10 +146,6 @@
146
146
  display: none;
147
147
  }
148
148
 
149
- .dark .analytics-ask-page {
150
- background: hsl(var(--secondary) / 0.38);
151
- }
152
-
153
149
  .dark .analytics-ask-page .analytics-chat-panel {
154
150
  background: transparent;
155
151
  }
@@ -25,6 +25,8 @@ const messages = {
25
25
  created: "建立於 {{date}}",
26
26
  },
27
27
  sidebar: {
28
+ collapseSidebar: "收合側邊欄",
29
+ expandSidebar: "展開側邊欄",
28
30
  collapseDashboards: "收起儀表板",
29
31
  expandDashboards: "展開儀表板",
30
32
  collapseAnalyses: "收起分析",
@@ -35,6 +35,8 @@ const enUS = {
35
35
  recentSalesDescription: "You made 265 sales this month.",
36
36
  },
37
37
  sidebar: {
38
+ collapseSidebar: "Collapse sidebar",
39
+ expandSidebar: "Expand sidebar",
38
40
  collapseDashboards: "Collapse dashboards",
39
41
  expandDashboards: "Expand dashboards",
40
42
  collapseAnalyses: "Collapse analyses",
@@ -3406,6 +3408,8 @@ export const messagesByLocale = {
3406
3408
  created: "创建于 {{date}}",
3407
3409
  },
3408
3410
  sidebar: {
3411
+ collapseSidebar: "折叠侧边栏",
3412
+ expandSidebar: "展开侧边栏",
3409
3413
  collapseDashboards: "收起仪表板",
3410
3414
  expandDashboards: "展开仪表板",
3411
3415
  collapseAnalyses: "收起分析",
@@ -3580,6 +3584,8 @@ export const messagesByLocale = {
3580
3584
  created: "Creado el {{date}}",
3581
3585
  },
3582
3586
  sidebar: {
3587
+ collapseSidebar: "Contraer barra lateral",
3588
+ expandSidebar: "Expandir barra lateral",
3583
3589
  collapseDashboards: "Contraer paneles",
3584
3590
  expandDashboards: "Expandir paneles",
3585
3591
  collapseAnalyses: "Contraer análisis",
@@ -3762,6 +3768,8 @@ export const messagesByLocale = {
3762
3768
  created: "Créé le {{date}}",
3763
3769
  },
3764
3770
  sidebar: {
3771
+ collapseSidebar: "Réduire la barre latérale",
3772
+ expandSidebar: "Développer la barre latérale",
3765
3773
  collapseDashboards: "Réduire les tableaux de bord",
3766
3774
  expandDashboards: "Développer les tableaux de bord",
3767
3775
  collapseAnalyses: "Réduire les analyses",
@@ -3950,6 +3958,8 @@ export const messagesByLocale = {
3950
3958
  created: "Erstellt am {{date}}",
3951
3959
  },
3952
3960
  sidebar: {
3961
+ collapseSidebar: "Seitenleiste einklappen",
3962
+ expandSidebar: "Seitenleiste erweitern",
3953
3963
  collapseDashboards: "Dashboards einklappen",
3954
3964
  expandDashboards: "Dashboards ausklappen",
3955
3965
  collapseAnalyses: "Analysen einklappen",
@@ -4138,6 +4148,8 @@ export const messagesByLocale = {
4138
4148
  created: "{{date}} 作成",
4139
4149
  },
4140
4150
  sidebar: {
4151
+ collapseSidebar: "サイドバーを折りたたむ",
4152
+ expandSidebar: "サイドバーを展開",
4141
4153
  collapseDashboards: "ダッシュボードを折りたたむ",
4142
4154
  expandDashboards: "ダッシュボードを展開",
4143
4155
  collapseAnalyses: "分析を折りたたむ",
@@ -4322,6 +4334,8 @@ export const messagesByLocale = {
4322
4334
  created: "{{date}} 생성됨",
4323
4335
  },
4324
4336
  sidebar: {
4337
+ collapseSidebar: "사이드바 접기",
4338
+ expandSidebar: "사이드바 펼치기",
4325
4339
  collapseDashboards: "대시보드 접기",
4326
4340
  expandDashboards: "대시보드 펼치기",
4327
4341
  collapseAnalyses: "분석 접기",
@@ -4505,6 +4519,8 @@ export const messagesByLocale = {
4505
4519
  created: "Criado em {{date}}",
4506
4520
  },
4507
4521
  sidebar: {
4522
+ collapseSidebar: "Recolher barra lateral",
4523
+ expandSidebar: "Expandir barra lateral",
4508
4524
  collapseDashboards: "Recolher dashboards",
4509
4525
  expandDashboards: "Expandir dashboards",
4510
4526
  collapseAnalyses: "Recolher análises",
@@ -4693,6 +4709,8 @@ export const messagesByLocale = {
4693
4709
  created: "{{date}} को बनाया गया",
4694
4710
  },
4695
4711
  sidebar: {
4712
+ collapseSidebar: "साइडबार समेटें",
4713
+ expandSidebar: "साइडबार फैलाएं",
4696
4714
  collapseDashboards: "डैशबोर्ड समेटें",
4697
4715
  expandDashboards: "डैशबोर्ड फैलाएं",
4698
4716
  collapseAnalyses: "विश्लेषण समेटें",
@@ -4874,6 +4892,8 @@ export const messagesByLocale = {
4874
4892
  created: "تم الإنشاء في {{date}}",
4875
4893
  },
4876
4894
  sidebar: {
4895
+ collapseSidebar: "طي الشريط الجانبي",
4896
+ expandSidebar: "توسيع الشريط الجانبي",
4877
4897
  collapseDashboards: "طي لوحات المعلومات",
4878
4898
  expandDashboards: "توسيع لوحات المعلومات",
4879
4899
  collapseAnalyses: "طي التحليلات",
@@ -427,6 +427,7 @@ export default function SqlDashboardPage() {
427
427
  const navigate = useNavigate();
428
428
  const dashboardId = searchParams.get("id") || routeId;
429
429
  const reportScreenshot = searchParams.get("reportScreenshot") === "1";
430
+ const reportSettingsRequested = searchParams.get("reportSettings") === "1";
430
431
  const reportPanelLimit = reportScreenshot
431
432
  ? parseReportPanelLimit(searchParams.get("reportPanelLimit"))
432
433
  : null;
@@ -1033,6 +1034,28 @@ export default function SqlDashboardPage() {
1033
1034
  return out;
1034
1035
  }, [dashboard?.filters, searchParams]);
1035
1036
 
1037
+ useEffect(() => {
1038
+ if (!reportScreenshot && reportSettingsRequested) {
1039
+ setEmailReportOpen(true);
1040
+ }
1041
+ }, [reportScreenshot, reportSettingsRequested]);
1042
+
1043
+ const handleEmailReportOpenChange = useCallback(
1044
+ (open: boolean) => {
1045
+ setEmailReportOpen(open);
1046
+ if (open || !reportSettingsRequested) return;
1047
+ setSearchParams(
1048
+ (prev) => {
1049
+ const next = new URLSearchParams(prev);
1050
+ next.delete("reportSettings");
1051
+ return next;
1052
+ },
1053
+ { replace: true },
1054
+ );
1055
+ },
1056
+ [reportSettingsRequested, setSearchParams],
1057
+ );
1058
+
1036
1059
  // Distinct tab values across panels in declaration order. When this is
1037
1060
  // non-empty the dashboard renders a tab strip and filters panels by tab.
1038
1061
  const tabs = useMemo<string[]>(() => {
@@ -1453,7 +1476,7 @@ export default function SqlDashboardPage() {
1453
1476
  {dashboardId ? (
1454
1477
  <EmailReportDialog
1455
1478
  open={emailReportOpen}
1456
- onOpenChange={setEmailReportOpen}
1479
+ onOpenChange={handleEmailReportOpenChange}
1457
1480
  dashboardId={dashboardId}
1458
1481
  dashboardName={dashboard.name}
1459
1482
  filters={currentReportFilters}
@@ -1565,7 +1588,7 @@ export default function SqlDashboardPage() {
1565
1588
  placeholder={t("sqlDashboard.addDescriptionPlaceholder")}
1566
1589
  className="text-sm resize-y"
1567
1590
  />
1568
- ) : dashboard.description ? (
1591
+ ) : !reportScreenshot && dashboard.description ? (
1569
1592
  <button
1570
1593
  className={
1571
1594
  canEdit
@@ -1637,12 +1660,14 @@ export default function SqlDashboardPage() {
1637
1660
  )}
1638
1661
 
1639
1662
  {/* Filters */}
1640
- {dashboard.filters && dashboard.filters.length > 0 && (
1641
- <DashboardFilterBar
1642
- filters={dashboard.filters}
1643
- onSaveView={canEdit ? handleSaveView : undefined}
1644
- />
1645
- )}
1663
+ {!reportScreenshot &&
1664
+ dashboard.filters &&
1665
+ dashboard.filters.length > 0 && (
1666
+ <DashboardFilterBar
1667
+ filters={dashboard.filters}
1668
+ onSaveView={canEdit ? handleSaveView : undefined}
1669
+ />
1670
+ )}
1646
1671
 
1647
1672
  {/* Panels grid */}
1648
1673
  {dashboard.panels.length === 0 ? (
@@ -1269,6 +1269,8 @@ function visitorLabel(
1269
1269
  recording: SessionRecordingSummary,
1270
1270
  t: ReturnType<typeof useT>,
1271
1271
  ): string {
1272
+ const email = emailLike(recording.userId) || emailLike(recording.userKey);
1273
+ if (email) return email;
1272
1274
  return (
1273
1275
  recording.userId ||
1274
1276
  recording.userKey ||
@@ -1277,6 +1279,11 @@ function visitorLabel(
1277
1279
  );
1278
1280
  }
1279
1281
 
1282
+ function emailLike(value: string | null): string | null {
1283
+ if (!value?.includes("@")) return null;
1284
+ return value;
1285
+ }
1286
+
1280
1287
  function formatDuration(ms: number | null): string {
1281
1288
  if (!ms || !Number.isFinite(ms) || ms <= 0) return "0s";
1282
1289
  const seconds = Math.round(ms / 1000);
@@ -374,6 +374,8 @@ function visitorLabel(
374
374
  recording: SessionRecordingSummary,
375
375
  t: ReturnType<typeof useT>,
376
376
  ): string {
377
+ const email = emailLike(recording.userId) || emailLike(recording.userKey);
378
+ if (email) return email;
377
379
  return (
378
380
  recording.userId ||
379
381
  recording.userKey ||
@@ -382,6 +384,11 @@ function visitorLabel(
382
384
  );
383
385
  }
384
386
 
387
+ function emailLike(value: string | null): string | null {
388
+ if (!value?.includes("@")) return null;
389
+ return value;
390
+ }
391
+
385
392
  function shortId(value: string): string {
386
393
  return value.length > 22
387
394
  ? `${value.slice(0, 10)}...${value.slice(-8)}`
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-06-28
4
+ ---
5
+
6
+ The Ask tab now matches the darker background used across the rest of Analytics.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-06-28
4
+ ---
5
+
6
+ Dashboard email reports now use cleaner light-mode snapshots with direct subscription settings links.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-06-28
4
+ ---
5
+
6
+ The left sidebar now collapses into an animated icon rail with quieter footer controls.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-06-28
4
+ ---
5
+
6
+ Sessions now show only signed-in recordings with playable replay events.
@@ -267,7 +267,7 @@
267
267
  "chartType": "metric",
268
268
  "source": "first-party",
269
269
  "width": 1,
270
- "sql": "SELECT COUNT(*) AS count FROM session_recordings WHERE chunk_count > 0 AND ('{{timeRange}}' IN ('', 'all') OR ('{{timeRange}}' = '7d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '7 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '30d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '30 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '90d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '90 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '180d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '180 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '365d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '365 days', 'YYYY-MM-DD'))) AND ('{{emailFilter}}' IN ('', 'all') OR ('{{emailFilter}}' = 'exclude_builder' AND lower(coalesce(user_id, '')) NOT LIKE '%@builder.io') OR ('{{emailFilter}}' = 'only_builder' AND lower(coalesce(user_id, '')) LIKE '%@builder.io'))",
270
+ "sql": "SELECT COUNT(*) AS count FROM session_recordings WHERE chunk_count > 0 AND event_count > 0 AND COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')) IS NOT NULL AND ('{{timeRange}}' IN ('', 'all') OR ('{{timeRange}}' = '7d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '7 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '30d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '30 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '90d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '90 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '180d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '180 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '365d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '365 days', 'YYYY-MM-DD'))) AND ('{{emailFilter}}' IN ('', 'all') OR ('{{emailFilter}}' = 'exclude_builder' AND lower(coalesce(COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')), '')) NOT LIKE '%@builder.io') OR ('{{emailFilter}}' = 'only_builder' AND lower(coalesce(COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')), '')) LIKE '%@builder.io'))",
271
271
  "config": {
272
272
  "yKey": "count",
273
273
  "yFormatter": "number",
@@ -280,7 +280,7 @@
280
280
  "chartType": "area",
281
281
  "source": "first-party",
282
282
  "width": 1,
283
- "sql": "SELECT substr(started_at, 1, 10) AS date, SUM(chunk_count) AS count FROM session_recordings WHERE chunk_count > 0 AND ('{{timeRange}}' IN ('', 'all') OR ('{{timeRange}}' = '7d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '7 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '30d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '30 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '90d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '90 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '180d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '180 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '365d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '365 days', 'YYYY-MM-DD'))) AND ('{{emailFilter}}' IN ('', 'all') OR ('{{emailFilter}}' = 'exclude_builder' AND lower(coalesce(user_id, '')) NOT LIKE '%@builder.io') OR ('{{emailFilter}}' = 'only_builder' AND lower(coalesce(user_id, '')) LIKE '%@builder.io')) GROUP BY substr(started_at, 1, 10) ORDER BY date",
283
+ "sql": "SELECT substr(started_at, 1, 10) AS date, SUM(chunk_count) AS count FROM session_recordings WHERE chunk_count > 0 AND event_count > 0 AND COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')) IS NOT NULL AND ('{{timeRange}}' IN ('', 'all') OR ('{{timeRange}}' = '7d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '7 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '30d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '30 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '90d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '90 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '180d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '180 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '365d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '365 days', 'YYYY-MM-DD'))) AND ('{{emailFilter}}' IN ('', 'all') OR ('{{emailFilter}}' = 'exclude_builder' AND lower(coalesce(COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')), '')) NOT LIKE '%@builder.io') OR ('{{emailFilter}}' = 'only_builder' AND lower(coalesce(COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')), '')) LIKE '%@builder.io')) GROUP BY substr(started_at, 1, 10) ORDER BY date",
284
284
  "config": {
285
285
  "xKey": "date",
286
286
  "yKey": "count",
@@ -295,7 +295,7 @@
295
295
  "chartType": "table",
296
296
  "source": "first-party",
297
297
  "width": 2,
298
- "sql": "SELECT id AS recording_id, session_id, COALESCE(NULLIF(app, ''), NULLIF(template, ''), 'unknown') AS app, COALESCE(NULLIF(user_id, ''), NULLIF(user_key, ''), NULLIF(anonymous_id, ''), 'anonymous') AS visitor, chunk_count AS chunks, event_count AS events, started_at, COALESCE(ended_at, last_ingested_at, started_at) AS last_seen, '/sessions/' || id AS href FROM session_recordings WHERE chunk_count > 0 AND ('{{timeRange}}' IN ('', 'all') OR ('{{timeRange}}' = '7d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '7 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '30d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '30 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '90d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '90 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '180d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '180 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '365d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '365 days', 'YYYY-MM-DD'))) AND ('{{emailFilter}}' IN ('', 'all') OR ('{{emailFilter}}' = 'exclude_builder' AND lower(coalesce(user_id, '')) NOT LIKE '%@builder.io') OR ('{{emailFilter}}' = 'only_builder' AND lower(coalesce(user_id, '')) LIKE '%@builder.io')) ORDER BY last_seen DESC LIMIT 25",
298
+ "sql": "SELECT id AS recording_id, session_id, COALESCE(NULLIF(app, ''), NULLIF(template, ''), 'unknown') AS app, COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')) AS visitor, chunk_count AS chunks, event_count AS events, started_at, COALESCE(ended_at, last_ingested_at, started_at) AS last_seen, '/sessions/' || id AS href FROM session_recordings WHERE chunk_count > 0 AND event_count > 0 AND COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')) IS NOT NULL AND ('{{timeRange}}' IN ('', 'all') OR ('{{timeRange}}' = '7d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '7 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '30d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '30 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '90d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '90 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '180d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '180 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '365d' AND substr(started_at, 1, 10) >= to_char(CURRENT_DATE - INTERVAL '365 days', 'YYYY-MM-DD'))) AND ('{{emailFilter}}' IN ('', 'all') OR ('{{emailFilter}}' = 'exclude_builder' AND lower(coalesce(COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')), '')) NOT LIKE '%@builder.io') OR ('{{emailFilter}}' = 'only_builder' AND lower(coalesce(COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, '')), '')) LIKE '%@builder.io')) ORDER BY last_seen DESC LIMIT 25",
299
299
  "config": {
300
300
  "description": "Recent first-party session recordings. Session links open the local replay viewer.",
301
301
  "sortable": true,
@@ -27,6 +27,7 @@ type ReportSnapshot = {
27
27
  description?: string;
28
28
  filters: Record<string, string>;
29
29
  dashboardUrl: string;
30
+ reportSettingsUrl: string;
30
31
  generatedAt: string;
31
32
  };
32
33
 
@@ -39,6 +40,7 @@ const DEFAULT_SERVERLESS_CHROMIUM_PACK_URL =
39
40
  "https://github.com/Sparticuz/chromium/releases/download/v149.0.0/chromium-v149.0.0-pack.x64.tar";
40
41
  const DASHBOARD_REPORT_SCREENSHOT_PARAM = "reportScreenshot";
41
42
  const DASHBOARD_REPORT_PANEL_LIMIT_PARAM = "reportPanelLimit";
43
+ const DASHBOARD_REPORT_SETTINGS_PARAM = "reportSettings";
42
44
  const DASHBOARD_REPORT_CID = "dashboard-report-snapshot";
43
45
  const COMPACT_REPORT_PANEL_LIMIT = 12;
44
46
  const LOCAL_SCREENSHOT_TIMEOUT_MS = 90_000;
@@ -114,7 +116,11 @@ function dashboardBaseUrl(): string {
114
116
  function buildDashboardPath(
115
117
  dashboardId: string,
116
118
  filters: Record<string, string>,
117
- options?: { reportScreenshot?: boolean; panelLimit?: number },
119
+ options?: {
120
+ reportScreenshot?: boolean;
121
+ reportSettings?: boolean;
122
+ panelLimit?: number;
123
+ },
118
124
  ): string {
119
125
  const url = new URL(
120
126
  `/dashboards/${encodeURIComponent(dashboardId)}`,
@@ -126,6 +132,9 @@ function buildDashboardPath(
126
132
  if (options?.reportScreenshot) {
127
133
  url.searchParams.set(DASHBOARD_REPORT_SCREENSHOT_PARAM, "1");
128
134
  }
135
+ if (options?.reportSettings) {
136
+ url.searchParams.set(DASHBOARD_REPORT_SETTINGS_PARAM, "1");
137
+ }
129
138
  if (options?.panelLimit && options.panelLimit > 0) {
130
139
  url.searchParams.set(
131
140
  DASHBOARD_REPORT_PANEL_LIMIT_PARAM,
@@ -138,7 +147,11 @@ function buildDashboardPath(
138
147
  function buildDashboardUrl(
139
148
  dashboardId: string,
140
149
  filters: Record<string, string>,
141
- options?: { reportScreenshot?: boolean; panelLimit?: number },
150
+ options?: {
151
+ reportScreenshot?: boolean;
152
+ reportSettings?: boolean;
153
+ panelLimit?: number;
154
+ },
142
155
  ): string {
143
156
  const path = buildDashboardPath(dashboardId, filters, options);
144
157
  const url = new URL(path, `${dashboardBaseUrl()}/`);
@@ -178,6 +191,9 @@ async function collectReportSnapshot(
178
191
  description: config.description,
179
192
  filters,
180
193
  dashboardUrl: buildDashboardUrl(sub.dashboardId, filters),
194
+ reportSettingsUrl: buildDashboardUrl(sub.dashboardId, filters, {
195
+ reportSettings: true,
196
+ }),
181
197
  generatedAt: new Date().toISOString(),
182
198
  };
183
199
  }
@@ -335,7 +351,10 @@ async function captureDashboardPng(
335
351
  deviceScaleFactor: 1,
336
352
  });
337
353
  page.setDefaultTimeout(timeout);
338
- await page.emulateMedia({ media: "screen" });
354
+ await page.emulateMedia({ media: "screen", colorScheme: "light" });
355
+ await page.addInitScript(() => {
356
+ window.localStorage.setItem("theme", "light");
357
+ });
339
358
  await page.goto(screenshotUrl.toString(), {
340
359
  waitUntil: "domcontentloaded",
341
360
  timeout,
@@ -423,10 +442,8 @@ function renderReportEmailHtml(
423
442
  ): string {
424
443
  const title = escapeHtml(snapshot.title);
425
444
  const dashboardUrl = escapeHtml(snapshot.dashboardUrl);
445
+ const reportSettingsUrl = escapeHtml(snapshot.reportSettingsUrl);
426
446
  const date = escapeHtml(reportDate(snapshot));
427
- const description = snapshot.description
428
- ? `<p style="margin:8px 0 18px;color:#525866;font-size:14px;line-height:1.5;">${escapeHtml(snapshot.description)}</p>`
429
- : "";
430
447
  const screenshotBlock = options.screenshotAttached
431
448
  ? `<a href="${dashboardUrl}" style="display:block;text-decoration:none;">
432
449
  <img src="cid:${DASHBOARD_REPORT_CID}" alt="${title}" width="100%" style="display:block;width:100%;max-width:1280px;height:auto;border:1px solid #e5e7eb;border-radius:8px;" />
@@ -441,10 +458,14 @@ function renderReportEmailHtml(
441
458
  <h3 style="margin:0 0 8px;font-size:18px;line-height:1.35;font-weight:600;">
442
459
  Here's the report of <a href="${dashboardUrl}" style="color:#2563eb;text-decoration:none;">${title}</a> for ${date}.
443
460
  </h3>
444
- ${description}
445
461
  ${screenshotBlock}
446
462
  <p style="margin:18px 0 0;color:#525866;font-size:13px;line-height:1.45;">
447
463
  <a href="${dashboardUrl}" style="color:#2563eb;text-decoration:none;">Open dashboard</a>
464
+ <span style="color:#9ca3af;"> · </span>
465
+ <a href="${reportSettingsUrl}" style="color:#2563eb;text-decoration:none;">Edit subscription settings</a>
466
+ </p>
467
+ <p style="margin:6px 0 0;color:#6b7280;font-size:12px;line-height:1.45;">
468
+ Change recipients, delivery time, filters, or turn this report on/off.
448
469
  </p>
449
470
  </body>
450
471
  </html>`;
@@ -458,6 +479,7 @@ function renderReportText(
458
479
  `Daily dashboard report: ${snapshot.title}`,
459
480
  `Date: ${reportDate(snapshot)}`,
460
481
  `Open dashboard: ${snapshot.dashboardUrl}`,
482
+ `Edit subscription settings: ${snapshot.reportSettingsUrl}`,
461
483
  ];
462
484
  if (!options.screenshotAttached) {
463
485
  lines.push("Dashboard image unavailable for this run.");
@@ -166,10 +166,13 @@ const REPLAY_RECORDING_DATE_SQL = "substr(started_at, 1, 10)";
166
166
  const REPLAY_TIME_RANGE_FILTER = dashboardTimeRangeFilter(
167
167
  REPLAY_RECORDING_DATE_SQL,
168
168
  );
169
- const REPLAY_RECORDING_FILTER = `chunk_count > 0 AND event_count > 0 AND user_id LIKE '%@%' AND ${REPLAY_TIME_RANGE_FILTER} AND ${DASHBOARD_EMAIL_FILTER}`;
169
+ const REPLAY_VISITOR_EMAIL_SQL =
170
+ "COALESCE(NULLIF(CASE WHEN lower(coalesce(user_id, '')) LIKE '%@%' THEN user_id ELSE '' END, ''), NULLIF(CASE WHEN lower(coalesce(user_key, '')) LIKE '%@%' THEN user_key ELSE '' END, ''))";
171
+ const REPLAY_EMAIL_FILTER = `('{{emailFilter}}' IN ('', 'all') OR ('{{emailFilter}}' = 'exclude_builder' AND lower(coalesce(${REPLAY_VISITOR_EMAIL_SQL}, '')) NOT LIKE '%@builder.io') OR ('{{emailFilter}}' = 'only_builder' AND lower(coalesce(${REPLAY_VISITOR_EMAIL_SQL}, '')) LIKE '%@builder.io'))`;
172
+ const REPLAY_RECORDING_FILTER = `chunk_count > 0 AND event_count > 0 AND ${REPLAY_VISITOR_EMAIL_SQL} IS NOT NULL AND ${REPLAY_TIME_RANGE_FILTER} AND ${REPLAY_EMAIL_FILTER}`;
170
173
  const REPLAY_SESSIONS_SQL = `SELECT COUNT(*) AS count FROM session_recordings WHERE ${REPLAY_RECORDING_FILTER}`;
171
174
  const REPLAY_CHUNKS_OVER_TIME_SQL = `SELECT ${REPLAY_RECORDING_DATE_SQL} AS date, SUM(chunk_count) AS count FROM session_recordings WHERE ${REPLAY_RECORDING_FILTER} GROUP BY ${REPLAY_RECORDING_DATE_SQL} ORDER BY date`;
172
- const RECENT_REPLAY_SESSIONS_SQL = `SELECT id AS recording_id, session_id, COALESCE(NULLIF(app, ''), NULLIF(template, ''), 'unknown') AS app, COALESCE(NULLIF(user_id, ''), NULLIF(user_key, ''), NULLIF(anonymous_id, ''), 'anonymous') AS visitor, chunk_count AS chunks, event_count AS events, started_at, COALESCE(ended_at, last_ingested_at, started_at) AS last_seen, '/sessions/' || id AS href FROM session_recordings WHERE ${REPLAY_RECORDING_FILTER} ORDER BY last_seen DESC LIMIT 25`;
175
+ const RECENT_REPLAY_SESSIONS_SQL = `SELECT id AS recording_id, session_id, COALESCE(NULLIF(app, ''), NULLIF(template, ''), 'unknown') AS app, ${REPLAY_VISITOR_EMAIL_SQL} AS visitor, chunk_count AS chunks, event_count AS events, started_at, COALESCE(ended_at, last_ingested_at, started_at) AS last_seen, '/sessions/' || id AS href FROM session_recordings WHERE ${REPLAY_RECORDING_FILTER} ORDER BY last_seen DESC LIMIT 25`;
173
176
  export const FIRST_PARTY_DASHBOARD_FILTERS: FirstPartyDashboardFilter[] = [
174
177
  {
175
178
  id: "timeRange",
@@ -988,11 +988,18 @@ function rowToSessionRecordingSummary(
988
988
  }
989
989
 
990
990
  function hasVisibleSessionRecordingIdentity(row: any): boolean {
991
- return Boolean(replayEmail(row.userId) || replayString(row.anonymousId));
991
+ return Boolean(replayEmail(row.userId) || replayEmail(row.userKey));
992
+ }
993
+
994
+ function hasPlayableSessionRecordingEvents(row: any): boolean {
995
+ return Number(row.chunkCount ?? 0) > 0 && Number(row.eventCount ?? 0) > 0;
992
996
  }
993
997
 
994
998
  function isVisibleSessionRecording(row: any): boolean {
995
- return hasVisibleSessionRecordingIdentity(row);
999
+ return (
1000
+ hasVisibleSessionRecordingIdentity(row) &&
1001
+ hasPlayableSessionRecordingEvents(row)
1002
+ );
996
1003
  }
997
1004
 
998
1005
  function mergeReplayMetadata(
@@ -1045,7 +1052,14 @@ function replayTextContains(column: unknown, query: string) {
1045
1052
  function replayVisibleIdentityCondition() {
1046
1053
  return or(
1047
1054
  replayTextContains(schema.sessionRecordings.userId, "@"),
1048
- sql`nullif(trim(coalesce(${schema.sessionRecordings.anonymousId}, '')), '') is not null`,
1055
+ replayTextContains(schema.sessionRecordings.userKey, "@"),
1056
+ );
1057
+ }
1058
+
1059
+ function replayPlayableEventsCondition() {
1060
+ return and(
1061
+ gte(schema.sessionRecordings.chunkCount, 1),
1062
+ gte(schema.sessionRecordings.eventCount, 1),
1049
1063
  );
1050
1064
  }
1051
1065
 
@@ -1353,6 +1367,7 @@ export async function listSessionRecordings(
1353
1367
  orgId: scope.orgId ?? undefined,
1354
1368
  }),
1355
1369
  replayVisibleIdentityCondition(),
1370
+ replayPlayableEventsCondition(),
1356
1371
  ];
1357
1372
  if (filters.app)
1358
1373
  conditions.push(eq(schema.sessionRecordings.app, filters.app));
@@ -1363,7 +1378,12 @@ export async function listSessionRecordings(
1363
1378
  conditions.push(eq(schema.sessionRecordings.sessionId, filters.sessionId));
1364
1379
  }
1365
1380
  if (filters.userId) {
1366
- conditions.push(eq(schema.sessionRecordings.userId, filters.userId));
1381
+ conditions.push(
1382
+ or(
1383
+ eq(schema.sessionRecordings.userId, filters.userId),
1384
+ eq(schema.sessionRecordings.userKey, filters.userId),
1385
+ ),
1386
+ );
1367
1387
  }
1368
1388
  if (filters.anonymousId) {
1369
1389
  conditions.push(
@@ -425,7 +425,7 @@ export function Sidebar() {
425
425
  return (
426
426
  <aside
427
427
  className={cn(
428
- "flex h-full min-w-0 shrink-0 flex-col overflow-hidden border-e border-border bg-sidebar text-sidebar-foreground",
428
+ "flex h-full min-w-0 shrink-0 flex-col overflow-hidden border-e border-border bg-sidebar text-sidebar-foreground transition-[width] duration-200 ease-out",
429
429
  collapsed ? "w-14" : "w-56",
430
430
  )}
431
431
  >
@@ -553,15 +553,15 @@ export function Sidebar() {
553
553
 
554
554
  {!collapsed && (
555
555
  <div className="mt-auto shrink-0">
556
- <div className="border-t border-border px-2 py-1">
556
+ <div className="px-2 py-1">
557
557
  <ExtensionsSidebarSection />
558
558
  </div>
559
559
 
560
- <div className="border-t border-border px-3 py-2">
560
+ <div className="px-3 py-2">
561
561
  <OrgSwitcher />
562
562
  </div>
563
563
 
564
- <div className="border-t border-border px-3 py-2">
564
+ <div className="px-3 py-2">
565
565
  <DevDatabaseLink />
566
566
  <FeedbackButton />
567
567
  </div>
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-06-28
4
+ ---
5
+
6
+ Left sidebar collapse motion and footer controls now feel smoother and use less divider chrome.
@@ -20,11 +20,24 @@ import {
20
20
  } from "@/components/ui/sheet";
21
21
  import { TAB_ID } from "@/lib/tab-id";
22
22
 
23
+ const SIDEBAR_COLLAPSE_KEY = "brain.sidebar.collapsed";
24
+
25
+ function readSidebarCollapsed() {
26
+ if (typeof window === "undefined") return false;
27
+ try {
28
+ return window.localStorage.getItem(SIDEBAR_COLLAPSE_KEY) === "1";
29
+ } catch {
30
+ return false;
31
+ }
32
+ }
33
+
23
34
  export function Layout({ children }: { children: React.ReactNode }) {
24
35
  const location = useLocation();
25
36
  const navigate = useNavigate();
26
37
  const t = useT();
27
38
  const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
39
+ const [sidebarCollapsed, setSidebarCollapsed] =
40
+ useState(readSidebarCollapsed);
28
41
  const isAskRoute = location.pathname === "/";
29
42
  const chatHomeHandoffActive = useAgentChatHomeHandoff({
30
43
  storageKey: "brain",
@@ -37,10 +50,24 @@ export function Layout({ children }: { children: React.ReactNode }) {
37
50
  setMobileSidebarOpen(false);
38
51
  }, [location.pathname]);
39
52
 
53
+ useEffect(() => {
54
+ try {
55
+ window.localStorage.setItem(
56
+ SIDEBAR_COLLAPSE_KEY,
57
+ sidebarCollapsed ? "1" : "0",
58
+ );
59
+ } catch {
60
+ // Ignore storage failures; the in-memory preference still works.
61
+ }
62
+ }, [sidebarCollapsed]);
63
+
40
64
  const sidebarFrame = (
41
65
  <>
42
66
  <div className="agent-layout-left-drawer hidden md:block">
43
- <Sidebar />
67
+ <Sidebar
68
+ collapsed={sidebarCollapsed}
69
+ onCollapsedChange={setSidebarCollapsed}
70
+ />
44
71
  </div>
45
72
  <Sheet open={mobileSidebarOpen} onOpenChange={setMobileSidebarOpen}>
46
73
  <SheetContent side="left" className="w-[min(18rem,88vw)] p-0">
@@ -50,7 +77,7 @@ export function Layout({ children }: { children: React.ReactNode }) {
50
77
  <SheetDescription className="sr-only">
51
78
  {t("navigation.brainNavigationDescription")}
52
79
  </SheetDescription>
53
- <Sidebar />
80
+ <Sidebar collapsed={false} collapsible={false} />
54
81
  </SheetContent>
55
82
  </Sheet>
56
83
  </>