@agent-native/core 0.103.0 → 0.104.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 (572) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +36 -0
  3. package/corpus/core/package.json +9 -2
  4. package/corpus/core/src/agent/engine/credential-errors.ts +2 -2
  5. package/corpus/core/src/agent/production-agent.ts +30 -0
  6. package/corpus/core/src/agent/run-store.ts +12 -2
  7. package/corpus/core/src/cli/create.ts +1 -0
  8. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +30 -11
  9. package/corpus/core/src/cli/templates-meta.ts +4 -3
  10. package/corpus/core/src/client/AgentAskPopover.tsx +89 -0
  11. package/corpus/core/src/client/AgentChatHome.tsx +4 -0
  12. package/corpus/core/src/client/AgentPanel.tsx +321 -223
  13. package/corpus/core/src/client/AssistantChat.tsx +6 -10
  14. package/corpus/core/src/client/MultiTabAssistantChat.tsx +53 -372
  15. package/corpus/core/src/client/agent-chat-adapter.ts +13 -1
  16. package/corpus/core/src/client/agent-page/AgentContextTab.tsx +133 -149
  17. package/corpus/core/src/client/agent-page/AgentEmptyState.tsx +44 -0
  18. package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +153 -82
  19. package/corpus/core/src/client/agent-page/AgentTabFrame.tsx +39 -0
  20. package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +368 -356
  21. package/corpus/core/src/client/agent-page/types.ts +1 -1
  22. package/corpus/core/src/client/analytics.ts +51 -5
  23. package/corpus/core/src/client/chat/run-recovery.tsx +12 -4
  24. package/corpus/core/src/client/composer/PromptComposer.tsx +5 -15
  25. package/corpus/core/src/client/composer/TiptapComposer.tsx +32 -3
  26. package/corpus/core/src/client/dynamic-suggestions.ts +3 -3
  27. package/corpus/core/src/client/index.ts +16 -1
  28. package/corpus/core/src/client/resources/ResourceTree.tsx +249 -38
  29. package/corpus/core/src/client/resources/ResourcesPanel.tsx +307 -140
  30. package/corpus/core/src/client/session-replay.ts +158 -5
  31. package/corpus/core/src/client/settings/AutomationsSection.tsx +30 -10
  32. package/corpus/core/src/client/settings/SettingsPanel.tsx +3 -2
  33. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +2 -0
  34. package/corpus/core/src/client/settings/agent-settings-search.ts +2 -2
  35. package/corpus/core/src/client/use-chat-threads.ts +2 -0
  36. package/corpus/core/src/connections/catalog.ts +49 -7
  37. package/corpus/core/src/db/index.ts +6 -1
  38. package/corpus/core/src/extensions/actions.ts +106 -16
  39. package/corpus/core/src/extensions/content-patch.ts +22 -0
  40. package/corpus/core/src/extensions/routes.ts +18 -0
  41. package/corpus/core/src/extensions/store.ts +8 -0
  42. package/corpus/core/src/index.ts +3 -0
  43. package/corpus/core/src/ingestion/docx.ts +158 -0
  44. package/corpus/core/src/ingestion/figma-node-to-html.ts +1860 -0
  45. package/corpus/core/src/ingestion/figma.ts +548 -0
  46. package/corpus/core/src/ingestion/index.ts +107 -0
  47. package/corpus/core/src/ingestion/media.ts +264 -0
  48. package/corpus/core/src/ingestion/notion.ts +121 -0
  49. package/corpus/core/src/ingestion/office.ts +214 -0
  50. package/corpus/core/src/ingestion/orchestration.ts +160 -0
  51. package/corpus/core/src/ingestion/pptx.ts +333 -0
  52. package/corpus/core/src/ingestion/selection.ts +81 -0
  53. package/corpus/core/src/ingestion/website.ts +151 -0
  54. package/corpus/core/src/integrations/plugin.ts +45 -37
  55. package/corpus/core/src/localization/default-messages.ts +35 -12
  56. package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
  57. package/corpus/core/src/observability/traces.ts +5 -3
  58. package/corpus/core/src/provider-api/index.ts +452 -8
  59. package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +18 -1
  60. package/corpus/core/src/search-utils/index.ts +112 -0
  61. package/corpus/core/src/secrets/register-framework-secrets.ts +61 -0
  62. package/corpus/core/src/server/action-discovery.ts +33 -8
  63. package/corpus/core/src/server/agent-chat/framework-prompts.ts +2 -2
  64. package/corpus/core/src/server/agent-chat/prompt-resources.ts +144 -0
  65. package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
  66. package/corpus/core/src/server/core-routes-plugin.ts +12 -0
  67. package/corpus/core/src/server/index.ts +30 -0
  68. package/corpus/core/src/server/workspace-provider-oauth.ts +583 -0
  69. package/corpus/core/src/styles/agent-native.css +9 -0
  70. package/corpus/core/src/templates/default/app/i18n/en-US.ts +3 -3
  71. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
  72. package/corpus/core/src/templates/workspace-root/.env.example +12 -0
  73. package/corpus/core/src/vite/client.ts +2 -0
  74. package/corpus/core/src/workspace-connections/index.ts +6 -0
  75. package/corpus/core/src/workspace-connections/lifecycle.ts +43 -0
  76. package/corpus/core/src/workspace-connections/store.ts +16 -0
  77. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +46 -3
  78. package/corpus/templates/analytics/AGENTS.md +9 -0
  79. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +120 -6
  80. package/corpus/templates/analytics/actions/mutate-dashboard.ts +92 -30
  81. package/corpus/templates/analytics/actions/update-dashboard.ts +5 -5
  82. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +313 -220
  83. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +2 -2
  84. package/corpus/templates/analytics/app/components/layout/Layout.tsx +9 -6
  85. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +90 -64
  86. package/corpus/templates/analytics/app/i18n-data.ts +3 -3
  87. package/corpus/templates/analytics/app/lib/dashboard-list-loading.ts +25 -0
  88. package/corpus/templates/analytics/app/lib/item-popularity.ts +13 -4
  89. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +1 -1
  90. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/pivot.ts +8 -3
  91. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +1 -0
  92. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +15 -3
  93. package/corpus/templates/analytics/changelog/2026-07-16-dashboard-filter-defaults-can-now-be-changed-reliably-withou.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-16-dashboard-lists-load-in-one-stable-order-without-popping-bet.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-07-16-fixed-dashboard-filter-dropdown-text-alignment.md +6 -0
  96. package/corpus/templates/analytics/changelog/2026-07-16-recurring-signed-in-users-can-now-be-viewed-as-weekly-bars-b.md +6 -0
  97. package/corpus/templates/analytics/changelog/2026-07-16-the-analytics-agent-can-now-duplicate-a-chart-and-place-the-.md +6 -0
  98. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +41 -1
  99. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +1 -1
  100. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +47 -1
  101. package/corpus/templates/analytics/server/lib/session-replay.ts +68 -0
  102. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -0
  103. package/corpus/templates/analytics/server/routes/sessions/lookup.get.ts +47 -0
  104. package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +16 -9
  105. package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +86 -0
  106. package/corpus/templates/assets/AGENTS.md +10 -0
  107. package/corpus/templates/assets/actions/create-generation-session.ts +59 -1
  108. package/corpus/templates/assets/actions/edit-image.ts +2 -0
  109. package/corpus/templates/assets/actions/generate-asset.ts +52 -0
  110. package/corpus/templates/assets/actions/generate-image-batch.ts +55 -0
  111. package/corpus/templates/assets/actions/generate-image.ts +219 -1
  112. package/corpus/templates/assets/actions/open-asset-picker.ts +14 -0
  113. package/corpus/templates/assets/actions/refine-image.ts +3 -0
  114. package/corpus/templates/assets/actions/restyle-image.ts +2 -0
  115. package/corpus/templates/assets/agent-native.app-skill.json +4 -0
  116. package/corpus/templates/assets/app/components/layout/Layout.tsx +2 -0
  117. package/corpus/templates/assets/app/i18n/zh-TW.ts +3 -0
  118. package/corpus/templates/assets/app/i18n-data.ts +29 -13
  119. package/corpus/templates/assets/app/routes/agent.tsx +7 -1
  120. package/corpus/templates/assets/app/routes/library.tsx +9 -0
  121. package/corpus/templates/assets/app/routes/settings.tsx +3 -0
  122. package/corpus/templates/assets/changelog/2026-07-16-creative-context-library.md +6 -0
  123. package/corpus/templates/assets/package.json +1 -0
  124. package/corpus/templates/assets/server/lib/image-processing.ts +1 -22
  125. package/corpus/templates/assets/server/plugins/creative-context.ts +205 -0
  126. package/corpus/templates/brain/app/i18n-data.ts +3 -3
  127. package/corpus/templates/brain/app/lib/brain.ts +1 -1
  128. package/corpus/templates/brain/server/lib/search.ts +17 -67
  129. package/corpus/templates/calendar/app/i18n-data.ts +3 -3
  130. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +19 -18
  131. package/corpus/templates/chat/app/i18n/en-US.ts +3 -3
  132. package/corpus/templates/chat/app/lib/agent-page.tsx +10 -1
  133. package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +1 -1
  134. package/corpus/templates/clips/AGENTS.md +4 -0
  135. package/corpus/templates/clips/actions/cleanup-transcript.ts +35 -4
  136. package/corpus/templates/clips/actions/create-meeting.ts +6 -2
  137. package/corpus/templates/clips/actions/create-organization.ts +3 -2
  138. package/corpus/templates/clips/actions/create-recording.ts +4 -1
  139. package/corpus/templates/clips/actions/finalize-recording.ts +44 -7
  140. package/corpus/templates/clips/actions/import-loom-recording.ts +4 -1
  141. package/corpus/templates/clips/actions/lib/create-recording-schema.ts +2 -2
  142. package/corpus/templates/clips/actions/list-meetings.ts +23 -5
  143. package/corpus/templates/clips/actions/list-organization-state.ts +1 -1
  144. package/corpus/templates/clips/actions/remove-silences.ts +10 -1
  145. package/corpus/templates/clips/actions/request-transcript.ts +53 -11
  146. package/corpus/templates/clips/actions/search-recordings-utils.ts +7 -0
  147. package/corpus/templates/clips/actions/search-recordings.ts +5 -8
  148. package/corpus/templates/clips/actions/set-organization-branding.ts +2 -2
  149. package/corpus/templates/clips/actions/stitch-recordings.ts +10 -5
  150. package/corpus/templates/clips/actions/update-ai-request-status.ts +38 -0
  151. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +3 -4
  152. package/corpus/templates/clips/app/components/editor/editor-selection.ts +19 -0
  153. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +10 -10
  154. package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +1 -2
  155. package/corpus/templates/clips/app/components/library/library-grid.tsx +101 -93
  156. package/corpus/templates/clips/app/components/player/video-player.tsx +11 -0
  157. package/corpus/templates/clips/app/components/workspace/branding-editor.tsx +53 -1
  158. package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
  159. package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
  160. package/corpus/templates/clips/app/i18n/en-US.ts +10 -4
  161. package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
  162. package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
  163. package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
  164. package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
  165. package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
  166. package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
  167. package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -1
  168. package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -1
  169. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +5 -9
  170. package/corpus/templates/clips/app/routes/_app.settings.organization.tsx +6 -2
  171. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +129 -27
  172. package/corpus/templates/clips/app/routes/record.tsx +23 -2
  173. package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -2
  174. package/corpus/templates/clips/changelog/2026-07-16-authorized-viewers-can-open-shared-private-clips-without-a-m.md +6 -0
  175. package/corpus/templates/clips/changelog/2026-07-16-camera-bubble-hover-controls-appear-above-the-face.md +6 -0
  176. package/corpus/templates/clips/changelog/2026-07-16-chrome-extension-recovers-stale-recorder-state.md +6 -0
  177. package/corpus/templates/clips/changelog/2026-07-16-clips-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
  178. package/corpus/templates/clips/changelog/2026-07-16-clips-search-now-matches-recording-content-without-requiring.md +6 -0
  179. package/corpus/templates/clips/changelog/2026-07-16-declined-meetings-no-longer-show-desktop-reminders.md +6 -0
  180. package/corpus/templates/clips/changelog/2026-07-16-failed-desktop-saves-now-show-their-local-recovery-copy.md +6 -0
  181. package/corpus/templates/clips/changelog/2026-07-16-long-desktop-clips-now-preserve-complete-playback-synced-aud.md +6 -0
  182. package/corpus/templates/clips/changelog/2026-07-16-long-recording-lists-keep-stitch-and-library-actions-visible.md +6 -0
  183. package/corpus/templates/clips/changelog/2026-07-16-organization-admins-can-choose-new-recording-visibility.md +6 -0
  184. package/corpus/templates/clips/changelog/2026-07-16-remove-silences-now-shows-queued-active-completed-and-failed.md +6 -0
  185. package/corpus/templates/clips/changelog/2026-07-16-settings-no-longer-repeats-the-builder-connection-status-in-.md +6 -0
  186. package/corpus/templates/clips/changelog/2026-07-16-transcripts-now-appear-from-native-browser-speech-sooner-wit.md +6 -0
  187. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
  188. package/corpus/templates/clips/chrome-extension/src/background.ts +73 -1
  189. package/corpus/templates/clips/chrome-extension/src/native-recording-state.ts +32 -0
  190. package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +248 -0
  191. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +106 -0
  192. package/corpus/templates/clips/desktop/src/app.tsx +66 -28
  193. package/corpus/templates/clips/desktop/src/lib/recorder.ts +335 -285
  194. package/corpus/templates/clips/desktop/src/lib/single-flight.ts +7 -0
  195. package/corpus/templates/clips/desktop/src/lib/upload-verification.ts +51 -0
  196. package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +2 -2
  197. package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +10 -2
  198. package/corpus/templates/clips/desktop/src/styles.css +13 -11
  199. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +8 -9
  200. package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +1 -0
  201. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +88 -13
  202. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +13 -2
  203. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +241 -6
  204. package/corpus/templates/clips/server/db/schema.ts +2 -2
  205. package/corpus/templates/clips/server/lib/builder-media-compression.ts +64 -67
  206. package/corpus/templates/clips/server/lib/calendar-event-classification.ts +19 -0
  207. package/corpus/templates/clips/server/lib/google-calendar-client.ts +1 -0
  208. package/corpus/templates/clips/server/lib/recordings.ts +40 -1
  209. package/corpus/templates/clips/server/plugins/agent-chat.ts +1 -0
  210. package/corpus/templates/clips/server/plugins/db.ts +2 -2
  211. package/corpus/templates/clips/server/routes/api/auth/google-calendar.get.ts +1 -1
  212. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -5
  213. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +51 -1
  214. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +1 -64
  215. package/corpus/templates/clips/shared/media-worker-contract.ts +32 -15
  216. package/corpus/templates/content/.agents/skills/content/SKILL.md +16 -0
  217. package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +85 -0
  218. package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +8 -0
  219. package/corpus/templates/content/AGENTS.md +9 -0
  220. package/corpus/templates/content/actions/create-document.ts +94 -0
  221. package/corpus/templates/content/actions/edit-document.ts +144 -4
  222. package/corpus/templates/content/actions/update-document.ts +138 -0
  223. package/corpus/templates/content/agent-native.app-skill.json +4 -0
  224. package/corpus/templates/content/app/components/layout/Layout.tsx +2 -0
  225. package/corpus/templates/content/app/i18n/zh-TW.ts +3 -0
  226. package/corpus/templates/content/app/i18n-data.ts +13 -4
  227. package/corpus/templates/content/app/routes/_app.agent.tsx +2 -1
  228. package/corpus/templates/content/app/routes/_app.settings.tsx +3 -0
  229. package/corpus/templates/content/changelog/2026-07-16-creative-context-library.md +6 -0
  230. package/corpus/templates/content/package.json +1 -0
  231. package/corpus/templates/content/server/plugins/creative-context.ts +31 -0
  232. package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +116 -0
  233. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +16 -0
  234. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
  235. package/corpus/templates/design/AGENTS.md +6 -0
  236. package/corpus/templates/design/actions/clone-creative-context-design.ts +176 -0
  237. package/corpus/templates/design/actions/edit-design.ts +128 -0
  238. package/corpus/templates/design/actions/generate-design.ts +278 -14
  239. package/corpus/templates/design/actions/generate-screens.ts +42 -1
  240. package/corpus/templates/design/agent-native.app-skill.json +4 -0
  241. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -3
  242. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
  243. package/corpus/templates/design/app/i18n-data.ts +10 -4
  244. package/corpus/templates/design/app/routes/agent.tsx +2 -1
  245. package/corpus/templates/design/app/routes/settings.tsx +3 -0
  246. package/corpus/templates/design/changelog/2026-07-16-creative-context-library.md +6 -0
  247. package/corpus/templates/design/changelog/2026-07-16-design-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
  248. package/corpus/templates/design/package.json +1 -0
  249. package/corpus/templates/design/server/lib/figma-design-context.ts +5 -335
  250. package/corpus/templates/design/server/lib/figma-node-to-html.ts +1 -1859
  251. package/corpus/templates/design/server/lib/import-design-files.ts +6 -8
  252. package/corpus/templates/design/server/plugins/creative-context.ts +31 -0
  253. package/corpus/templates/design/shared/generation-session.ts +7 -0
  254. package/corpus/templates/dispatch/app/i18n-data.ts +3 -3
  255. package/corpus/templates/forms/app/i18n/en-US.ts +3 -3
  256. package/corpus/templates/macros/app/i18n/en-US.ts +3 -3
  257. package/corpus/templates/mail/app/components/email/EmailThread.tsx +35 -5
  258. package/corpus/templates/mail/app/i18n/en-US.ts +3 -3
  259. package/corpus/templates/mail/changelog/2026-07-16-mail-previews-now-expand-to-show-the-full-message-without-an.md +6 -0
  260. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +30 -11
  261. package/corpus/templates/plan/AGENTS.md +21 -1
  262. package/corpus/templates/plan/actions/get-visual-plan.ts +1 -1
  263. package/corpus/templates/plan/actions/patch-visual-plan-source.ts +161 -0
  264. package/corpus/templates/plan/actions/read-visual-plan-source.ts +1 -1
  265. package/corpus/templates/plan/actions/update-visual-plan.ts +126 -10
  266. package/corpus/templates/plan/app/hooks/use-plans.ts +2 -0
  267. package/corpus/templates/plan/app/i18n/en-US.ts +3 -3
  268. package/corpus/templates/plan/app/pages/PlansPage.tsx +65 -62
  269. package/corpus/templates/plan/changelog/2026-07-16-local-plan-previews-now-load-annotations-containing-html-lik.md +6 -0
  270. package/corpus/templates/plan/changelog/2026-07-16-plan-agents-now-prevent-stale-edits-from-overwriting-newer-p.md +6 -0
  271. package/corpus/templates/plan/server/plan-mdx.ts +75 -2
  272. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +21 -4
  273. package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +122 -0
  274. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +11 -0
  275. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +12 -3
  276. package/corpus/templates/slides/AGENTS.md +6 -0
  277. package/corpus/templates/slides/actions/add-slide.ts +230 -14
  278. package/corpus/templates/slides/actions/clone-context-slide.ts +302 -0
  279. package/corpus/templates/slides/actions/create-deck.ts +130 -0
  280. package/corpus/templates/slides/actions/extract-pdf.ts +6 -2
  281. package/corpus/templates/slides/actions/import-file.ts +5 -4
  282. package/corpus/templates/slides/actions/patch-deck.ts +200 -10
  283. package/corpus/templates/slides/actions/update-slide.ts +208 -15
  284. package/corpus/templates/slides/app/components/layout/Layout.tsx +2 -0
  285. package/corpus/templates/slides/app/components/visual-editor/CanvasCommentPins.tsx +16 -1
  286. package/corpus/templates/slides/app/i18n/ar-SA.ts +3 -0
  287. package/corpus/templates/slides/app/i18n/de-DE.ts +3 -0
  288. package/corpus/templates/slides/app/i18n/en-US.ts +6 -3
  289. package/corpus/templates/slides/app/i18n/es-ES.ts +3 -0
  290. package/corpus/templates/slides/app/i18n/fr-FR.ts +3 -0
  291. package/corpus/templates/slides/app/i18n/hi-IN.ts +3 -0
  292. package/corpus/templates/slides/app/i18n/ja-JP.ts +3 -0
  293. package/corpus/templates/slides/app/i18n/ko-KR.ts +3 -0
  294. package/corpus/templates/slides/app/i18n/pt-BR.ts +3 -0
  295. package/corpus/templates/slides/app/i18n/zh-CN.ts +3 -0
  296. package/corpus/templates/slides/app/i18n/zh-TW.ts +3 -0
  297. package/corpus/templates/slides/app/lib/validate-native-slide-html.ts +176 -0
  298. package/corpus/templates/slides/app/routes/agent.tsx +7 -1
  299. package/corpus/templates/slides/app/routes/settings.tsx +3 -0
  300. package/corpus/templates/slides/changelog/2026-07-16-creative-context-library.md +6 -0
  301. package/corpus/templates/slides/changelog/2026-07-16-google-slides-native-cloning.md +6 -0
  302. package/corpus/templates/slides/package.json +1 -0
  303. package/corpus/templates/slides/server/handlers/import/docx-parser.ts +4 -85
  304. package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +7 -421
  305. package/corpus/templates/slides/server/plugins/creative-context.ts +166 -0
  306. package/dist/agent/engine/credential-errors.d.ts +1 -1
  307. package/dist/agent/engine/credential-errors.d.ts.map +1 -1
  308. package/dist/agent/engine/credential-errors.js +2 -2
  309. package/dist/agent/engine/credential-errors.js.map +1 -1
  310. package/dist/agent/production-agent.d.ts.map +1 -1
  311. package/dist/agent/production-agent.js +25 -0
  312. package/dist/agent/production-agent.js.map +1 -1
  313. package/dist/agent/run-store.d.ts.map +1 -1
  314. package/dist/agent/run-store.js +12 -2
  315. package/dist/agent/run-store.js.map +1 -1
  316. package/dist/cli/create.d.ts.map +1 -1
  317. package/dist/cli/create.js +1 -0
  318. package/dist/cli/create.js.map +1 -1
  319. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  320. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  321. package/dist/cli/skills-content/visual-plan-skill.js +30 -11
  322. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  323. package/dist/cli/templates-meta.d.ts.map +1 -1
  324. package/dist/cli/templates-meta.js +4 -3
  325. package/dist/cli/templates-meta.js.map +1 -1
  326. package/dist/client/AgentAskPopover.d.ts +11 -0
  327. package/dist/client/AgentAskPopover.d.ts.map +1 -0
  328. package/dist/client/AgentAskPopover.js +30 -0
  329. package/dist/client/AgentAskPopover.js.map +1 -0
  330. package/dist/client/AgentChatHome.d.ts +1 -1
  331. package/dist/client/AgentChatHome.d.ts.map +1 -1
  332. package/dist/client/AgentChatHome.js +2 -2
  333. package/dist/client/AgentChatHome.js.map +1 -1
  334. package/dist/client/AgentPanel.d.ts +9 -19
  335. package/dist/client/AgentPanel.d.ts.map +1 -1
  336. package/dist/client/AgentPanel.js +119 -80
  337. package/dist/client/AgentPanel.js.map +1 -1
  338. package/dist/client/AssistantChat.d.ts.map +1 -1
  339. package/dist/client/AssistantChat.js +4 -4
  340. package/dist/client/AssistantChat.js.map +1 -1
  341. package/dist/client/MultiTabAssistantChat.d.ts +3 -9
  342. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  343. package/dist/client/MultiTabAssistantChat.js +49 -189
  344. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  345. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  346. package/dist/client/agent-chat-adapter.js +12 -1
  347. package/dist/client/agent-chat-adapter.js.map +1 -1
  348. package/dist/client/agent-page/AgentContextTab.d.ts.map +1 -1
  349. package/dist/client/agent-page/AgentContextTab.js +26 -28
  350. package/dist/client/agent-page/AgentContextTab.js.map +1 -1
  351. package/dist/client/agent-page/AgentEmptyState.d.ts +13 -0
  352. package/dist/client/agent-page/AgentEmptyState.d.ts.map +1 -0
  353. package/dist/client/agent-page/AgentEmptyState.js +6 -0
  354. package/dist/client/agent-page/AgentEmptyState.js.map +1 -0
  355. package/dist/client/agent-page/AgentJobsTab.d.ts +1 -1
  356. package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
  357. package/dist/client/agent-page/AgentJobsTab.js +90 -58
  358. package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
  359. package/dist/client/agent-page/AgentTabFrame.d.ts +12 -0
  360. package/dist/client/agent-page/AgentTabFrame.d.ts.map +1 -0
  361. package/dist/client/agent-page/AgentTabFrame.js +7 -0
  362. package/dist/client/agent-page/AgentTabFrame.js.map +1 -0
  363. package/dist/client/agent-page/AgentTabsPage.d.ts +9 -1
  364. package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
  365. package/dist/client/agent-page/AgentTabsPage.js +135 -99
  366. package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
  367. package/dist/client/agent-page/types.d.ts +1 -1
  368. package/dist/client/agent-page/types.d.ts.map +1 -1
  369. package/dist/client/agent-page/types.js.map +1 -1
  370. package/dist/client/analytics.d.ts +10 -3
  371. package/dist/client/analytics.d.ts.map +1 -1
  372. package/dist/client/analytics.js +37 -2
  373. package/dist/client/analytics.js.map +1 -1
  374. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  375. package/dist/client/chat/run-recovery.js +10 -3
  376. package/dist/client/chat/run-recovery.js.map +1 -1
  377. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  378. package/dist/client/composer/PromptComposer.js +2 -2
  379. package/dist/client/composer/PromptComposer.js.map +1 -1
  380. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  381. package/dist/client/composer/TiptapComposer.js +15 -3
  382. package/dist/client/composer/TiptapComposer.js.map +1 -1
  383. package/dist/client/dynamic-suggestions.js +3 -3
  384. package/dist/client/dynamic-suggestions.js.map +1 -1
  385. package/dist/client/index.d.ts +4 -3
  386. package/dist/client/index.d.ts.map +1 -1
  387. package/dist/client/index.js +3 -2
  388. package/dist/client/index.js.map +1 -1
  389. package/dist/client/resources/ResourceTree.d.ts +5 -1
  390. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  391. package/dist/client/resources/ResourceTree.js +74 -5
  392. package/dist/client/resources/ResourceTree.js.map +1 -1
  393. package/dist/client/resources/ResourcesPanel.d.ts +11 -2
  394. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  395. package/dist/client/resources/ResourcesPanel.js +105 -31
  396. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  397. package/dist/client/session-replay.d.ts +28 -0
  398. package/dist/client/session-replay.d.ts.map +1 -1
  399. package/dist/client/session-replay.js +122 -8
  400. package/dist/client/session-replay.js.map +1 -1
  401. package/dist/client/settings/AutomationsSection.d.ts +3 -1
  402. package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
  403. package/dist/client/settings/AutomationsSection.js +16 -6
  404. package/dist/client/settings/AutomationsSection.js.map +1 -1
  405. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  406. package/dist/client/settings/SettingsPanel.js +3 -3
  407. package/dist/client/settings/SettingsPanel.js.map +1 -1
  408. package/dist/client/settings/SettingsTabsPage.d.ts +2 -0
  409. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  410. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  411. package/dist/client/settings/agent-settings-search.js +2 -2
  412. package/dist/client/settings/agent-settings-search.js.map +1 -1
  413. package/dist/client/use-chat-threads.d.ts +2 -0
  414. package/dist/client/use-chat-threads.d.ts.map +1 -1
  415. package/dist/client/use-chat-threads.js.map +1 -1
  416. package/dist/collab/awareness.d.ts +2 -2
  417. package/dist/collab/awareness.d.ts.map +1 -1
  418. package/dist/collab/routes.d.ts +1 -1
  419. package/dist/connections/catalog.d.ts +41 -7
  420. package/dist/connections/catalog.d.ts.map +1 -1
  421. package/dist/connections/catalog.js +40 -7
  422. package/dist/connections/catalog.js.map +1 -1
  423. package/dist/db/index.d.ts +2 -2
  424. package/dist/db/index.d.ts.map +1 -1
  425. package/dist/db/index.js +2 -2
  426. package/dist/db/index.js.map +1 -1
  427. package/dist/extensions/actions.d.ts.map +1 -1
  428. package/dist/extensions/actions.js +85 -15
  429. package/dist/extensions/actions.js.map +1 -1
  430. package/dist/extensions/content-patch.d.ts +4 -0
  431. package/dist/extensions/content-patch.d.ts.map +1 -1
  432. package/dist/extensions/content-patch.js +18 -0
  433. package/dist/extensions/content-patch.js.map +1 -1
  434. package/dist/extensions/routes.d.ts.map +1 -1
  435. package/dist/extensions/routes.js +14 -0
  436. package/dist/extensions/routes.js.map +1 -1
  437. package/dist/extensions/store.d.ts +1 -0
  438. package/dist/extensions/store.d.ts.map +1 -1
  439. package/dist/extensions/store.js +4 -1
  440. package/dist/extensions/store.js.map +1 -1
  441. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  442. package/dist/index.d.ts +1 -1
  443. package/dist/index.d.ts.map +1 -1
  444. package/dist/index.js +1 -1
  445. package/dist/index.js.map +1 -1
  446. package/dist/ingestion/docx.d.ts +16 -0
  447. package/dist/ingestion/docx.d.ts.map +1 -0
  448. package/dist/ingestion/docx.js +129 -0
  449. package/dist/ingestion/docx.js.map +1 -0
  450. package/dist/ingestion/figma-node-to-html.d.ts +304 -0
  451. package/dist/ingestion/figma-node-to-html.d.ts.map +1 -0
  452. package/dist/ingestion/figma-node-to-html.js +1292 -0
  453. package/dist/ingestion/figma-node-to-html.js.map +1 -0
  454. package/dist/ingestion/figma.d.ts +115 -0
  455. package/dist/ingestion/figma.d.ts.map +1 -0
  456. package/dist/ingestion/figma.js +399 -0
  457. package/dist/ingestion/figma.js.map +1 -0
  458. package/dist/ingestion/index.d.ts +11 -0
  459. package/dist/ingestion/index.d.ts.map +1 -0
  460. package/dist/ingestion/index.js +11 -0
  461. package/dist/ingestion/index.js.map +1 -0
  462. package/dist/ingestion/media.d.ts +36 -0
  463. package/dist/ingestion/media.d.ts.map +1 -0
  464. package/dist/ingestion/media.js +178 -0
  465. package/dist/ingestion/media.js.map +1 -0
  466. package/dist/ingestion/notion.d.ts +12 -0
  467. package/dist/ingestion/notion.d.ts.map +1 -0
  468. package/dist/ingestion/notion.js +104 -0
  469. package/dist/ingestion/notion.js.map +1 -0
  470. package/dist/ingestion/office.d.ts +45 -0
  471. package/dist/ingestion/office.d.ts.map +1 -0
  472. package/dist/ingestion/office.js +141 -0
  473. package/dist/ingestion/office.js.map +1 -0
  474. package/dist/ingestion/orchestration.d.ts +52 -0
  475. package/dist/ingestion/orchestration.d.ts.map +1 -0
  476. package/dist/ingestion/orchestration.js +89 -0
  477. package/dist/ingestion/orchestration.js.map +1 -0
  478. package/dist/ingestion/pptx.d.ts +28 -0
  479. package/dist/ingestion/pptx.d.ts.map +1 -0
  480. package/dist/ingestion/pptx.js +255 -0
  481. package/dist/ingestion/pptx.js.map +1 -0
  482. package/dist/ingestion/selection.d.ts +20 -0
  483. package/dist/ingestion/selection.d.ts.map +1 -0
  484. package/dist/ingestion/selection.js +52 -0
  485. package/dist/ingestion/selection.js.map +1 -0
  486. package/dist/ingestion/website.d.ts +27 -0
  487. package/dist/ingestion/website.d.ts.map +1 -0
  488. package/dist/ingestion/website.js +100 -0
  489. package/dist/ingestion/website.js.map +1 -0
  490. package/dist/integrations/plugin.d.ts.map +1 -1
  491. package/dist/integrations/plugin.js +32 -27
  492. package/dist/integrations/plugin.js.map +1 -1
  493. package/dist/localization/default-messages.d.ts +22 -0
  494. package/dist/localization/default-messages.d.ts.map +1 -1
  495. package/dist/localization/default-messages.js +31 -9
  496. package/dist/localization/default-messages.js.map +1 -1
  497. package/dist/observability/hosted-model-experiment.d.ts +39 -0
  498. package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
  499. package/dist/observability/hosted-model-experiment.js +90 -0
  500. package/dist/observability/hosted-model-experiment.js.map +1 -0
  501. package/dist/observability/routes.d.ts +5 -5
  502. package/dist/observability/traces.d.ts.map +1 -1
  503. package/dist/observability/traces.js +5 -3
  504. package/dist/observability/traces.js.map +1 -1
  505. package/dist/progress/routes.d.ts +1 -1
  506. package/dist/provider-api/index.d.ts +35 -4
  507. package/dist/provider-api/index.d.ts.map +1 -1
  508. package/dist/provider-api/index.js +339 -8
  509. package/dist/provider-api/index.js.map +1 -1
  510. package/dist/resources/handlers.d.ts +1 -1
  511. package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
  512. package/dist/scripts/agent-engines/list-agent-engines.js +18 -1
  513. package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
  514. package/dist/search-utils/index.d.ts +12 -0
  515. package/dist/search-utils/index.d.ts.map +1 -0
  516. package/dist/search-utils/index.js +95 -0
  517. package/dist/search-utils/index.js.map +1 -0
  518. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  519. package/dist/secrets/register-framework-secrets.js +57 -0
  520. package/dist/secrets/register-framework-secrets.js.map +1 -1
  521. package/dist/secrets/routes.d.ts +9 -9
  522. package/dist/server/action-discovery.d.ts +8 -0
  523. package/dist/server/action-discovery.d.ts.map +1 -1
  524. package/dist/server/action-discovery.js +26 -9
  525. package/dist/server/action-discovery.js.map +1 -1
  526. package/dist/server/agent-chat/framework-prompts.js +2 -2
  527. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  528. package/dist/server/agent-chat/prompt-resources.d.ts +19 -0
  529. package/dist/server/agent-chat/prompt-resources.d.ts.map +1 -1
  530. package/dist/server/agent-chat/prompt-resources.js +95 -0
  531. package/dist/server/agent-chat/prompt-resources.js.map +1 -1
  532. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  533. package/dist/server/agent-chat-plugin.js +7 -0
  534. package/dist/server/agent-chat-plugin.js.map +1 -1
  535. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  536. package/dist/server/core-routes-plugin.js +5 -0
  537. package/dist/server/core-routes-plugin.js.map +1 -1
  538. package/dist/server/index.d.ts +5 -1
  539. package/dist/server/index.d.ts.map +1 -1
  540. package/dist/server/index.js +5 -1
  541. package/dist/server/index.js.map +1 -1
  542. package/dist/server/workspace-provider-oauth.d.ts +48 -0
  543. package/dist/server/workspace-provider-oauth.d.ts.map +1 -0
  544. package/dist/server/workspace-provider-oauth.js +415 -0
  545. package/dist/server/workspace-provider-oauth.js.map +1 -0
  546. package/dist/styles/agent-native.css +9 -0
  547. package/dist/templates/chat/app/i18n/en-US.ts +3 -3
  548. package/dist/templates/chat/app/lib/agent-page.tsx +10 -1
  549. package/dist/templates/default/app/i18n/en-US.ts +3 -3
  550. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
  551. package/dist/templates/workspace-root/.env.example +12 -0
  552. package/dist/vite/client.d.ts.map +1 -1
  553. package/dist/vite/client.js +2 -0
  554. package/dist/vite/client.js.map +1 -1
  555. package/dist/workspace-connections/index.d.ts +1 -0
  556. package/dist/workspace-connections/index.d.ts.map +1 -1
  557. package/dist/workspace-connections/index.js +1 -0
  558. package/dist/workspace-connections/index.js.map +1 -1
  559. package/dist/workspace-connections/lifecycle.d.ts +16 -0
  560. package/dist/workspace-connections/lifecycle.d.ts.map +1 -0
  561. package/dist/workspace-connections/lifecycle.js +14 -0
  562. package/dist/workspace-connections/lifecycle.js.map +1 -0
  563. package/dist/workspace-connections/store.d.ts.map +1 -1
  564. package/dist/workspace-connections/store.js +16 -0
  565. package/dist/workspace-connections/store.js.map +1 -1
  566. package/package.json +10 -3
  567. package/src/templates/chat/app/i18n/en-US.ts +3 -3
  568. package/src/templates/chat/app/lib/agent-page.spec.tsx +10 -1
  569. package/src/templates/chat/app/lib/agent-page.tsx +10 -1
  570. package/src/templates/default/app/i18n/en-US.ts +3 -3
  571. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
  572. package/src/templates/workspace-root/.env.example +12 -0
@@ -97,17 +97,20 @@ export function Layout({ children }: LayoutProps) {
97
97
  const reportScreenshot =
98
98
  new URLSearchParams(location.search).get("reportScreenshot") === "1";
99
99
 
100
- // Analytics has two distinct "primary resources" dashboards
101
- // (`/dashboards/:id`, legacy `/adhoc/:id`) and ad-hoc analyses
102
- // (`/analyses/:id`). Each binds the chat to that artifact so a dashboard
103
- // chat doesn't leak into a different analysis (and vice versa). The list
104
- // pages and Ask leave scope null so general data questions still work.
100
+ // Analytics stages the active primary resource as composer context
101
+ // dashboards (`/dashboards/:id`, legacy `/adhoc/:id`) and ad-hoc analyses
102
+ // (`/analyses/:id`). List pages and Ask leave context null so general data
103
+ // questions still work.
105
104
  const analyticsScope = useMemo(() => {
106
105
  const dashMatch = location.pathname.match(
107
106
  /^\/(?:adhoc|dashboards)\/([^/]+)/,
108
107
  );
109
108
  if (dashMatch?.[1]) {
110
- return { type: "dashboard" as const, id: dashMatch[1] };
109
+ return {
110
+ type: "dashboard" as const,
111
+ id: dashMatch[1],
112
+ contextKey: "analytics-selected-dashboard",
113
+ };
111
114
  }
112
115
  const analysisMatch = location.pathname.match(/^\/analyses\/([^/]+)/);
113
116
  if (analysisMatch?.[1]) {
@@ -21,13 +21,13 @@ import {
21
21
  IconLock,
22
22
  IconLink,
23
23
  IconMessageCircle,
24
+ IconHierarchy2,
24
25
  IconUsersGroup,
25
26
  IconEye,
26
27
  IconEyeOff,
27
28
  IconPlayerPlay,
28
29
  IconLayoutSidebarLeftCollapse,
29
30
  IconLayoutSidebarLeftExpand,
30
- IconBrain,
31
31
  } from "@tabler/icons-react";
32
32
  import {
33
33
  useQuery,
@@ -138,6 +138,7 @@ import {
138
138
  type DashboardView,
139
139
  } from "@/hooks/use-dashboard-views";
140
140
  import { useUserPref } from "@/hooks/use-user-pref";
141
+ import { shouldRenderDashboardList } from "@/lib/dashboard-list-loading";
141
142
  import { usePopularity, popularityOf } from "@/lib/item-popularity";
142
143
  import {
143
144
  analysisDetailPrefetchKey,
@@ -184,7 +185,11 @@ import {
184
185
  import { CSS } from "@dnd-kit/utilities";
185
186
 
186
187
  const bottomItems = [
187
- { icon: IconBrain, labelKey: "settings.agentTitle", href: "/agent" },
188
+ {
189
+ icon: IconHierarchy2,
190
+ labelKey: "settings.agentTitle",
191
+ href: "/agent",
192
+ },
188
193
  { icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
189
194
  ];
190
195
 
@@ -1631,7 +1636,7 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1631
1636
  useState<SidebarSortMode>(() => getStoredSortMode(DASHBOARD_SORT_MODE_KEY));
1632
1637
  const [analysisSortMode, setAnalysisSortModeState] =
1633
1638
  useState<SidebarSortMode>(() => getStoredSortMode(ANALYSIS_SORT_MODE_KEY));
1634
- const popularity = usePopularity();
1639
+ const { data: popularity, isReady: popularityReady } = usePopularity();
1635
1640
 
1636
1641
  useEffect(() => {
1637
1642
  if (typeof window !== "undefined" && window.localStorage.getItem("theme")) {
@@ -1692,7 +1697,11 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1692
1697
  );
1693
1698
 
1694
1699
  // Server-backed favorites
1695
- const { data: favoritesData, save: saveFavorites } = useUserPref<{
1700
+ const {
1701
+ data: favoritesData,
1702
+ isLoading: favoritesLoading,
1703
+ save: saveFavorites,
1704
+ } = useUserPref<{
1696
1705
  ids: string[];
1697
1706
  }>("favorites");
1698
1707
  const favoriteIds = useMemo(
@@ -1781,6 +1790,7 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1781
1790
  const {
1782
1791
  data: sqlDashboards = [],
1783
1792
  isLoading: sqlDashboardsLoading,
1793
+ isPlaceholderData: sqlDashboardsPlaceholder,
1784
1794
  isError: sqlDashboardsError,
1785
1795
  refetch: refetchSqlDashboards,
1786
1796
  } = useQuery({
@@ -1922,7 +1932,7 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1922
1932
  const aPop = popularityOf(popularity, "dashboard", a.id);
1923
1933
  const bPop = popularityOf(popularity, "dashboard", b.id);
1924
1934
  if (aPop !== bPop) return bPop - aPop;
1925
- return a.name.localeCompare(b.name);
1935
+ return a.name.localeCompare(b.name) || a.id.localeCompare(b.id);
1926
1936
  });
1927
1937
  }, [
1928
1938
  hiddenIds,
@@ -1978,6 +1988,19 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1978
1988
  [topLevelDashboards, dashShowAll],
1979
1989
  );
1980
1990
 
1991
+ const dashboardListHasRendered = useRef(false);
1992
+ const dashboardListReady = shouldRenderDashboardList({
1993
+ sqlDashboardsLoading,
1994
+ sqlDashboardsPlaceholder,
1995
+ isInitialLoad: !dashboardListHasRendered.current,
1996
+ favoritesLoading,
1997
+ popularityReady,
1998
+ sortMode: dashboardSortMode,
1999
+ });
2000
+ useEffect(() => {
2001
+ if (dashboardListReady) dashboardListHasRendered.current = true;
2002
+ }, [dashboardListReady]);
2003
+
1981
2004
  // The flattened id order exactly as rendered (each parent immediately
1982
2005
  // followed by its nested children). Drag reordering must use this so the
1983
2006
  // arrayMove indices match what the user sees; the raw `visibleDashboards`
@@ -2448,7 +2471,7 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
2448
2471
  active: location.pathname.startsWith("/data-dictionary"),
2449
2472
  },
2450
2473
  {
2451
- icon: IconBrain,
2474
+ icon: IconHierarchy2,
2452
2475
  label: t("settings.agentTitle"),
2453
2476
  href: "/agent",
2454
2477
  active: location.pathname === "/agent",
@@ -2747,64 +2770,67 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
2747
2770
  strategy={verticalListSortingStrategy}
2748
2771
  >
2749
2772
  <div className="ms-4 min-w-0 space-y-0.5">
2750
- {displayedDashboards.map((d) => {
2751
- const children = dashboardChildren.get(d.id) ?? [];
2752
- return (
2753
- <Fragment key={d.id}>
2754
- <SortableDashboardItem
2755
- d={d}
2756
- isActive={activeDashboardId === d.id}
2757
- location={location}
2758
- favoriteIds={favoriteIds}
2759
- onToggleFavorite={toggleFavorite}
2760
- onDelete={handleDashboardDelete}
2761
- onRename={handleDashboardRename}
2762
- onArchive={handleDashboardArchive}
2763
- onSetVisibility={handleDashboardSetVisibility}
2764
- onPrefetch={prefetchDashboard}
2765
- views={allViewsMap[d.id]}
2766
- />
2767
- {children.length > 0 && (
2768
- <div className="ms-3 space-y-0.5 border-s border-sidebar-border/60 ps-1">
2769
- {children.map((child) => (
2770
- <SortableDashboardItem
2771
- key={child.id}
2772
- d={child}
2773
- isActive={activeDashboardId === child.id}
2774
- location={location}
2775
- favoriteIds={favoriteIds}
2776
- onToggleFavorite={toggleFavorite}
2777
- onDelete={handleDashboardDelete}
2778
- onRename={handleDashboardRename}
2779
- onArchive={handleDashboardArchive}
2780
- onSetVisibility={
2781
- handleDashboardSetVisibility
2782
- }
2783
- onPrefetch={prefetchDashboard}
2784
- views={allViewsMap[child.id]}
2785
- />
2786
- ))}
2787
- </div>
2788
- )}
2789
- </Fragment>
2790
- );
2791
- })}
2792
- {topLevelDashboards.length > SIDEBAR_PREVIEW_COUNT && (
2793
- <button
2794
- onClick={() => setDashShowAll(!dashShowAll)}
2795
- className="flex items-center gap-1 px-3 py-1 text-[11px] text-muted-foreground/70 hover:text-primary"
2796
- >
2797
- {dashShowAll
2798
- ? t("sidebar.showLess")
2799
- : t("sidebar.showMore", {
2800
- count:
2801
- topLevelDashboards.length -
2802
- SIDEBAR_PREVIEW_COUNT,
2803
- })}
2804
- </button>
2805
- )}
2806
- {sqlDashboardsLoading &&
2807
- sqlDashboards.length === 0 &&
2773
+ {dashboardListReady &&
2774
+ displayedDashboards.map((d) => {
2775
+ const children = dashboardChildren.get(d.id) ?? [];
2776
+ return (
2777
+ <Fragment key={d.id}>
2778
+ <SortableDashboardItem
2779
+ d={d}
2780
+ isActive={activeDashboardId === d.id}
2781
+ location={location}
2782
+ favoriteIds={favoriteIds}
2783
+ onToggleFavorite={toggleFavorite}
2784
+ onDelete={handleDashboardDelete}
2785
+ onRename={handleDashboardRename}
2786
+ onArchive={handleDashboardArchive}
2787
+ onSetVisibility={handleDashboardSetVisibility}
2788
+ onPrefetch={prefetchDashboard}
2789
+ views={allViewsMap[d.id]}
2790
+ />
2791
+ {children.length > 0 && (
2792
+ <div className="ms-3 space-y-0.5 border-s border-sidebar-border/60 ps-1">
2793
+ {children.map((child) => (
2794
+ <SortableDashboardItem
2795
+ key={child.id}
2796
+ d={child}
2797
+ isActive={
2798
+ activeDashboardId === child.id
2799
+ }
2800
+ location={location}
2801
+ favoriteIds={favoriteIds}
2802
+ onToggleFavorite={toggleFavorite}
2803
+ onDelete={handleDashboardDelete}
2804
+ onRename={handleDashboardRename}
2805
+ onArchive={handleDashboardArchive}
2806
+ onSetVisibility={
2807
+ handleDashboardSetVisibility
2808
+ }
2809
+ onPrefetch={prefetchDashboard}
2810
+ views={allViewsMap[child.id]}
2811
+ />
2812
+ ))}
2813
+ </div>
2814
+ )}
2815
+ </Fragment>
2816
+ );
2817
+ })}
2818
+ {dashboardListReady &&
2819
+ topLevelDashboards.length > SIDEBAR_PREVIEW_COUNT && (
2820
+ <button
2821
+ onClick={() => setDashShowAll(!dashShowAll)}
2822
+ className="flex items-center gap-1 px-3 py-1 text-[11px] text-muted-foreground/70 hover:text-primary"
2823
+ >
2824
+ {dashShowAll
2825
+ ? t("sidebar.showLess")
2826
+ : t("sidebar.showMore", {
2827
+ count:
2828
+ topLevelDashboards.length -
2829
+ SIDEBAR_PREVIEW_COUNT,
2830
+ })}
2831
+ </button>
2832
+ )}
2833
+ {!dashboardListReady &&
2808
2834
  Array.from({ length: 3 }).map((_, i) => (
2809
2835
  <div
2810
2836
  key={`sql-skeleton-${i}`}
@@ -168,10 +168,10 @@ const enUS = {
168
168
  untitledDashboard: "Untitled dashboard",
169
169
  },
170
170
  settings: {
171
- agentTitle: "Agent settings",
171
+ agentTitle: "Agent workspace",
172
172
  agentDescription:
173
- "Open the agent sidebar settings for model, API keys, automations, voice, and other agent controls.",
174
- openAgentSettings: "Open agent settings",
173
+ "Open the agent workspace for model, API keys, automations, voice, and other agent controls.",
174
+ openAgentSettings: "Open agent workspace",
175
175
  account: "Account",
176
176
  signedInAs: "Signed in as",
177
177
  credentials: "Data Source Credentials",
@@ -0,0 +1,25 @@
1
+ export type DashboardSortMode = "most-used" | "alphabetical" | "manual";
2
+
3
+ export type DashboardListLoadingArgs = {
4
+ sqlDashboardsLoading: boolean;
5
+ sqlDashboardsPlaceholder: boolean;
6
+ isInitialLoad: boolean;
7
+ favoritesLoading: boolean;
8
+ popularityReady: boolean;
9
+ sortMode: DashboardSortMode;
10
+ };
11
+
12
+ export function shouldRenderDashboardList({
13
+ sqlDashboardsLoading,
14
+ sqlDashboardsPlaceholder,
15
+ isInitialLoad,
16
+ favoritesLoading,
17
+ popularityReady,
18
+ sortMode,
19
+ }: DashboardListLoadingArgs): boolean {
20
+ if (sqlDashboardsLoading || (isInitialLoad && sqlDashboardsPlaceholder)) {
21
+ return false;
22
+ }
23
+ if (sortMode !== "most-used") return true;
24
+ return favoritesLoading === false && popularityReady;
25
+ }
@@ -20,6 +20,10 @@ const ANONYMOUS_SCOPE = "anonymous:none";
20
20
 
21
21
  export type ItemType = "dashboard" | "analysis" | "extension";
22
22
  export type Popularity = Record<string, number>;
23
+ export type PopularityState = {
24
+ data: Popularity;
25
+ isReady: boolean;
26
+ };
23
27
 
24
28
  let currentScope = ANONYMOUS_SCOPE;
25
29
 
@@ -94,18 +98,20 @@ export function incrementItemView(type: ItemType, id: string): void {
94
98
  write(p);
95
99
  }
96
100
 
97
- export function usePopularity(): Popularity {
98
- const { session } = useSession();
99
- const { data: org } = useOrg();
101
+ export function usePopularity(): PopularityState {
102
+ const { session, isLoading: sessionLoading } = useSession();
103
+ const { data: org, isLoading: orgLoading } = useOrg();
100
104
  const email = session?.email?.trim() || "anonymous";
101
105
  const orgId = org?.orgId ?? "none";
102
106
  const nextScope = `${email}:${orgId}`;
103
107
 
104
108
  const [snapshot, setSnapshot] = useState<Popularity>(() => read());
109
+ const [readyScope, setReadyScope] = useState<string | null>(null);
105
110
 
106
111
  useEffect(() => {
107
112
  setScope(nextScope);
108
113
  setSnapshot(read());
114
+ setReadyScope(nextScope);
109
115
  }, [nextScope]);
110
116
 
111
117
  useEffect(() => {
@@ -117,7 +123,10 @@ export function usePopularity(): Popularity {
117
123
  window.removeEventListener("storage", refresh);
118
124
  };
119
125
  }, []);
120
- return snapshot;
126
+ return {
127
+ data: snapshot,
128
+ isReady: !sessionLoading && !orgLoading && readyScope === nextScope,
129
+ };
121
130
  }
122
131
 
123
132
  export function popularityOf(
@@ -427,7 +427,7 @@ function FilterControl({
427
427
  onValueChange={(v) => setValue({ [filter.id]: v })}
428
428
  >
429
429
  <SelectTrigger className="h-8 w-[140px] text-xs">
430
- <SelectValue />
430
+ <SelectValue className="flex-1 text-left" />
431
431
  </SelectTrigger>
432
432
  <SelectContent>
433
433
  {filter.options?.map((opt) => (
@@ -17,6 +17,7 @@ export interface PivotResult {
17
17
 
18
18
  const ISO_DAY_RE = /^\d{4}-\d{2}-\d{2}$/;
19
19
  const MAX_DAILY_GAP_FILL_DAYS = 800;
20
+ const DAY_MS = 86_400_000;
20
21
 
21
22
  function dayToUtcMs(day: string): number | null {
22
23
  if (!ISO_DAY_RE.test(day)) return null;
@@ -54,7 +55,7 @@ function fillMissingDailyRows(
54
55
  const endMs = dayToUtcMs(last);
55
56
  if (startMs == null || endMs == null || endMs < startMs) return rows;
56
57
 
57
- const dayCount = Math.floor((endMs - startMs) / 86_400_000) + 1;
58
+ const dayCount = Math.floor((endMs - startMs) / DAY_MS) + 1;
58
59
  if (dayCount > MAX_DAILY_GAP_FILL_DAYS) return rows;
59
60
 
60
61
  const byDay = new Map<string, Record<string, unknown>>();
@@ -66,7 +67,7 @@ function fillMissingDailyRows(
66
67
  }
67
68
 
68
69
  const filled: Record<string, unknown>[] = [];
69
- for (let ms = startMs; ms <= endMs; ms += 86_400_000) {
70
+ for (let ms = startMs; ms <= endMs; ms += DAY_MS) {
70
71
  const day = utcMsToDay(ms);
71
72
  filled.push(
72
73
  fillMissingSeries(byDay.get(day) ?? { [xKey]: day }, seriesKeys),
@@ -78,6 +79,7 @@ function fillMissingDailyRows(
78
79
  export function pivotRows(
79
80
  rows: Record<string, unknown>[],
80
81
  config: PivotConfig,
82
+ options?: { fillDateGaps?: boolean },
81
83
  ): PivotResult {
82
84
  const { xKey, seriesKey, valueKey } = config;
83
85
  const byX = new Map<string, Record<string, unknown>>();
@@ -116,7 +118,10 @@ export function pivotRows(
116
118
  }
117
119
 
118
120
  return {
119
- rows: fillMissingDailyRows(orderedRows, xKey, seriesKeys),
121
+ rows:
122
+ options?.fillDateGaps === false
123
+ ? orderedRows
124
+ : fillMissingDailyRows(orderedRows, xKey, seriesKeys),
120
125
  seriesKeys,
121
126
  };
122
127
  }
@@ -88,6 +88,7 @@ export interface SqlPanelConfig {
88
88
  pivot?: PivotConfig;
89
89
  /** Stack bar/area series on top of each other instead of side-by-side / overlapping. */
90
90
  stacked?: boolean;
91
+ /** Fixed bar width in pixels for bar charts. Values are clamped by the renderer. */
91
92
  /** Show the chart legend. Defaults to true for chart renderers. */
92
93
  legend?: boolean;
93
94
  /** Optional display labels for exact metric values, e.g. {"0":"normal"}. */
@@ -43,7 +43,7 @@ import {
43
43
  useState,
44
44
  type FormEvent,
45
45
  } from "react";
46
- import { Link, useParams } from "react-router";
46
+ import { Link, useParams, useSearchParams } from "react-router";
47
47
 
48
48
  import { Button } from "@/components/ui/button";
49
49
  import { Card, CardContent } from "@/components/ui/card";
@@ -265,9 +265,15 @@ const MOUSE_INTERACTION = {
265
265
  export default function SessionDetailPage() {
266
266
  const t = useT();
267
267
  const { recordingId = "" } = useParams();
268
+ const [searchParams] = useSearchParams();
268
269
  const { codeRequiredDialog } = useSendToAgentChat();
269
270
  const { data, isLoading, error } = useSessionReplayPlayback(recordingId);
270
271
  const recording = data?.recording;
272
+ const initialSeekMs = useMemo(() => {
273
+ const raw = searchParams.get("atMs");
274
+ if (!raw || !/^\d+$/.test(raw)) return 0;
275
+ return Number(raw);
276
+ }, [searchParams]);
271
277
 
272
278
  return (
273
279
  <div className="analytics-session-detail-page flex h-full min-h-0 w-full flex-col gap-3 overflow-hidden">
@@ -319,7 +325,7 @@ export default function SessionDetailPage() {
319
325
  <DetailSkeleton />
320
326
  ) : data && recording ? (
321
327
  <div className="min-h-0 flex-1">
322
- <ReplayWorkbench response={data} />
328
+ <ReplayWorkbench response={data} initialSeekMs={initialSeekMs} />
323
329
  </div>
324
330
  ) : null}
325
331
  </div>
@@ -428,8 +434,10 @@ function AskSessionPopover({
428
434
 
429
435
  function ReplayWorkbench({
430
436
  response,
437
+ initialSeekMs,
431
438
  }: {
432
439
  response: SessionReplayPlaybackResponse;
440
+ initialSeekMs: number;
433
441
  }) {
434
442
  const events = useReplayEvents(response);
435
443
  const markers = useMemo(() => buildReplayMarkers(events), [events]);
@@ -458,6 +466,7 @@ function ReplayWorkbench({
458
466
  events={events}
459
467
  markers={markers}
460
468
  response={response}
469
+ initialSeekMs={initialSeekMs}
461
470
  onTimeUpdate={setCurrentTime}
462
471
  registerSeek={registerSeek}
463
472
  />
@@ -475,12 +484,14 @@ function ReplayPlayer({
475
484
  events,
476
485
  markers,
477
486
  response,
487
+ initialSeekMs,
478
488
  onTimeUpdate,
479
489
  registerSeek,
480
490
  }: {
481
491
  events: AnyReplayEvent[];
482
492
  markers: ReplayMarker[];
483
493
  response: SessionReplayPlaybackResponse;
494
+ initialSeekMs: number;
484
495
  onTimeUpdate: (ms: number) => void;
485
496
  registerSeek: (seek: (ms: number, autoplay?: boolean) => void) => void;
486
497
  }) {
@@ -777,7 +788,7 @@ function ReplayPlayer({
777
788
  const total = Number(meta?.totalTime ?? replayDuration(replayEvents));
778
789
  setTotalTime(Number.isFinite(total) ? total : 0);
779
790
  const startAt = clamp(
780
- currentTimeRef.current,
791
+ initialSeekMs || currentTimeRef.current,
781
792
  0,
782
793
  Number.isFinite(total) ? total : 0,
783
794
  );
@@ -856,6 +867,7 @@ function ReplayPlayer({
856
867
  currentTimeRef,
857
868
  eventsIdentity,
858
869
  eventsRef,
870
+ initialSeekMs,
859
871
  response.isComplete,
860
872
  speedRef,
861
873
  t,
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-16
4
+ ---
5
+
6
+ Dashboard filter defaults can now be changed reliably without unrelated chart errors blocking the edit.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-16
4
+ ---
5
+
6
+ Dashboard lists load in one stable order without popping between intermediate results
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-16
4
+ ---
5
+
6
+ Fixed dashboard filter dropdown text alignment
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-16
4
+ ---
5
+
6
+ Recurring signed-in users can now be viewed as weekly bars by template.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-16
4
+ ---
5
+
6
+ The Analytics agent can now duplicate a chart and place the copy beside it in one edit.
@@ -38,7 +38,7 @@
38
38
  "id": "emailFilter",
39
39
  "type": "select",
40
40
  "label": "Email filter",
41
- "default": "all",
41
+ "default": "exclude_builder",
42
42
  "options": [
43
43
  {
44
44
  "value": "all",
@@ -474,6 +474,46 @@
474
474
  "description": "Signed-in browser identities with non-docs app session activity on at least two days in the selected time range."
475
475
  }
476
476
  },
477
+ {
478
+ "id": "recurring-users-by-template",
479
+ "title": "Recurring Signed-In Users by Template",
480
+ "chartType": "area",
481
+ "source": "first-party",
482
+ "width": 2,
483
+ "sql": "WITH all_users AS (SELECT NULLIF(user_key, '') AS user_key, event_date, user_id, COALESCE(NULLIF(template, ''), NULLIF(properties::jsonb ->> 'templateId', ''), NULLIF(properties::jsonb ->> 'agent_native_template', ''), NULLIF(properties::jsonb ->> 'agentNativeTemplate', ''), NULLIF(app, ''), NULLIF(properties::jsonb ->> 'agent_native_app', ''), NULLIF(properties::jsonb ->> 'agentNativeApp', ''), 'unknown') AS template FROM analytics_events WHERE event_name = 'session status' AND signed_in = 'true' AND NULLIF(user_key, '') IS NOT NULL AND lower(COALESCE(NULLIF(template, ''), NULLIF(properties::jsonb ->> 'templateId', ''), NULLIF(properties::jsonb ->> 'agent_native_template', ''), NULLIF(properties::jsonb ->> 'agentNativeTemplate', ''), NULLIF(app, ''), NULLIF(properties::jsonb ->> 'agent_native_app', ''), NULLIF(properties::jsonb ->> 'agentNativeApp', ''), 'unknown')) <> 'docs' 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'))), first_seen AS (SELECT user_key, MIN(event_date) AS first_date FROM all_users GROUP BY user_key) SELECT a.event_date AS date, a.template AS template, COUNT(DISTINCT a.user_key) AS users FROM all_users a JOIN first_seen f ON f.user_key = a.user_key WHERE a.event_date <> f.first_date AND a.template <> 'unknown' AND (a.event_date <= to_char(CURRENT_DATE, 'YYYY-MM-DD') AND ('{{timeRange}}' IN ('', 'all') OR ('{{timeRange}}' = '7d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '7 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '30d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '30 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '90d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '90 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '180d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '180 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '365d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '365 days', 'YYYY-MM-DD')))) GROUP BY 1, 2 ORDER BY date, template",
484
+ "config": {
485
+ "xKey": "date",
486
+ "yKey": "users",
487
+ "yFormatter": "number",
488
+ "pivot": {
489
+ "xKey": "date",
490
+ "seriesKey": "template",
491
+ "valueKey": "users"
492
+ },
493
+ "stacked": true,
494
+ "description": "Daily signed-in visitors who are NOT on their all-time first active day (Recurring only), stacked by inferred template/app used that day. Docs traffic and unknown template are excluded."
495
+ }
496
+ },
497
+ {
498
+ "id": "recurring-users-by-template-bar",
499
+ "title": "Recurring Signed-In Users by Template (Bar)",
500
+ "chartType": "bar",
501
+ "source": "first-party",
502
+ "width": 1,
503
+ "sql": "WITH all_users AS (SELECT NULLIF(user_key, '') AS user_key, event_date, user_id, COALESCE(NULLIF(template, ''), NULLIF(properties::jsonb ->> 'templateId', ''), NULLIF(properties::jsonb ->> 'agent_native_template', ''), NULLIF(properties::jsonb ->> 'agentNativeTemplate', ''), NULLIF(app, ''), NULLIF(properties::jsonb ->> 'agent_native_app', ''), NULLIF(properties::jsonb ->> 'agentNativeApp', ''), 'unknown') AS template FROM analytics_events WHERE event_name = 'session status' AND signed_in = 'true' AND NULLIF(user_key, '') IS NOT NULL AND lower(COALESCE(NULLIF(template, ''), NULLIF(properties::jsonb ->> 'templateId', ''), NULLIF(properties::jsonb ->> 'agent_native_template', ''), NULLIF(properties::jsonb ->> 'agentNativeTemplate', ''), NULLIF(app, ''), NULLIF(properties::jsonb ->> 'agent_native_app', ''), NULLIF(properties::jsonb ->> 'agentNativeApp', ''), 'unknown')) <> 'docs' 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'))), first_seen AS (SELECT user_key, MIN(event_date) AS first_date FROM all_users GROUP BY user_key) SELECT to_char(date_trunc('week', a.event_date::date), 'YYYY-MM-DD') AS date, a.template AS template, COUNT(DISTINCT a.user_key) AS users FROM all_users a JOIN first_seen f ON f.user_key = a.user_key WHERE a.event_date <> f.first_date AND a.template <> 'unknown' AND (a.event_date <= to_char(CURRENT_DATE, 'YYYY-MM-DD') AND ('{{timeRange}}' IN ('', 'all') OR ('{{timeRange}}' = '7d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '7 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '30d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '30 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '90d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '90 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '180d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '180 days', 'YYYY-MM-DD')) OR ('{{timeRange}}' = '365d' AND a.event_date >= to_char(CURRENT_DATE - INTERVAL '365 days', 'YYYY-MM-DD')))) GROUP BY 1, 2 ORDER BY date, template",
504
+ "config": {
505
+ "xKey": "date",
506
+ "yKey": "users",
507
+ "yFormatter": "number",
508
+ "pivot": {
509
+ "xKey": "date",
510
+ "seriesKey": "template",
511
+ "valueKey": "users"
512
+ },
513
+ "stacked": true,
514
+ "description": "Weekly distinct signed-in visitors who are NOT on their all-time first active day (Recurring only), stacked by inferred template/app used that week. Weeks start Monday; docs traffic and unknown template are excluded."
515
+ }
516
+ },
477
517
  {
478
518
  "id": "retention-over-time",
479
519
  "title": "7d Rolling Signed-In Return Rate",
@@ -938,7 +938,7 @@ export const dashboardCatalogEntries: DashboardCatalogEntry[] = [
938
938
  "referrals",
939
939
  "virality",
940
940
  ],
941
- panelCount: 36,
941
+ panelCount: 38,
942
942
  version: CATALOG_VERSION,
943
943
  recommended: true,
944
944
  visibleInCatalog: false,