@agent-native/core 0.131.7 → 0.132.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 (320) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +123 -0
  3. package/corpus/core/docs/content/durable-background-runs.mdx +15 -6
  4. package/corpus/core/docs/design/durable-agent-runs.md +15 -11
  5. package/corpus/core/package.json +1 -1
  6. package/corpus/core/src/a2a/activity.ts +127 -10
  7. package/corpus/core/src/a2a/index.ts +3 -0
  8. package/corpus/core/src/agent/durable-background.ts +38 -28
  9. package/corpus/core/src/agent/harness/background.ts +12 -2
  10. package/corpus/core/src/agent/production-agent.ts +18 -15
  11. package/corpus/core/src/agent/run-store.ts +45 -3
  12. package/corpus/core/src/application-state/handlers.ts +45 -0
  13. package/corpus/core/src/application-state/index.ts +3 -0
  14. package/corpus/core/src/application-state/store.ts +38 -34
  15. package/corpus/core/src/audit/redact.ts +104 -18
  16. package/corpus/core/src/cli/create.ts +115 -16
  17. package/corpus/core/src/client/AgentPanel.tsx +2 -7
  18. package/corpus/core/src/client/AssistantChat.tsx +10 -2
  19. package/corpus/core/src/client/MultiTabAssistantChat.tsx +3 -0
  20. package/corpus/core/src/client/RunStuckBanner.tsx +29 -6
  21. package/corpus/core/src/client/agent-chat.ts +4 -9
  22. package/corpus/core/src/client/application-state.ts +115 -12
  23. package/corpus/core/src/client/dynamic-suggestions.ts +4 -12
  24. package/corpus/core/src/client/frame-protocol.ts +5 -1
  25. package/corpus/core/src/client/guided-questions.tsx +12 -23
  26. package/corpus/core/src/db/client.ts +148 -28
  27. package/corpus/core/src/db/create-get-db.ts +39 -6
  28. package/corpus/core/src/db/runtime-diagnostics.ts +41 -6
  29. package/corpus/core/src/deploy/build.ts +26 -33
  30. package/corpus/core/src/feature-flags/store.ts +10 -5
  31. package/corpus/core/src/integrations/a2a-continuations-store.ts +11 -0
  32. package/corpus/core/src/integrations/config-store.ts +13 -0
  33. package/corpus/core/src/integrations/google-docs-poller.ts +26 -2
  34. package/corpus/core/src/mcp-client/routes.ts +33 -2
  35. package/corpus/core/src/onboarding/plugin.ts +31 -25
  36. package/corpus/core/src/org/accept-pending.ts +2 -0
  37. package/corpus/core/src/org/auto-join-domain.ts +2 -0
  38. package/corpus/core/src/org/context.ts +35 -10
  39. package/corpus/core/src/org/handlers.ts +6 -0
  40. package/corpus/core/src/org/request-org-cache.ts +71 -0
  41. package/corpus/core/src/resources/store.ts +10 -9
  42. package/corpus/core/src/scripts/runner.ts +6 -3
  43. package/corpus/core/src/secrets/storage.ts +97 -5
  44. package/corpus/core/src/server/action-change.ts +33 -0
  45. package/corpus/core/src/server/action-routes.ts +11 -9
  46. package/corpus/core/src/server/agent-teams.ts +10 -2
  47. package/corpus/core/src/server/better-auth-instance.ts +39 -12
  48. package/corpus/core/src/server/core-routes-plugin.ts +19 -2
  49. package/corpus/core/src/server/credential-provider.ts +57 -14
  50. package/corpus/core/src/server/http-response-telemetry.ts +1 -0
  51. package/corpus/core/src/server/poll.ts +95 -57
  52. package/corpus/core/src/server/voice-providers-status.ts +19 -4
  53. package/corpus/core/src/workspace-files/tool.ts +18 -11
  54. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +38 -0
  55. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +1 -1
  56. package/corpus/templates/analytics/actions/ensure-native-v2-dashboards.ts +299 -0
  57. package/corpus/templates/analytics/actions/list-native-v2-dashboard-templates.ts +34 -0
  58. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +82 -0
  59. package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +2 -2
  60. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +40 -34
  61. package/corpus/templates/analytics/app/hooks/use-user-pref.ts +3 -3
  62. package/corpus/templates/analytics/app/i18n-data.ts +40 -0
  63. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +18 -10
  64. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +14 -0
  65. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +1 -0
  66. package/corpus/templates/analytics/app/routes/chart.tsx +3 -0
  67. package/corpus/templates/analytics/changelog/2026-07-30-analytics-dashboards-now-expose-native-funnel-heatmap-callou.md +6 -0
  68. package/corpus/templates/analytics/changelog/2026-07-30-analytics-now-ships-reusable-native-v2-dashboard-manifests-w.md +6 -0
  69. package/corpus/templates/analytics/server/lib/dashboard-report-render.ts +81 -1
  70. package/corpus/templates/analytics/server/lib/native-v2-dashboards.ts +457 -0
  71. package/corpus/templates/analytics/server/lib/report-chart-svg.ts +73 -2
  72. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -1
  73. package/corpus/templates/analytics/shared/dashboard-funnel.ts +83 -0
  74. package/corpus/templates/clips/actions/generate-workflow.ts +6 -4
  75. package/corpus/templates/clips/actions/reconcile-workflow-generation.ts +257 -0
  76. package/corpus/templates/clips/app/hooks/use-auto-title.ts +166 -4
  77. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -1
  78. package/corpus/templates/clips/changelog/2026-07-27-stopped-agent-runs-no-longer-leave-generated-workflow-cards-.md +6 -0
  79. package/corpus/templates/clips/changelog/2026-07-30-workflow-generation-now-stops-retrying-after-repeated-failur.md +6 -0
  80. package/corpus/templates/clips/shared/workflow.ts +5 -0
  81. package/corpus/templates/content/changelog/2026-07-30-long-running-delegated-requests-now-continue-reliably.md +6 -0
  82. package/corpus/templates/content/netlify.toml +3 -0
  83. package/corpus/templates/content/server/plugins/agent-chat.ts +1 -0
  84. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +2 -1
  85. package/corpus/templates/slides/actions/patch-deck.ts +25 -1
  86. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +17 -4
  87. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +9 -1
  88. package/corpus/templates/slides/app/components/layout/Layout.tsx +1 -1
  89. package/corpus/templates/slides/app/context/DeckContext.tsx +11 -3
  90. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +39 -11
  91. package/corpus/templates/slides/app/pages/Index.tsx +2 -2
  92. package/corpus/templates/slides/changelog/2026-07-30-slide-previews-keep-their-aspect-ratio-isolate-embedded-styl.md +6 -0
  93. package/corpus/templates/slides/changelog/2026-07-30-slides-no-longer-lose-decks-while-organization-access-is-loa.md +6 -0
  94. package/corpus/toolkit/CHANGELOG.md +8 -0
  95. package/corpus/toolkit/package.json +1 -1
  96. package/corpus/toolkit/src/composer/runtime-adapters.tsx +16 -11
  97. package/dist/a2a/activity.d.ts +22 -4
  98. package/dist/a2a/activity.d.ts.map +1 -1
  99. package/dist/a2a/activity.js +97 -11
  100. package/dist/a2a/activity.js.map +1 -1
  101. package/dist/a2a/index.d.ts +1 -1
  102. package/dist/a2a/index.d.ts.map +1 -1
  103. package/dist/a2a/index.js +1 -1
  104. package/dist/a2a/index.js.map +1 -1
  105. package/dist/agent/durable-background.d.ts +13 -8
  106. package/dist/agent/durable-background.d.ts.map +1 -1
  107. package/dist/agent/durable-background.js +36 -28
  108. package/dist/agent/durable-background.js.map +1 -1
  109. package/dist/agent/harness/background.d.ts.map +1 -1
  110. package/dist/agent/harness/background.js +12 -2
  111. package/dist/agent/harness/background.js.map +1 -1
  112. package/dist/agent/production-agent.d.ts.map +1 -1
  113. package/dist/agent/production-agent.js +18 -15
  114. package/dist/agent/production-agent.js.map +1 -1
  115. package/dist/agent/run-store.d.ts +2 -0
  116. package/dist/agent/run-store.d.ts.map +1 -1
  117. package/dist/agent/run-store.js +44 -3
  118. package/dist/agent/run-store.js.map +1 -1
  119. package/dist/application-state/handlers.d.ts +15 -0
  120. package/dist/application-state/handlers.d.ts.map +1 -1
  121. package/dist/application-state/handlers.js +42 -2
  122. package/dist/application-state/handlers.js.map +1 -1
  123. package/dist/application-state/index.d.ts +2 -2
  124. package/dist/application-state/index.d.ts.map +1 -1
  125. package/dist/application-state/index.js +2 -2
  126. package/dist/application-state/index.js.map +1 -1
  127. package/dist/application-state/store.d.ts +11 -0
  128. package/dist/application-state/store.d.ts.map +1 -1
  129. package/dist/application-state/store.js +37 -40
  130. package/dist/application-state/store.js.map +1 -1
  131. package/dist/audit/redact.d.ts +25 -2
  132. package/dist/audit/redact.d.ts.map +1 -1
  133. package/dist/audit/redact.js +85 -21
  134. package/dist/audit/redact.js.map +1 -1
  135. package/dist/cli/create.d.ts +8 -1
  136. package/dist/cli/create.d.ts.map +1 -1
  137. package/dist/cli/create.js +98 -16
  138. package/dist/cli/create.js.map +1 -1
  139. package/dist/client/AgentPanel.d.ts.map +1 -1
  140. package/dist/client/AgentPanel.js +2 -7
  141. package/dist/client/AgentPanel.js.map +1 -1
  142. package/dist/client/AssistantChat.d.ts.map +1 -1
  143. package/dist/client/AssistantChat.js +10 -2
  144. package/dist/client/AssistantChat.js.map +1 -1
  145. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  146. package/dist/client/MultiTabAssistantChat.js +1 -1
  147. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  148. package/dist/client/RunStuckBanner.d.ts +11 -1
  149. package/dist/client/RunStuckBanner.d.ts.map +1 -1
  150. package/dist/client/RunStuckBanner.js +20 -7
  151. package/dist/client/RunStuckBanner.js.map +1 -1
  152. package/dist/client/agent-chat.d.ts.map +1 -1
  153. package/dist/client/agent-chat.js +4 -6
  154. package/dist/client/agent-chat.js.map +1 -1
  155. package/dist/client/application-state.d.ts +11 -0
  156. package/dist/client/application-state.d.ts.map +1 -1
  157. package/dist/client/application-state.js +87 -9
  158. package/dist/client/application-state.js.map +1 -1
  159. package/dist/client/dynamic-suggestions.d.ts.map +1 -1
  160. package/dist/client/dynamic-suggestions.js +4 -13
  161. package/dist/client/dynamic-suggestions.js.map +1 -1
  162. package/dist/client/frame-protocol.d.ts +1 -0
  163. package/dist/client/frame-protocol.d.ts.map +1 -1
  164. package/dist/client/frame-protocol.js.map +1 -1
  165. package/dist/client/guided-questions.d.ts.map +1 -1
  166. package/dist/client/guided-questions.js +6 -22
  167. package/dist/client/guided-questions.js.map +1 -1
  168. package/dist/collab/awareness.d.ts +2 -2
  169. package/dist/collab/awareness.d.ts.map +1 -1
  170. package/dist/collab/routes.d.ts +1 -1
  171. package/dist/db/client.d.ts +57 -10
  172. package/dist/db/client.d.ts.map +1 -1
  173. package/dist/db/client.js +122 -31
  174. package/dist/db/client.js.map +1 -1
  175. package/dist/db/create-get-db.d.ts.map +1 -1
  176. package/dist/db/create-get-db.js +31 -7
  177. package/dist/db/create-get-db.js.map +1 -1
  178. package/dist/db/runtime-diagnostics.d.ts +1 -0
  179. package/dist/db/runtime-diagnostics.d.ts.map +1 -1
  180. package/dist/db/runtime-diagnostics.js +31 -6
  181. package/dist/db/runtime-diagnostics.js.map +1 -1
  182. package/dist/deploy/build.d.ts +5 -20
  183. package/dist/deploy/build.d.ts.map +1 -1
  184. package/dist/deploy/build.js +18 -30
  185. package/dist/deploy/build.js.map +1 -1
  186. package/dist/feature-flags/store.d.ts.map +1 -1
  187. package/dist/feature-flags/store.js +10 -5
  188. package/dist/feature-flags/store.js.map +1 -1
  189. package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
  190. package/dist/integrations/a2a-continuations-store.js +12 -0
  191. package/dist/integrations/a2a-continuations-store.js.map +1 -1
  192. package/dist/integrations/config-store.d.ts +1 -0
  193. package/dist/integrations/config-store.d.ts.map +1 -1
  194. package/dist/integrations/config-store.js +11 -0
  195. package/dist/integrations/config-store.js.map +1 -1
  196. package/dist/integrations/google-docs-poller.d.ts.map +1 -1
  197. package/dist/integrations/google-docs-poller.js +19 -2
  198. package/dist/integrations/google-docs-poller.js.map +1 -1
  199. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  200. package/dist/mcp/screen-memory-stdio.d.ts.map +1 -1
  201. package/dist/mcp-client/routes.d.ts.map +1 -1
  202. package/dist/mcp-client/routes.js +30 -2
  203. package/dist/mcp-client/routes.js.map +1 -1
  204. package/dist/notifications/routes.d.ts +6 -6
  205. package/dist/onboarding/plugin.d.ts.map +1 -1
  206. package/dist/onboarding/plugin.js +12 -8
  207. package/dist/onboarding/plugin.js.map +1 -1
  208. package/dist/org/accept-pending.d.ts.map +1 -1
  209. package/dist/org/accept-pending.js +2 -0
  210. package/dist/org/accept-pending.js.map +1 -1
  211. package/dist/org/auto-join-domain.d.ts.map +1 -1
  212. package/dist/org/auto-join-domain.js +2 -0
  213. package/dist/org/auto-join-domain.js.map +1 -1
  214. package/dist/org/context.d.ts.map +1 -1
  215. package/dist/org/context.js +29 -9
  216. package/dist/org/context.js.map +1 -1
  217. package/dist/org/handlers.d.ts.map +1 -1
  218. package/dist/org/handlers.js +5 -0
  219. package/dist/org/handlers.js.map +1 -1
  220. package/dist/org/request-org-cache.d.ts +16 -0
  221. package/dist/org/request-org-cache.d.ts.map +1 -0
  222. package/dist/org/request-org-cache.js +62 -0
  223. package/dist/org/request-org-cache.js.map +1 -0
  224. package/dist/progress/routes.d.ts +1 -1
  225. package/dist/resources/handlers.d.ts +1 -1
  226. package/dist/resources/store.d.ts.map +1 -1
  227. package/dist/resources/store.js +11 -9
  228. package/dist/resources/store.js.map +1 -1
  229. package/dist/scripts/runner.d.ts.map +1 -1
  230. package/dist/scripts/runner.js +3 -3
  231. package/dist/scripts/runner.js.map +1 -1
  232. package/dist/secrets/storage.d.ts.map +1 -1
  233. package/dist/secrets/storage.js +82 -5
  234. package/dist/secrets/storage.js.map +1 -1
  235. package/dist/server/action-change.d.ts +20 -0
  236. package/dist/server/action-change.d.ts.map +1 -1
  237. package/dist/server/action-change.js +29 -0
  238. package/dist/server/action-change.js.map +1 -1
  239. package/dist/server/action-routes.d.ts.map +1 -1
  240. package/dist/server/action-routes.js +7 -8
  241. package/dist/server/action-routes.js.map +1 -1
  242. package/dist/server/agent-teams.d.ts.map +1 -1
  243. package/dist/server/agent-teams.js +10 -2
  244. package/dist/server/agent-teams.js.map +1 -1
  245. package/dist/server/better-auth-instance.d.ts.map +1 -1
  246. package/dist/server/better-auth-instance.js +31 -14
  247. package/dist/server/better-auth-instance.js.map +1 -1
  248. package/dist/server/core-routes-plugin.d.ts +1 -0
  249. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  250. package/dist/server/core-routes-plugin.js +18 -4
  251. package/dist/server/core-routes-plugin.js.map +1 -1
  252. package/dist/server/credential-provider.d.ts +16 -0
  253. package/dist/server/credential-provider.d.ts.map +1 -1
  254. package/dist/server/credential-provider.js +49 -13
  255. package/dist/server/credential-provider.js.map +1 -1
  256. package/dist/server/http-response-telemetry.d.ts.map +1 -1
  257. package/dist/server/http-response-telemetry.js +1 -0
  258. package/dist/server/http-response-telemetry.js.map +1 -1
  259. package/dist/server/poll.d.ts +6 -0
  260. package/dist/server/poll.d.ts.map +1 -1
  261. package/dist/server/poll.js +84 -47
  262. package/dist/server/poll.js.map +1 -1
  263. package/dist/server/realtime-token.d.ts +1 -1
  264. package/dist/server/voice-providers-status.d.ts.map +1 -1
  265. package/dist/server/voice-providers-status.js +12 -3
  266. package/dist/server/voice-providers-status.js.map +1 -1
  267. package/dist/workspace-files/tool.d.ts.map +1 -1
  268. package/dist/workspace-files/tool.js +18 -11
  269. package/dist/workspace-files/tool.js.map +1 -1
  270. package/docs/content/durable-background-runs.mdx +15 -6
  271. package/docs/design/durable-agent-runs.md +15 -11
  272. package/package.json +3 -3
  273. package/src/a2a/activity.ts +127 -10
  274. package/src/a2a/index.ts +3 -0
  275. package/src/agent/durable-background.ts +38 -28
  276. package/src/agent/harness/background.ts +12 -2
  277. package/src/agent/production-agent.ts +18 -15
  278. package/src/agent/run-store.ts +45 -3
  279. package/src/application-state/handlers.ts +45 -0
  280. package/src/application-state/index.ts +3 -0
  281. package/src/application-state/store.ts +38 -34
  282. package/src/audit/redact.ts +104 -18
  283. package/src/cli/create.ts +115 -16
  284. package/src/client/AgentPanel.tsx +2 -7
  285. package/src/client/AssistantChat.tsx +10 -2
  286. package/src/client/MultiTabAssistantChat.tsx +3 -0
  287. package/src/client/RunStuckBanner.tsx +29 -6
  288. package/src/client/agent-chat.ts +4 -9
  289. package/src/client/application-state.ts +115 -12
  290. package/src/client/dynamic-suggestions.ts +4 -12
  291. package/src/client/frame-protocol.ts +5 -1
  292. package/src/client/guided-questions.tsx +12 -23
  293. package/src/db/client.ts +148 -28
  294. package/src/db/create-get-db.ts +39 -6
  295. package/src/db/runtime-diagnostics.ts +41 -6
  296. package/src/deploy/build.ts +26 -33
  297. package/src/feature-flags/store.ts +10 -5
  298. package/src/integrations/a2a-continuations-store.ts +11 -0
  299. package/src/integrations/config-store.ts +13 -0
  300. package/src/integrations/google-docs-poller.ts +26 -2
  301. package/src/mcp-client/routes.ts +33 -2
  302. package/src/onboarding/plugin.ts +31 -25
  303. package/src/org/accept-pending.ts +2 -0
  304. package/src/org/auto-join-domain.ts +2 -0
  305. package/src/org/context.ts +35 -10
  306. package/src/org/handlers.ts +6 -0
  307. package/src/org/request-org-cache.ts +71 -0
  308. package/src/resources/store.ts +10 -9
  309. package/src/scripts/runner.ts +6 -3
  310. package/src/secrets/storage.ts +97 -5
  311. package/src/server/action-change.ts +33 -0
  312. package/src/server/action-routes.ts +11 -9
  313. package/src/server/agent-teams.ts +10 -2
  314. package/src/server/better-auth-instance.ts +39 -12
  315. package/src/server/core-routes-plugin.ts +19 -2
  316. package/src/server/credential-provider.ts +57 -14
  317. package/src/server/http-response-telemetry.ts +1 -0
  318. package/src/server/poll.ts +95 -57
  319. package/src/server/voice-providers-status.ts +19 -4
  320. package/src/workspace-files/tool.ts +18 -11
@@ -947,6 +947,10 @@ const enUS = {
947
947
  chartTypePie: "Pie",
948
948
  chartTypeMetric: "Metric",
949
949
  chartTypeTable: "Table",
950
+ chartTypeFunnel: "Funnel",
951
+ chartTypeHeatmap: "Heatmap",
952
+ chartTypeCallout: "Callout",
953
+ chartTypeSection: "Section",
950
954
  chartTypeExtension: "Custom visualization",
951
955
  failedToSavePanel: "Failed to save panel",
952
956
  failedToFormatSql: "Failed to format SQL",
@@ -1416,6 +1420,10 @@ const analyticsSliceTranslations: {
1416
1420
  chartTypePie: "馅饼",
1417
1421
  chartTypeMetric: "公制",
1418
1422
  chartTypeTable: "桌子",
1423
+ chartTypeFunnel: "漏斗",
1424
+ chartTypeHeatmap: "热力图",
1425
+ chartTypeCallout: "提示",
1426
+ chartTypeSection: "分区",
1419
1427
  chartTypeExtension: "自定义可视化",
1420
1428
  failedToSavePanel: "保存面板失败",
1421
1429
  failedToFormatSql: "格式化SQL失败",
@@ -1716,6 +1724,10 @@ const analyticsSliceTranslations: {
1716
1724
  chartTypePie: "Pastel",
1717
1725
  chartTypeMetric: "Métrico",
1718
1726
  chartTypeTable: "Mesa",
1727
+ chartTypeFunnel: "Embudo",
1728
+ chartTypeHeatmap: "Mapa de calor",
1729
+ chartTypeCallout: "Aviso",
1730
+ chartTypeSection: "Sección",
1719
1731
  chartTypeExtension: "Visualización personalizada",
1720
1732
  failedToSavePanel: "No se pudo guardar el panel",
1721
1733
  failedToFormatSql: "No se pudo formatear SQL",
@@ -2033,6 +2045,10 @@ const analyticsSliceTranslations: {
2033
2045
  chartTypePie: "Tarte",
2034
2046
  chartTypeMetric: "Métrique",
2035
2047
  chartTypeTable: "Tableau",
2048
+ chartTypeFunnel: "Entonnoir",
2049
+ chartTypeHeatmap: "Carte thermique",
2050
+ chartTypeCallout: "Alerte",
2051
+ chartTypeSection: "Section",
2036
2052
  chartTypeExtension: "Visualisation personnalisée",
2037
2053
  failedToSavePanel: "Échec de l'enregistrement du panneau",
2038
2054
  failedToFormatSql: "Échec du formatage du SQL",
@@ -2348,6 +2364,10 @@ const analyticsSliceTranslations: {
2348
2364
  chartTypePie: "Torte",
2349
2365
  chartTypeMetric: "Metrisch",
2350
2366
  chartTypeTable: "Tisch",
2367
+ chartTypeFunnel: "Trichter",
2368
+ chartTypeHeatmap: "Heatmap",
2369
+ chartTypeCallout: "Hinweis",
2370
+ chartTypeSection: "Abschnitt",
2351
2371
  chartTypeExtension: "Benutzerdefinierte Visualisierung",
2352
2372
  failedToSavePanel: "Das Panel konnte nicht gespeichert werden",
2353
2373
  failedToFormatSql: "SQL konnte nicht formatiert werden",
@@ -2658,6 +2678,10 @@ const analyticsSliceTranslations: {
2658
2678
  chartTypePie: "パイ",
2659
2679
  chartTypeMetric: "メトリック",
2660
2680
  chartTypeTable: "テーブル",
2681
+ chartTypeFunnel: "ファネル",
2682
+ chartTypeHeatmap: "ヒートマップ",
2683
+ chartTypeCallout: "コールアウト",
2684
+ chartTypeSection: "セクション",
2661
2685
  chartTypeExtension: "カスタム可視化",
2662
2686
  failedToSavePanel: "パネルの保存に失敗しました",
2663
2687
  failedToFormatSql: "SQLのフォーマットに失敗しました",
@@ -2962,6 +2986,10 @@ const analyticsSliceTranslations: {
2962
2986
  chartTypePie: "파이",
2963
2987
  chartTypeMetric: "미터법",
2964
2988
  chartTypeTable: "테이블",
2989
+ chartTypeFunnel: "퍼널",
2990
+ chartTypeHeatmap: "히트맵",
2991
+ chartTypeCallout: "콜아웃",
2992
+ chartTypeSection: "섹션",
2965
2993
  chartTypeExtension: "사용자 지정 시각화",
2966
2994
  failedToSavePanel: "패널을 저장하지 못했습니다.",
2967
2995
  failedToFormatSql: "SQL 포맷 실패",
@@ -3266,6 +3294,10 @@ const analyticsSliceTranslations: {
3266
3294
  chartTypePie: "Torta",
3267
3295
  chartTypeMetric: "Métrica",
3268
3296
  chartTypeTable: "Mesa",
3297
+ chartTypeFunnel: "Funil",
3298
+ chartTypeHeatmap: "Mapa de calor",
3299
+ chartTypeCallout: "Destaque",
3300
+ chartTypeSection: "Seção",
3269
3301
  chartTypeExtension: "Visualização personalizada",
3270
3302
  failedToSavePanel: "Falha ao salvar painel",
3271
3303
  failedToFormatSql: "Falha ao formatar SQL",
@@ -3572,6 +3604,10 @@ const analyticsSliceTranslations: {
3572
3604
  chartTypePie: "पाई",
3573
3605
  chartTypeMetric: "मीट्रिक",
3574
3606
  chartTypeTable: "मेज़",
3607
+ chartTypeFunnel: "फ़नल",
3608
+ chartTypeHeatmap: "हीटमैप",
3609
+ chartTypeCallout: "कॉलआउट",
3610
+ chartTypeSection: "अनुभाग",
3575
3611
  chartTypeExtension: "कस्टम विज़ुअलाइज़ेशन",
3576
3612
  failedToSavePanel: "पैनल सहेजने में विफल",
3577
3613
  failedToFormatSql: "SQL को फ़ॉर्मेट करने में विफल",
@@ -3871,6 +3907,10 @@ const analyticsSliceTranslations: {
3871
3907
  chartTypePie: "فطيرة",
3872
3908
  chartTypeMetric: "متري",
3873
3909
  chartTypeTable: "طاولة",
3910
+ chartTypeFunnel: "مسار تحويل",
3911
+ chartTypeHeatmap: "خريطة حرارية",
3912
+ chartTypeCallout: "تنبيه",
3913
+ chartTypeSection: "قسم",
3874
3914
  chartTypeExtension: "عرض مرئي مخصص",
3875
3915
  failedToSavePanel: "فشل حفظ اللوحة",
3876
3916
  failedToFormatSql: "فشل تهيئة SQL",
@@ -57,6 +57,10 @@ const CHART_TYPES: { value: ChartType; labelKey: string }[] = [
57
57
  { value: "pie", labelKey: "panelEditor.chartTypePie" },
58
58
  { value: "metric", labelKey: "panelEditor.chartTypeMetric" },
59
59
  { value: "table", labelKey: "panelEditor.chartTypeTable" },
60
+ { value: "funnel", labelKey: "panelEditor.chartTypeFunnel" },
61
+ { value: "heatmap", labelKey: "panelEditor.chartTypeHeatmap" },
62
+ { value: "callout", labelKey: "panelEditor.chartTypeCallout" },
63
+ { value: "section", labelKey: "panelEditor.chartTypeSection" },
60
64
  { value: "extension", labelKey: "panelEditor.chartTypeExtension" },
61
65
  ];
62
66
 
@@ -290,6 +294,7 @@ function PanelEditorContent({
290
294
 
291
295
  const isEdit = !!panel;
292
296
  const isExtensionPanel = form.chartType === "extension";
297
+ const isSectionPanel = form.chartType === "section";
293
298
  const isProgramSource = form.source === "program";
294
299
  const { programId, paramsText: initialParamsText } = useMemo(
295
300
  () =>
@@ -332,10 +337,13 @@ function PanelEditorContent({
332
337
  const canSave = isExtensionPanel
333
338
  ? form.title.trim().length > 0 &&
334
339
  (form.extensionMode === "slot" || form.extensionId.trim().length > 0)
335
- : isProgramSource
336
- ? form.title.trim().length > 0 && selectedProgramId.trim().length > 0
337
- : form.title.trim().length > 0 && form.sql.trim().length > 0;
338
- const canFormat = !isExtensionPanel && canFormatPanelSql(form.source);
340
+ : isSectionPanel
341
+ ? form.title.trim().length > 0
342
+ : isProgramSource
343
+ ? form.title.trim().length > 0 && selectedProgramId.trim().length > 0
344
+ : form.title.trim().length > 0 && form.sql.trim().length > 0;
345
+ const canFormat =
346
+ !isExtensionPanel && !isSectionPanel && canFormatPanelSql(form.source);
339
347
 
340
348
  const handleSubmit = async () => {
341
349
  if (!canSave || saving) return;
@@ -343,7 +351,7 @@ function PanelEditorContent({
343
351
  setError(null);
344
352
  try {
345
353
  let sqlForSave = form.sql;
346
- if (isProgramSource) {
354
+ if (isProgramSource && !isSectionPanel) {
347
355
  try {
348
356
  sqlForSave = serializeProgramDescriptor(
349
357
  selectedProgramId,
@@ -388,7 +396,7 @@ function PanelEditorContent({
388
396
  `If no source can answer, report the exact unavailable/error result instead of saving a panel with guessed schema or metrics. ` +
389
397
  `Use the \`mutate-dashboard\` action with code like \`dashboard.insertPanel({"id":"new-panel","title":"New Panel","source":"first-party","chartType":"metric","width":1,"sql":"SELECT COUNT(*) AS value FROM analytics_events"}).atBottom();\` ` +
390
398
  `to append, or \`.nextTo("panel-id")\`, \`.atRow(2)\`, \`.atRowStart(2)\`, \`.before("panel-id")\`, \`.after("panel-id")\`, or \`.atIndex(n)\` to place the panel. Prefer \`.nextTo("panel-id")\` or \`.atRow(rowNumber)\` for visible row placement requests; they keep the chart in the intended rendered row and expand/rebalance that row when needed. ` +
391
- `Panel shape: { id (unique slug), title, sql, source ('bigquery'|'ga4'|'amplitude'|'first-party'|'demo'|'prometheus'|'program'), chartType ('line'|'area'|'bar'|'metric'|'table'|'pie'|'section'|'extension'), width (legacy integer 1..6; set to 1 unless editing existing data), tab? (use 'Group / Tab' for grouped tabs), columns? (section panels only - 1..6 max panels per row for panels following this section), config? }. ` +
399
+ `Panel shape: { id (unique slug), title, sql, source ('bigquery'|'ga4'|'amplitude'|'first-party'|'demo'|'prometheus'|'program'), chartType ('line'|'area'|'bar'|'metric'|'table'|'pie'|'funnel'|'heatmap'|'callout'|'section'|'extension'), width (legacy integer 1..6; set to 1 unless editing existing data), tab? (use 'Group / Tab' for grouped tabs), columns? (section panels only - 1..6 max panels per row for panels following this section), config? }. ` +
392
400
  `Visible layout auto-fits by row: one panel in a row spans the row, two split it, three split it into thirds, up to the section column limit. ` +
393
401
  `For amplitude panels, sql is a JSON descriptor: {"event":"event name","groupBy":"property","days":30}. ` +
394
402
  `For first-party panels, sql is read-only SQL over analytics_events only; use source 'first-party' and do not call db-query for this datasource. ` +
@@ -396,8 +404,8 @@ function PanelEditorContent({
396
404
  `For prometheus panels, sql is a JSON descriptor: {"promql":"rate(http_requests_total[5m])","mode":"range","range":"1h","step":"30s"}. mode defaults to "range"; range defaults to "1h"; step is auto if omitted. Returned rows have shape {timestamp, series, value} — set config.xKey="timestamp", config.yKey="value", and a single series in config.yKeys for clean charting. ` +
397
405
  `For program panels (arbitrary provider data joins/cohorts not expressible in the other sources), first save-data-program (or reuse an existing one via list-data-programs), then set sql to a JSON descriptor: {"programId":"<id>","params":{...}}. See the data-programs skill for the emit(rows, schema) contract and the Risk Meeting worked example. ` +
398
406
  `Native dashboard panels and Data Programs come first. Add an extension panel only when the user explicitly asks for a genuinely bespoke, one-off Custom Block for this dashboard and native panels cannot represent it faithfully. For a reusable/native capability call connect-builder instead. New agent-authored Custom Blocks use config.extensionId plus config.customBlock={authoredBy:"agent",intent:"one-off",scope:"dashboard",nativeGapReason:"custom-visualization"|"custom-interaction"|"custom-layout"|"other"}; never put prompt/customer text in that metadata. Use config.extensionSlotId only when the user explicitly asks for a personal/per-viewer slot; slot installs are per-user and automated report identities may have no install. ` +
399
- `Config is optional: { xKey, yKey, yKeys, yFormatter ('number'|'currency'|'percent'), rightYKeys, rightYFormatter, description, columns, pivot, limit, color, colors, stacked, legend, valueLabels }. ` +
400
- `For line/area/bar series that share an x-axis but not a unit (a count next to a rate), put the smaller-unit series on a second y-axis with config.rightYKeys (a subset of yKeys) and an optional config.rightYFormatter — do not build an extension for a dual-axis chart. ` +
407
+ `Config is optional: { xKey, yKey, yKeys, yFormatter ('number'|'currency'|'percent'), rightYKeys, rightYFormatter, description, columns, pivot, limit, color, colors, stacked, legend, valueLabels }. For funnel panels, use config.xKey for the stage label, config.yKey for the non-negative count/value, and keep the SQL ORDER BY in the intended funnel order. ` +
408
+ `For line/area/bar series that share an x-axis but not a unit (a count next to a rate), put the smaller-unit series on a second y-axis with config.rightYKeys (a subset of yKeys) and an optional config.rightYFormatter — do not build an extension for a dual-axis chart. Use heatmap, callout, and section panels when their native contracts fit; do not create a Custom Block for a supported native panel. ` +
401
409
  `Chart legends render automatically; set config.legend=false only when the user explicitly asks to hide the legend. ` +
402
410
  `Use \`get-sql-dashboard.layout.groups[].rows[].rowNumber/panelIds\` to identify and verify visible rows. ` +
403
411
  `Consult the data dictionary first via \`list-data-dictionary --search <topic>\`, then use AGENTS.md, .agents/skills, and connected data-source instructions before writing SQL. ` +
@@ -455,7 +463,7 @@ function PanelEditorContent({
455
463
  </Select>
456
464
  </div>
457
465
 
458
- {!isExtensionPanel ? (
466
+ {!isExtensionPanel && !isSectionPanel ? (
459
467
  <div className="grid gap-1.5">
460
468
  <Label htmlFor="panel-source">{t("panelEditor.source")}</Label>
461
469
  <Select
@@ -600,7 +608,7 @@ function PanelEditorContent({
600
608
  </div>
601
609
  )}
602
610
  </div>
603
- ) : isProgramSource ? (
611
+ ) : isSectionPanel ? null : isProgramSource ? (
604
612
  <div className="grid gap-4">
605
613
  <div className="grid gap-1.5">
606
614
  <Label htmlFor="panel-program">
@@ -178,6 +178,15 @@ type DashboardTabGroup = {
178
178
  tabs: Array<{ value: string; label: string }>;
179
179
  };
180
180
 
181
+ function sameFilterMap(
182
+ a: Record<string, string> | undefined,
183
+ b: Record<string, string>,
184
+ ): boolean {
185
+ const aKeys = Object.keys(a ?? {});
186
+ if (aKeys.length !== Object.keys(b).length) return false;
187
+ return aKeys.every((key) => a![key] === b[key]);
188
+ }
189
+
181
190
  function groupDashboardTabs(tabs: string[]): {
182
191
  groups: DashboardTabGroup[];
183
192
  hasNestedTabs: boolean;
@@ -1013,6 +1022,10 @@ function SqlDashboardPageContent({
1013
1022
  currentFilters[k] = v;
1014
1023
  }
1015
1024
  });
1025
+ // Opening a dashboard restores the saved filters into the URL, so
1026
+ // without this the mere act of loading a page writes the value back —
1027
+ // one round-trip plus a sync event that invalidates every mounted query.
1028
+ if (sameFilterMap(savedFilters?.filters, currentFilters)) return;
1016
1029
  saveFilterPref({ filters: currentFilters });
1017
1030
  }, 1500);
1018
1031
  return () => clearTimeout(saveTimer.current);
@@ -1021,6 +1034,7 @@ function SqlDashboardPageContent({
1021
1034
  loaded,
1022
1035
  dashboard?.filters,
1023
1036
  dashboardId,
1037
+ savedFilters,
1024
1038
  saveFilterPref,
1025
1039
  reportScreenshot,
1026
1040
  ]);
@@ -15,6 +15,7 @@ export type ChartType =
15
15
  | "table"
16
16
  | "pie"
17
17
  | "section"
18
+ | "funnel"
18
19
  | "heatmap"
19
20
  | "callout"
20
21
  | "extension";
@@ -16,6 +16,9 @@ const VALID_CHART_TYPES = new Set([
16
16
  "metric",
17
17
  "table",
18
18
  "pie",
19
+ "funnel",
20
+ "heatmap",
21
+ "callout",
19
22
  ]);
20
23
  // Embed URLs accept external sources plus the restricted first-party analytics
21
24
  // source. They intentionally do not expose arbitrary app database querying.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-30
4
+ ---
5
+
6
+ Analytics dashboards now expose native funnel, heatmap, callout, and section panels.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-30
4
+ ---
5
+
6
+ Analytics now ships reusable native v2 dashboard manifests with an admin provisioning action for real Data Program bindings.
@@ -13,6 +13,7 @@ import type {
13
13
  SqlPanel,
14
14
  TableColumnConfig,
15
15
  } from "../../app/pages/adhoc/sql-dashboard/types";
16
+ import { resolveDashboardFunnelRows } from "../../shared/dashboard-funnel";
16
17
  import { DASHBOARD_REPORT_ACTION_TIMEOUT_MS } from "../../shared/dashboard-report-timeouts.js";
17
18
  import {
18
19
  MAX_CONCURRENT_FIRST_PARTY_SQL_QUERIES,
@@ -25,6 +26,7 @@ import {
25
26
  import { resolveAnalyticsPanelSource } from "./dashboard-panel-source-resolver";
26
27
  import {
27
28
  renderReportChartSvg,
29
+ renderFunnelChartSvg,
28
30
  REPORT_CHART_FONT_FAMILY,
29
31
  type ReportChartSeries,
30
32
  type ReportChartType,
@@ -534,6 +536,7 @@ const REPORT_CHART_TYPES: Record<string, ReportChartType> = {
534
536
  line: "line",
535
537
  area: "area",
536
538
  pie: "pie",
539
+ funnel: "funnel",
537
540
  "stacked-bar": "bar",
538
541
  "stacked-area": "area",
539
542
  };
@@ -923,7 +926,7 @@ async function renderChartBlock(args: {
923
926
  panel: SqlPanel;
924
927
  rows: Array<Record<string, unknown>>;
925
928
  forcedYKeys?: string[];
926
- chartType: ReportChartType;
929
+ chartType: Exclude<ReportChartType, "funnel">;
927
930
  index: number;
928
931
  description: string;
929
932
  }): Promise<PanelBlock> {
@@ -997,6 +1000,72 @@ async function renderChartBlock(args: {
997
1000
  }
998
1001
  }
999
1002
 
1003
+ async function renderFunnelChartBlock(args: {
1004
+ panel: SqlPanel;
1005
+ rows: Array<Record<string, unknown>>;
1006
+ index: number;
1007
+ description: string;
1008
+ }): Promise<PanelBlock> {
1009
+ const { panel, rows, index, description } = args;
1010
+ const funnel = resolveDashboardFunnelRows(
1011
+ rows,
1012
+ panel.config?.xKey,
1013
+ panel.config?.yKey,
1014
+ );
1015
+ if (funnel.items.length === 0) {
1016
+ const table = renderTableHtml(panel, rows);
1017
+ return {
1018
+ panelId: panel.id,
1019
+ html: panelCardHtml(
1020
+ panel,
1021
+ `${table.html}${noteHtml("No funnel stages were returned, so the rows are shown as a table.")}`,
1022
+ ),
1023
+ text: `${panel.title}\n${table.text}`,
1024
+ };
1025
+ }
1026
+
1027
+ const subtitle = description;
1028
+ const alt = `funnel chart of ${funnel.items.map((item) => item.label).join(", ")}`;
1029
+ try {
1030
+ const svg = renderFunnelChartSvg({
1031
+ title: "",
1032
+ subtitle,
1033
+ rows: funnel.items,
1034
+ width: CHART_WIDTH,
1035
+ height: CHART_HEIGHT,
1036
+ formatter: panel.config?.yFormatter,
1037
+ colors: panel.config?.colors,
1038
+ });
1039
+ const png = await rasterizeChartPng(svg, CHART_WIDTH * CHART_RASTER_SCALE);
1040
+ const slug =
1041
+ panel.id.replace(/[^A-Za-z0-9_-]/g, "-").slice(0, 40) || "panel";
1042
+ const contentId = `dashboard-report-panel-${index}-${slug}`;
1043
+ return {
1044
+ panelId: panel.id,
1045
+ html: panelCardHtml(
1046
+ panel,
1047
+ `<img src="cid:${contentId}" alt="${escapeHtml(alt)}" width="${CHART_WIDTH}" style="display:block;width:100%;max-width:${CHART_WIDTH}px;height:auto;border:0;" />`,
1048
+ ),
1049
+ text: `${panel.title}: chart attached${subtitle ? ` (${subtitle})` : ""}`,
1050
+ attachment: {
1051
+ filename: `${slug}.png`,
1052
+ content: png,
1053
+ contentType: "image/png",
1054
+ contentId,
1055
+ disposition: "inline",
1056
+ },
1057
+ };
1058
+ } catch (error) {
1059
+ return failureBlock(
1060
+ panel,
1061
+ "Chart rendering failed",
1062
+ error instanceof Error
1063
+ ? error.message
1064
+ : "The funnel image could not be rendered.",
1065
+ );
1066
+ }
1067
+ }
1068
+
1000
1069
  function enforceAttachmentBudget(blocks: PanelBlock[]): void {
1001
1070
  const totalBytes = () =>
1002
1071
  blocks.reduce(
@@ -1093,6 +1162,17 @@ export async function renderReportEmail(args: {
1093
1162
  const chartType: ReportChartType | undefined =
1094
1163
  REPORT_CHART_TYPES[panel.chartType];
1095
1164
  if (chartType) {
1165
+ if (chartType === "funnel") {
1166
+ const block = await renderFunnelChartBlock({
1167
+ panel,
1168
+ rows,
1169
+ index: chartIndex++,
1170
+ description,
1171
+ });
1172
+ if (truncatedNote) block.html += truncatedNote;
1173
+ blocks.push(block);
1174
+ continue;
1175
+ }
1096
1176
  const block = await renderChartBlock({
1097
1177
  panel,
1098
1178
  rows,