@agent-native/core 0.92.6 → 0.92.8

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 (297) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +18 -0
  3. package/corpus/core/docs/content/a2a-protocol.mdx +12 -0
  4. package/corpus/core/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
  5. package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
  6. package/corpus/core/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
  7. package/corpus/core/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
  8. package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
  9. package/corpus/core/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
  10. package/corpus/core/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
  11. package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
  12. package/corpus/core/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
  13. package/corpus/core/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
  14. package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
  15. package/corpus/core/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
  16. package/corpus/core/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
  17. package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
  18. package/corpus/core/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
  19. package/corpus/core/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
  20. package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
  21. package/corpus/core/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
  22. package/corpus/core/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
  23. package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
  24. package/corpus/core/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
  25. package/corpus/core/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
  26. package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
  27. package/corpus/core/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
  28. package/corpus/core/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
  29. package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
  30. package/corpus/core/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
  31. package/corpus/core/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
  32. package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
  33. package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
  34. package/corpus/core/docs/content/pr-visual-recap.mdx +3 -3
  35. package/corpus/core/docs/content/pure-agent-apps.mdx +22 -0
  36. package/corpus/core/package.json +1 -1
  37. package/corpus/core/src/agent/engine/builtin.ts +1 -1
  38. package/corpus/core/src/agent/model-config.ts +30 -30
  39. package/corpus/core/src/agent/production-agent.ts +129 -7
  40. package/corpus/core/src/cli/design-connect.ts +438 -83
  41. package/corpus/core/src/cli/recap.ts +2 -2
  42. package/corpus/core/src/cli/sync-builder-starter-manifest.ts +1 -1
  43. package/corpus/core/src/client/AgentPanel.tsx +8 -1
  44. package/corpus/core/src/client/agent-chat-adapter.ts +12 -7
  45. package/corpus/core/src/client/composer/TiptapComposer.tsx +1 -1
  46. package/corpus/core/src/client/index.ts +4 -0
  47. package/corpus/core/src/client/org/TeamPage.tsx +41 -26
  48. package/corpus/core/src/client/use-action.ts +113 -1
  49. package/corpus/core/src/db/client.ts +12 -2
  50. package/corpus/core/src/db/create-get-db.ts +4 -1
  51. package/corpus/core/src/scripts/agent-engines/manage-agent-engine.ts +1 -1
  52. package/corpus/core/src/scripts/agent-engines/set-agent-engine.ts +1 -1
  53. package/corpus/core/src/server/transcribe-voice.ts +1 -1
  54. package/corpus/core/src/usage/store.ts +13 -4
  55. package/corpus/core/src/vite/client.ts +38 -1
  56. package/corpus/templates/analytics/AGENTS.md +3 -0
  57. package/corpus/templates/analytics/actions/get-data-program.ts +78 -0
  58. package/corpus/templates/analytics/actions/list-data-programs.ts +49 -0
  59. package/corpus/templates/analytics/app/global.css +11 -0
  60. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +163 -17
  61. package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
  62. package/corpus/templates/analytics/app/i18n-data.ts +20 -0
  63. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +96 -3
  64. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -1
  65. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +61 -4
  66. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +40 -2
  67. package/corpus/templates/analytics/changelog/2026-07-09-analytics-no-longer-forgets-successful-data-queries-when-a-l.md +6 -0
  68. package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-keep-consistent-spacing-when-they-stack-ver.md +6 -0
  69. package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-tables-and-extensions-can-be-selected-and-d.md +6 -0
  70. package/corpus/templates/analytics/changelog/2026-07-09-long-running-analytics-requests-now-recover-automatically-wh.md +6 -0
  71. package/corpus/templates/analytics/server/db/index.ts +6 -0
  72. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +1 -7
  73. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +102 -15
  74. package/corpus/templates/content/app/hooks/use-content-database.ts +52 -0
  75. package/corpus/templates/content/app/hooks/use-document-properties.ts +50 -6
  76. package/corpus/templates/content/app/i18n/zh-TW.ts +2 -0
  77. package/corpus/templates/content/app/i18n-data.ts +28 -0
  78. package/corpus/templates/content/changelog/2026-07-09-notion-conflict-warnings-no-longer-flash-during-normal-synce.md +6 -0
  79. package/corpus/templates/content/changelog/2026-07-09-property-menus-and-delete-confirmations-now-open-visibly-and.md +6 -0
  80. package/corpus/templates/content/server/lib/notion-sync.ts +130 -28
  81. package/corpus/templates/design/actions/add-breakpoint.ts +48 -68
  82. package/corpus/templates/design/actions/add-localhost-screens.ts +496 -61
  83. package/corpus/templates/design/actions/apply-component-prop-edit.ts +2 -18
  84. package/corpus/templates/design/actions/apply-design-token-edit.ts +51 -82
  85. package/corpus/templates/design/actions/apply-tweaks.ts +63 -41
  86. package/corpus/templates/design/actions/capture-design-state.ts +2 -2
  87. package/corpus/templates/design/actions/connect-localhost.ts +58 -12
  88. package/corpus/templates/design/actions/create-component.ts +2 -18
  89. package/corpus/templates/design/actions/create-design-branch.ts +38 -18
  90. package/corpus/templates/design/actions/create-fusion-app.ts +15 -11
  91. package/corpus/templates/design/actions/delete-file.ts +19 -34
  92. package/corpus/templates/design/actions/deploy-design-preview.ts +59 -27
  93. package/corpus/templates/design/actions/deploy-fusion-app.ts +22 -15
  94. package/corpus/templates/design/actions/export-pdf.ts +2 -1
  95. package/corpus/templates/design/actions/export-zip.ts +9 -3
  96. package/corpus/templates/design/actions/generate-design.ts +107 -70
  97. package/corpus/templates/design/actions/get-component-details.ts +2 -18
  98. package/corpus/templates/design/actions/get-design-branch-diff.ts +2 -3
  99. package/corpus/templates/design/actions/get-design-surface-index.ts +2 -18
  100. package/corpus/templates/design/actions/get-design.ts +2 -1
  101. package/corpus/templates/design/actions/grant-localhost-write-consent.ts +7 -1
  102. package/corpus/templates/design/actions/import-design-tokens.ts +114 -76
  103. package/corpus/templates/design/actions/index-components.ts +2 -18
  104. package/corpus/templates/design/actions/list-design-source-capabilities.ts +23 -28
  105. package/corpus/templates/design/actions/list-local-files.ts +9 -2
  106. package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +82 -98
  107. package/corpus/templates/design/actions/open-component-source.ts +2 -18
  108. package/corpus/templates/design/actions/open-visual-edit.ts +19 -1
  109. package/corpus/templates/design/actions/present-design-variants.ts +70 -70
  110. package/corpus/templates/design/actions/preview-component-prop-edit.ts +4 -14
  111. package/corpus/templates/design/actions/read-local-file.ts +9 -2
  112. package/corpus/templates/design/actions/remove-breakpoint.ts +40 -61
  113. package/corpus/templates/design/actions/rename-screen.ts +425 -0
  114. package/corpus/templates/design/actions/request-localhost-write-consent.ts +12 -2
  115. package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +9 -2
  116. package/corpus/templates/design/actions/sync-fusion-app.ts +56 -39
  117. package/corpus/templates/design/actions/update-design.ts +376 -61
  118. package/corpus/templates/design/actions/update-file.ts +455 -188
  119. package/corpus/templates/design/actions/write-local-file.ts +10 -2
  120. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +685 -608
  121. package/corpus/templates/design/app/components/design/LayersPanel.tsx +43 -15
  122. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +576 -2015
  123. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +62 -14
  124. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +263 -25
  125. package/corpus/templates/design/app/components/design/design-canvas/annotation-submit.ts +34 -0
  126. package/corpus/templates/design/app/components/design/design-canvas/coordinate-transforms.ts +40 -0
  127. package/corpus/templates/design/app/components/design/design-canvas/creation.ts +47 -0
  128. package/corpus/templates/design/app/components/design/design-canvas/element-payload.ts +27 -0
  129. package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +62 -0
  130. package/corpus/templates/design/app/components/design/design-canvas/external-preview.ts +137 -0
  131. package/corpus/templates/design/app/components/design/design-canvas/file-drop.ts +10 -0
  132. package/corpus/templates/design/app/components/design/design-canvas/hit-test.ts +23 -0
  133. package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +23 -0
  134. package/corpus/templates/design/app/components/design/design-canvas/iframe-pan.ts +177 -0
  135. package/corpus/templates/design/app/components/design/design-canvas/motion-types.ts +7 -0
  136. package/corpus/templates/design/app/components/design/design-canvas/pending-text-edit.ts +62 -0
  137. package/corpus/templates/design/app/components/design/index.ts +2 -2
  138. package/corpus/templates/design/app/components/design/multi-screen/canvas-tools.ts +100 -0
  139. package/corpus/templates/design/app/components/design/multi-screen/coordinate-transforms.ts +81 -0
  140. package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +23 -13
  141. package/corpus/templates/design/app/components/design/multi-screen/culling.ts +238 -19
  142. package/corpus/templates/design/app/components/design/multi-screen/draft-primitives.ts +424 -0
  143. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +341 -0
  144. package/corpus/templates/design/app/components/design/multi-screen/iframe-targeting.ts +52 -0
  145. package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +62 -0
  146. package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +283 -0
  147. package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +272 -0
  148. package/corpus/templates/design/app/components/design/multi-screen/types.ts +5 -1
  149. package/corpus/templates/design/app/components/design/multi-screen/wheel-gesture-state.ts +12 -0
  150. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +325 -84
  151. package/corpus/templates/design/app/hooks/use-navigation-state.ts +15 -1
  152. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +119 -47
  153. package/corpus/templates/design/app/i18n/zh-TW.ts +9 -0
  154. package/corpus/templates/design/app/i18n-data.ts +223 -0
  155. package/corpus/templates/design/app/lib/design-save-outbox.ts +379 -0
  156. package/corpus/templates/design/app/lib/png-clipboard.ts +113 -0
  157. package/corpus/templates/design/app/pages/design-editor/canvas-primitives.ts +229 -0
  158. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +918 -0
  159. package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +43 -0
  160. package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +336 -0
  161. package/corpus/templates/design/app/pages/design-editor/data-operations.ts +270 -0
  162. package/corpus/templates/design/app/pages/design-editor/dom-guards.ts +24 -0
  163. package/corpus/templates/design/app/pages/design-editor/dom-utils.ts +11 -0
  164. package/corpus/templates/design/app/pages/design-editor/editor-session.ts +20 -0
  165. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +408 -0
  166. package/corpus/templates/design/app/pages/design-editor/export-capture.ts +115 -0
  167. package/corpus/templates/design/app/pages/design-editor/geometry-persistence.ts +93 -0
  168. package/corpus/templates/design/app/pages/design-editor/history.ts +169 -0
  169. package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +185 -0
  170. package/corpus/templates/design/app/pages/design-editor/motion-state.ts +309 -0
  171. package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +438 -0
  172. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +510 -0
  173. package/corpus/templates/design/app/pages/design-editor/portable-style.ts +115 -0
  174. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +337 -0
  175. package/corpus/templates/design/app/pages/design-editor/style-utils.ts +5 -0
  176. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +92 -0
  177. package/corpus/templates/design/app/pages/design-editor/tweak-save.ts +87 -0
  178. package/corpus/templates/design/app/pages/design-editor/types.ts +36 -0
  179. package/corpus/templates/design/app/routes/design.$id.tsx +11 -1
  180. package/corpus/templates/design/changelog/2026-07-09-design-edits-canvas-positions-tools-and-tab-context-now-pers.md +6 -0
  181. package/corpus/templates/design/changelog/2026-07-09-figma-style-shortcuts-drawing-annotations-and-cross-screen-d.md +6 -0
  182. package/corpus/templates/design/changelog/2026-07-09-hand-and-scale-tools-now-keep-their-active-toolbar-identity-.md +6 -0
  183. package/corpus/templates/design/changelog/2026-07-09-large-multi-screen-designs-now-stay-responsive-during-long-c.md +6 -0
  184. package/corpus/templates/design/changelog/2026-07-09-layer-drags-now-land-exactly-where-the-insertion-indicator-s.md +6 -0
  185. package/corpus/templates/design/server/db/index.ts +2 -52
  186. package/corpus/templates/design/server/db/schema.ts +16 -0
  187. package/corpus/templates/design/server/lib/design-data-access.ts +70 -0
  188. package/corpus/templates/design/server/lib/design-data-mutation.ts +249 -0
  189. package/corpus/templates/design/server/lib/fusion-screens.ts +89 -76
  190. package/corpus/templates/design/server/lib/import-design-files.ts +76 -35
  191. package/corpus/templates/design/server/lib/verify-write-grant.ts +7 -2
  192. package/corpus/templates/design/server/plugins/db.ts +19 -0
  193. package/corpus/templates/design/server/source-workspace.ts +12 -13
  194. package/corpus/templates/design/shared/resolve-tweaks.ts +15 -0
  195. package/corpus/templates/design/shared/screen-rename.ts +42 -0
  196. package/corpus/templates/design/shared/source-mode.ts +84 -4
  197. package/dist/agent/engine/builder-engine.d.ts +1 -1
  198. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  199. package/dist/agent/engine/builtin.js +1 -1
  200. package/dist/agent/engine/builtin.js.map +1 -1
  201. package/dist/agent/model-config.d.ts +9 -9
  202. package/dist/agent/model-config.d.ts.map +1 -1
  203. package/dist/agent/model-config.js +30 -30
  204. package/dist/agent/model-config.js.map +1 -1
  205. package/dist/agent/production-agent.d.ts +60 -1
  206. package/dist/agent/production-agent.d.ts.map +1 -1
  207. package/dist/agent/production-agent.js +106 -7
  208. package/dist/agent/production-agent.js.map +1 -1
  209. package/dist/cli/design-connect.d.ts +30 -1
  210. package/dist/cli/design-connect.d.ts.map +1 -1
  211. package/dist/cli/design-connect.js +359 -75
  212. package/dist/cli/design-connect.js.map +1 -1
  213. package/dist/cli/recap.js +2 -2
  214. package/dist/cli/recap.js.map +1 -1
  215. package/dist/cli/sync-builder-starter-manifest.js +1 -1
  216. package/dist/cli/sync-builder-starter-manifest.js.map +1 -1
  217. package/dist/client/AgentPanel.d.ts.map +1 -1
  218. package/dist/client/AgentPanel.js +6 -1
  219. package/dist/client/AgentPanel.js.map +1 -1
  220. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  221. package/dist/client/agent-chat-adapter.js +10 -5
  222. package/dist/client/agent-chat-adapter.js.map +1 -1
  223. package/dist/client/composer/TiptapComposer.js +1 -1
  224. package/dist/client/composer/TiptapComposer.js.map +1 -1
  225. package/dist/client/index.d.ts +1 -1
  226. package/dist/client/index.d.ts.map +1 -1
  227. package/dist/client/index.js +1 -1
  228. package/dist/client/index.js.map +1 -1
  229. package/dist/client/org/TeamPage.d.ts.map +1 -1
  230. package/dist/client/org/TeamPage.js +6 -5
  231. package/dist/client/org/TeamPage.js.map +1 -1
  232. package/dist/client/use-action.d.ts +32 -0
  233. package/dist/client/use-action.d.ts.map +1 -1
  234. package/dist/client/use-action.js +68 -1
  235. package/dist/client/use-action.js.map +1 -1
  236. package/dist/collab/awareness.d.ts +2 -2
  237. package/dist/collab/awareness.d.ts.map +1 -1
  238. package/dist/collab/routes.d.ts +1 -1
  239. package/dist/db/client.d.ts +3 -0
  240. package/dist/db/client.d.ts.map +1 -1
  241. package/dist/db/client.js +7 -2
  242. package/dist/db/client.js.map +1 -1
  243. package/dist/db/create-get-db.d.ts.map +1 -1
  244. package/dist/db/create-get-db.js +2 -2
  245. package/dist/db/create-get-db.js.map +1 -1
  246. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  247. package/dist/notifications/routes.d.ts +1 -1
  248. package/dist/observability/routes.d.ts +5 -5
  249. package/dist/progress/routes.d.ts +1 -1
  250. package/dist/resources/handlers.d.ts +1 -1
  251. package/dist/scripts/agent-engines/manage-agent-engine.js +1 -1
  252. package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
  253. package/dist/scripts/agent-engines/set-agent-engine.js +1 -1
  254. package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
  255. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  256. package/dist/server/transcribe-voice.js +1 -1
  257. package/dist/server/transcribe-voice.js.map +1 -1
  258. package/dist/usage/store.d.ts.map +1 -1
  259. package/dist/usage/store.js +13 -4
  260. package/dist/usage/store.js.map +1 -1
  261. package/dist/vite/client.d.ts.map +1 -1
  262. package/dist/vite/client.js +36 -1
  263. package/dist/vite/client.js.map +1 -1
  264. package/docs/content/a2a-protocol.mdx +12 -0
  265. package/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
  266. package/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
  267. package/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
  268. package/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
  269. package/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
  270. package/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
  271. package/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
  272. package/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
  273. package/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
  274. package/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
  275. package/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
  276. package/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
  277. package/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
  278. package/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
  279. package/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
  280. package/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
  281. package/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
  282. package/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
  283. package/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
  284. package/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
  285. package/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
  286. package/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
  287. package/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
  288. package/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
  289. package/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
  290. package/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
  291. package/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
  292. package/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
  293. package/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
  294. package/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
  295. package/docs/content/pr-visual-recap.mdx +3 -3
  296. package/docs/content/pure-agent-apps.mdx +22 -0
  297. package/package.json +2 -2
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Analytics HTTP surface for listing stored data programs.
3
+ *
4
+ * Core registers list-data-programs for the agent tool bag; template apps also
5
+ * expose it here so extension iframes can call it via
6
+ * /_agent-native/actions/list-data-programs.
7
+ */
8
+ import { defineAction } from "@agent-native/core";
9
+ import { listDataPrograms } from "@agent-native/core/data-programs";
10
+ import { getCredentialContext } from "@agent-native/core/server/request-context";
11
+ import { z } from "zod";
12
+
13
+ import { ANALYTICS_APP_ID } from "../server/lib/provider-credentials";
14
+
15
+ export default defineAction({
16
+ description:
17
+ "List data programs for Analytics, scoped to what the caller can access.",
18
+ schema: z.object({
19
+ includeArchived: z.boolean().optional(),
20
+ }),
21
+ http: { method: "GET" },
22
+ readOnly: true,
23
+ run: async (args) => {
24
+ const ctx = getCredentialContext();
25
+ if (!ctx)
26
+ throw new Error("No authenticated context for list-data-programs.");
27
+
28
+ const programs = await listDataPrograms(
29
+ ANALYTICS_APP_ID,
30
+ { userEmail: ctx.userEmail, orgId: ctx.orgId ?? undefined },
31
+ { includeArchived: args.includeArchived },
32
+ );
33
+
34
+ return {
35
+ programs: programs.map((p) => ({
36
+ id: p.id,
37
+ name: p.name,
38
+ title: p.title,
39
+ description: p.description,
40
+ refreshMode: p.refreshMode,
41
+ refreshTtlMs: p.refreshTtlMs,
42
+ background: p.background,
43
+ archivedAt: p.archivedAt,
44
+ updatedAt: p.updatedAt,
45
+ columns: p.outputColumns ? JSON.parse(p.outputColumns) : [],
46
+ })),
47
+ };
48
+ },
49
+ });
@@ -602,6 +602,7 @@
602
602
  .dashboard-grid-container {
603
603
  --dashboard-drop-line: hsl(217 91% 60%);
604
604
  container: dashboard-grid / inline-size;
605
+ gap: 0;
605
606
  }
606
607
 
607
608
  .dashboard-grid {
@@ -634,6 +635,16 @@
634
635
  margin-block: -0.75rem;
635
636
  }
636
637
 
638
+ /* At compact widths, panels from the same dashboard row stack vertically.
639
+ Give the drop targets between those panels the same 1rem footprint as the
640
+ row drop targets so every adjacent chart has consistent spacing. */
641
+ @container dashboard-grid (max-width: 767px) {
642
+ .dashboard-grid
643
+ > .dashboard-column-drop-slot:not(:first-child):not(:last-child) {
644
+ margin-block: -0.25rem;
645
+ }
646
+ }
647
+
637
648
  .dashboard-row-drop-slot::after,
638
649
  .dashboard-column-drop-slot::after {
639
650
  content: "";
@@ -4,12 +4,14 @@ import {
4
4
  removeAgentChatContextItem,
5
5
  setAgentChatContextItem,
6
6
  setClientAppState,
7
+ useAgentChatContext,
7
8
  } from "@agent-native/core/client";
8
- import { useEffect } from "react";
9
+ import { useCallback, useEffect } from "react";
9
10
 
10
11
  import { TAB_ID } from "@/lib/tab-id";
11
12
 
12
13
  const DASHBOARD_CONTEXT_KEY = "analytics-selected-dashboard";
14
+ const DASHBOARD_PANEL_CONTEXT_KEY = "analytics-selected-dashboard-panel";
13
15
  const SELECTED_OBJECT_STATE_KEY = "selected-object";
14
16
  const SELECTED_OBJECT_SOURCE_FIELD = "__agentNativeSelectedObjectSource";
15
17
 
@@ -21,6 +23,29 @@ export interface DashboardChatContextArgs {
21
23
  canEdit?: boolean;
22
24
  }
23
25
 
26
+ export interface DashboardPanelChatContextArgs {
27
+ panelId: string;
28
+ panelTitle: string;
29
+ panelKind: "chart" | "table" | "extension";
30
+ chartType?: string | null;
31
+ source?: string | null;
32
+ configId?: string | null;
33
+ extensionId?: string | null;
34
+ }
35
+
36
+ export interface SelectDashboardPanelOptions {
37
+ focus?: boolean;
38
+ openSidebar?: boolean;
39
+ }
40
+
41
+ export interface DashboardChatContextResult {
42
+ selectedPanelId: string | null;
43
+ selectPanelForChat: (
44
+ panel: DashboardPanelChatContextArgs,
45
+ options?: SelectDashboardPanelOptions,
46
+ ) => void;
47
+ }
48
+
24
49
  function dashboardContext(
25
50
  args: Required<Pick<DashboardChatContextArgs, "id" | "kind">> & {
26
51
  title: string;
@@ -50,12 +75,19 @@ function dashboardContext(
50
75
  return lines.join("\n");
51
76
  }
52
77
 
53
- async function deleteSelectedObjectIfOwned() {
78
+ async function deleteSelectedObjectIfOwned(dashboardId: string) {
54
79
  try {
55
80
  const current = await readClientAppState<Record<string, unknown>>(
56
81
  SELECTED_OBJECT_STATE_KEY,
57
82
  );
58
83
  if (current?.[SELECTED_OBJECT_SOURCE_FIELD] !== TAB_ID) return;
84
+ const selectedDashboardId =
85
+ current.type === "dashboard"
86
+ ? current.id
87
+ : current.type === "dashboard-panel"
88
+ ? current.dashboardId
89
+ : null;
90
+ if (selectedDashboardId !== dashboardId) return;
59
91
  await deleteClientAppState(SELECTED_OBJECT_STATE_KEY, {
60
92
  keepalive: true,
61
93
  requestSource: TAB_ID,
@@ -65,21 +97,106 @@ async function deleteSelectedObjectIfOwned() {
65
97
  }
66
98
  }
67
99
 
68
- export function useDashboardChatContext(args: DashboardChatContextArgs): void {
100
+ function panelSelectionMarker(dashboardId: string, panelId: string): string {
101
+ return `Analytics panel selection: dashboard=${encodeURIComponent(
102
+ dashboardId,
103
+ )}; panel=${encodeURIComponent(panelId)}`;
104
+ }
105
+
106
+ function parsePanelSelection(
107
+ context: string,
108
+ ): { dashboardId: string; panelId: string } | null {
109
+ const match = context.match(
110
+ /^Analytics panel selection: dashboard=([^;]+); panel=(.+)$/m,
111
+ );
112
+ if (!match) return null;
113
+ try {
114
+ return {
115
+ dashboardId: decodeURIComponent(match[1]),
116
+ panelId: decodeURIComponent(match[2]),
117
+ };
118
+ } catch {
119
+ return null;
120
+ }
121
+ }
122
+
123
+ export function useDashboardChatContext(
124
+ args: DashboardChatContextArgs,
125
+ ): DashboardChatContextResult {
69
126
  const { id, kind, title, panelCount, canEdit } = args;
127
+ const { items } = useAgentChatContext();
128
+ const panelContext = items.find(
129
+ (item) => item.key === DASHBOARD_PANEL_CONTEXT_KEY,
130
+ );
131
+ const panelSelection = panelContext
132
+ ? parsePanelSelection(panelContext.context)
133
+ : null;
134
+ const selectedPanelId =
135
+ id && panelSelection?.dashboardId === id ? panelSelection.panelId : null;
136
+ const hasSelectedPanel = selectedPanelId !== null;
137
+
138
+ const selectPanelForChat = useCallback(
139
+ (
140
+ panel: DashboardPanelChatContextArgs,
141
+ options: SelectDashboardPanelOptions = {},
142
+ ) => {
143
+ if (!id) return;
144
+ const displayDashboardTitle = title?.trim() || id;
145
+ const displayPanelTitle = panel.panelTitle.trim() || panel.panelId;
146
+ const contextLines = [
147
+ panelSelectionMarker(id, panel.panelId),
148
+ `The user selected this ${panel.panelKind} on the Analytics dashboard "${displayDashboardTitle}".`,
149
+ `Dashboard id: ${id}`,
150
+ `Dashboard kind: ${kind}`,
151
+ `Panel id: ${panel.panelId}`,
152
+ `Panel title: ${displayPanelTitle}`,
153
+ `Panel kind: ${panel.panelKind}`,
154
+ panel.chartType ? `Chart type: ${panel.chartType}` : "",
155
+ panel.source ? `Data source: ${panel.source}` : "",
156
+ panel.configId ? `Explorer config id: ${panel.configId}` : "",
157
+ panel.extensionId ? `Extension id: ${panel.extensionId}` : "",
158
+ kind === "sql"
159
+ ? "Inspect this panel with get-sql-dashboard (includeConfig: true) before changing it, then use mutate-dashboard for edits."
160
+ : "Inspect the linked Explorer config before changing this chart.",
161
+ ].filter(Boolean);
162
+
163
+ // The panel context occupies one stable composer slot, so selecting a
164
+ // different panel replaces the prior chip instead of accumulating chips.
165
+ setAgentChatContextItem({
166
+ key: DASHBOARD_PANEL_CONTEXT_KEY,
167
+ title: displayPanelTitle,
168
+ context: contextLines.join("\n"),
169
+ openSidebar: options.openSidebar ?? true,
170
+ focus: options.focus ?? false,
171
+ });
172
+ setClientAppState(
173
+ SELECTED_OBJECT_STATE_KEY,
174
+ {
175
+ type: "dashboard-panel",
176
+ dashboardId: id,
177
+ dashboardKind: kind,
178
+ dashboardTitle: displayDashboardTitle,
179
+ panelId: panel.panelId,
180
+ panelTitle: displayPanelTitle,
181
+ panelKind: panel.panelKind,
182
+ chartType: panel.chartType || undefined,
183
+ source: panel.source || undefined,
184
+ configId: panel.configId || undefined,
185
+ extensionId: panel.extensionId || undefined,
186
+ [SELECTED_OBJECT_SOURCE_FIELD]: TAB_ID,
187
+ },
188
+ {
189
+ keepalive: true,
190
+ requestSource: TAB_ID,
191
+ },
192
+ ).catch(() => {});
193
+ },
194
+ [id, kind, title],
195
+ );
70
196
 
71
197
  useEffect(() => {
72
198
  if (!id) return;
73
199
  const displayTitle = title?.trim() || id;
74
- const selection = {
75
- type: "dashboard",
76
- id,
77
- kind,
78
- title: displayTitle,
79
- panelCount,
80
- canEdit,
81
- [SELECTED_OBJECT_SOURCE_FIELD]: TAB_ID,
82
- };
83
200
 
84
201
  setAgentChatContextItem({
85
202
  key: DASHBOARD_CONTEXT_KEY,
@@ -94,17 +211,46 @@ export function useDashboardChatContext(args: DashboardChatContextArgs): void {
94
211
  openSidebar: false,
95
212
  focus: false,
96
213
  });
97
- setClientAppState(SELECTED_OBJECT_STATE_KEY, selection, {
98
- keepalive: true,
99
- requestSource: TAB_ID,
100
- }).catch(() => {});
101
214
 
102
215
  return () => {
103
216
  removeAgentChatContextItem({
104
217
  key: DASHBOARD_CONTEXT_KEY,
105
218
  openSidebar: false,
106
219
  });
107
- deleteSelectedObjectIfOwned();
108
220
  };
109
221
  }, [canEdit, id, kind, panelCount, title]);
222
+
223
+ useEffect(() => {
224
+ if (!id || hasSelectedPanel) return;
225
+ const displayTitle = title?.trim() || id;
226
+ setClientAppState(
227
+ SELECTED_OBJECT_STATE_KEY,
228
+ {
229
+ type: "dashboard",
230
+ id,
231
+ kind,
232
+ title: displayTitle,
233
+ panelCount,
234
+ canEdit,
235
+ [SELECTED_OBJECT_SOURCE_FIELD]: TAB_ID,
236
+ },
237
+ {
238
+ keepalive: true,
239
+ requestSource: TAB_ID,
240
+ },
241
+ ).catch(() => {});
242
+ }, [canEdit, hasSelectedPanel, id, kind, panelCount, title]);
243
+
244
+ useEffect(() => {
245
+ if (!id) return;
246
+ return () => {
247
+ removeAgentChatContextItem({
248
+ key: DASHBOARD_PANEL_CONTEXT_KEY,
249
+ openSidebar: false,
250
+ });
251
+ deleteSelectedObjectIfOwned(id);
252
+ };
253
+ }, [id]);
254
+
255
+ return { selectedPanelId, selectPanelForChat };
110
256
  }
@@ -777,6 +777,7 @@ const messages = {
777
777
  halfWidth: "半寬",
778
778
  fullWidth: "全寬",
779
779
  editInExplorer: "在 Explorer 中編輯",
780
+ chatWithChart: "與圖表聊天",
780
781
  removeChart: "刪除圖表",
781
782
  removeChartTitle: "刪除圖表?",
782
783
  removeChartDescription: "要從此儀表板移除「{{name}}」嗎?此操作無法復原。",
@@ -832,6 +833,7 @@ const messages = {
832
833
  extensionMissingId: "此擴充面板未選擇任何擴充功能。",
833
834
  extensionUnavailable: "此擴充功能未與您共用,或已不存在。",
834
835
  panelOptions: "面板選項",
836
+ chatWithPanel: "與面板聊天",
835
837
  fullScreen: "全螢幕",
836
838
  refresh: "重新整理",
837
839
  refreshing: "正在重新整理...",
@@ -539,6 +539,7 @@ const enUS = {
539
539
  halfWidth: "Half width",
540
540
  fullWidth: "Full width",
541
541
  editInExplorer: "Edit in Explorer",
542
+ chatWithChart: "Chat with chart",
542
543
  removeChart: "Remove chart",
543
544
  removeChartTitle: "Remove chart?",
544
545
  removeChartDescription:
@@ -596,6 +597,7 @@ const enUS = {
596
597
  extensionUnavailable:
597
598
  "This extension isn't shared with you, or it no longer exists.",
598
599
  panelOptions: "Panel options",
600
+ chatWithPanel: "Chat with panel",
599
601
  fullScreen: "Full screen",
600
602
  refresh: "Refresh",
601
603
  refreshing: "Refreshing...",
@@ -5755,6 +5757,7 @@ const translatedAnalyticsDebtTranslations = {
5755
5757
  deletePermanentlyTitle: "永久删除?",
5756
5758
  deletePermanently: "永久删除",
5757
5759
  editInExplorer: "在 Explorer 中编辑",
5760
+ chatWithChart: "与图表聊天",
5758
5761
  fullWidth: "全宽",
5759
5762
  halfWidth: "半宽",
5760
5763
  hiddenDescription:
@@ -5874,6 +5877,7 @@ const translatedAnalyticsDebtTranslations = {
5874
5877
  noPanels: "该仪表板还没有面板。",
5875
5878
  noSavedViews: "尚未保存视图。",
5876
5879
  panelOptions: "面板选项",
5880
+ chatWithPanel: "与面板聊天",
5877
5881
  saveAsView: "另存为视图",
5878
5882
  saveCurrentView: "保存当前视图",
5879
5883
  saveFailed: "无法保存仪表板",
@@ -5962,6 +5966,7 @@ const translatedAnalyticsDebtTranslations = {
5962
5966
  deletePermanentlyTitle: "¿Eliminar permanentemente?",
5963
5967
  deletePermanently: "Eliminar permanentemente",
5964
5968
  editInExplorer: "Editar en Explorer",
5969
+ chatWithChart: "Chatear sobre el gráfico",
5965
5970
  fullWidth: "Ancho completo",
5966
5971
  halfWidth: "Medio ancho",
5967
5972
  hiddenDescription:
@@ -6085,6 +6090,7 @@ const translatedAnalyticsDebtTranslations = {
6085
6090
  noPanels: "Este panel aún no tiene paneles.",
6086
6091
  noSavedViews: "Aún no hay vistas guardadas.",
6087
6092
  panelOptions: "Opciones de paneles",
6093
+ chatWithPanel: "Chatear sobre el panel",
6088
6094
  saveAsView: "Guardar como vista",
6089
6095
  saveCurrentView: "Guardar vista actual",
6090
6096
  saveFailed: "No se pudo guardar el panel",
@@ -6177,6 +6183,7 @@ const translatedAnalyticsDebtTranslations = {
6177
6183
  deletePermanentlyTitle: "Supprimer définitivement ?",
6178
6184
  deletePermanently: "Supprimer définitivement",
6179
6185
  editInExplorer: "Modifier dans Explorer",
6186
+ chatWithChart: "Discuter du graphique",
6180
6187
  fullWidth: "Pleine largeur",
6181
6188
  halfWidth: "Demi-largeur",
6182
6189
  hiddenDescription:
@@ -6300,6 +6307,7 @@ const translatedAnalyticsDebtTranslations = {
6300
6307
  noPanels: "Ce tableau de bord n'a pas encore de panneaux.",
6301
6308
  noSavedViews: "Aucune vue enregistrée pour l'instant.",
6302
6309
  panelOptions: "Options du panneau",
6310
+ chatWithPanel: "Discuter du panneau",
6303
6311
  saveAsView: "Enregistrer sous vue",
6304
6312
  saveCurrentView: "Enregistrer la vue actuelle",
6305
6313
  saveFailed: "Impossible d'enregistrer le tableau de bord",
@@ -6393,6 +6401,7 @@ const translatedAnalyticsDebtTranslations = {
6393
6401
  deletePermanentlyTitle: "Endgültig löschen?",
6394
6402
  deletePermanently: "Dauerhaft löschen",
6395
6403
  editInExplorer: "Bearbeiten in Explorer",
6404
+ chatWithChart: "Mit Diagramm chatten",
6396
6405
  fullWidth: "Volle Breite",
6397
6406
  halfWidth: "Halbe Breite",
6398
6407
  hiddenDescription:
@@ -6516,6 +6525,7 @@ const translatedAnalyticsDebtTranslations = {
6516
6525
  noPanels: "Dieses Dashboard hat noch keine Panels.",
6517
6526
  noSavedViews: "Noch keine gespeicherten Ansichten.",
6518
6527
  panelOptions: "Panel-Optionen",
6528
+ chatWithPanel: "Mit Panel chatten",
6519
6529
  saveAsView: "Als Ansicht speichern",
6520
6530
  saveCurrentView: "Aktuelle Ansicht speichern",
6521
6531
  saveFailed: "Das Dashboard konnte nicht gespeichert werden",
@@ -6605,6 +6615,7 @@ const translatedAnalyticsDebtTranslations = {
6605
6615
  deletePermanentlyTitle: "永久に削除しますか?",
6606
6616
  deletePermanently: "完全に削除",
6607
6617
  editInExplorer: "Explorerで編集",
6618
+ chatWithChart: "グラフについてチャット",
6608
6619
  fullWidth: "全幅",
6609
6620
  halfWidth: "半角",
6610
6621
  hiddenDescription:
@@ -6727,6 +6738,7 @@ const translatedAnalyticsDebtTranslations = {
6727
6738
  noPanels: "このダッシュボードにはまだパネルがありません。",
6728
6739
  noSavedViews: "保存されたビューはまだありません。",
6729
6740
  panelOptions: "パネルオプション",
6741
+ chatWithPanel: "パネルについてチャット",
6730
6742
  saveAsView: "ビューとして保存",
6731
6743
  saveCurrentView: "現在のビューを保存する",
6732
6744
  saveFailed: "ダッシュボードを保存できませんでした",
@@ -6816,6 +6828,7 @@ const translatedAnalyticsDebtTranslations = {
6816
6828
  deletePermanentlyTitle: "영구적으로 삭제하시겠습니까?",
6817
6829
  deletePermanently: "영구 삭제",
6818
6830
  editInExplorer: "Explorer에서 편집",
6831
+ chatWithChart: "차트에 대해 채팅",
6819
6832
  fullWidth: "전폭",
6820
6833
  halfWidth: "반폭",
6821
6834
  hiddenDescription:
@@ -6937,6 +6950,7 @@ const translatedAnalyticsDebtTranslations = {
6937
6950
  noPanels: "이 대시보드에는 아직 패널이 없습니다.",
6938
6951
  noSavedViews: "아직 저장된 보기가 없습니다.",
6939
6952
  panelOptions: "패널 옵션",
6953
+ chatWithPanel: "패널에 대해 채팅",
6940
6954
  saveAsView: "보기로 저장",
6941
6955
  saveCurrentView: "현재 보기 저장",
6942
6956
  saveFailed: "대시보드를 저장할 수 없습니다.",
@@ -7028,6 +7042,7 @@ const translatedAnalyticsDebtTranslations = {
7028
7042
  deletePermanentlyTitle: "Excluir permanentemente?",
7029
7043
  deletePermanently: "Excluir permanentemente",
7030
7044
  editInExplorer: "Editar em Explorer",
7045
+ chatWithChart: "Conversar sobre o gráfico",
7031
7046
  fullWidth: "Largura total",
7032
7047
  halfWidth: "Meia largura",
7033
7048
  hiddenDescription:
@@ -7151,6 +7166,7 @@ const translatedAnalyticsDebtTranslations = {
7151
7166
  noPanels: "Este painel ainda não possui painéis.",
7152
7167
  noSavedViews: "Nenhuma visualização salva ainda.",
7153
7168
  panelOptions: "Opções do painel",
7169
+ chatWithPanel: "Conversar sobre o painel",
7154
7170
  saveAsView: "Salvar como visualização",
7155
7171
  saveCurrentView: "Salvar visualização atual",
7156
7172
  saveFailed: "Não foi possível salvar o painel",
@@ -7240,6 +7256,7 @@ const translatedAnalyticsDebtTranslations = {
7240
7256
  deletePermanentlyTitle: "स्थायी रूप से हटाएँ?",
7241
7257
  deletePermanently: "स्थायी रूप से हटाएँ",
7242
7258
  editInExplorer: "Explorer में संपादित करें",
7259
+ chatWithChart: "चार्ट के बारे में चैट करें",
7243
7260
  fullWidth: "पूरी चौड़ाई",
7244
7261
  halfWidth: "आधी चौड़ाई",
7245
7262
  hiddenDescription:
@@ -7361,6 +7378,7 @@ const translatedAnalyticsDebtTranslations = {
7361
7378
  noPanels: "इस डैशबोर्ड में अभी तक कोई पैनल नहीं है.",
7362
7379
  noSavedViews: "अभी तक कोई सहेजा गया दृश्य नहीं.",
7363
7380
  panelOptions: "पैनल विकल्प",
7381
+ chatWithPanel: "पैनल के बारे में चैट करें",
7364
7382
  saveAsView: "दृश्य के रूप में सहेजें",
7365
7383
  saveCurrentView: "वर्तमान दृश्य सहेजें",
7366
7384
  saveFailed: "डैशबोर्ड सहेजा नहीं जा सका",
@@ -7449,6 +7467,7 @@ const translatedAnalyticsDebtTranslations = {
7449
7467
  deletePermanentlyTitle: "هل تريد الحذف نهائيًا؟",
7450
7468
  deletePermanently: "حذف نهائيا",
7451
7469
  editInExplorer: "تحرير في Explorer",
7470
+ chatWithChart: "الدردشة حول المخطط",
7452
7471
  fullWidth: "العرض الكامل",
7453
7472
  halfWidth: "نصف العرض",
7454
7473
  hiddenDescription:
@@ -7570,6 +7589,7 @@ const translatedAnalyticsDebtTranslations = {
7570
7589
  noPanels: "لوحة القيادة هذه لا تحتوي على لوحات حتى الآن.",
7571
7590
  noSavedViews: "لا توجد طرق عرض محفوظة حتى الآن.",
7572
7591
  panelOptions: "خيارات اللوحة",
7592
+ chatWithPanel: "الدردشة حول اللوحة",
7573
7593
  saveAsView: "حفظ كعرض",
7574
7594
  saveCurrentView: "حفظ العرض الحالي",
7575
7595
  saveFailed: "تعذر حفظ لوحة البيانات",
@@ -6,10 +6,12 @@ import {
6
6
  IconTrash,
7
7
  IconArrowsMaximize,
8
8
  IconArrowsMinimize,
9
+ IconDotsVertical,
9
10
  IconExternalLink,
11
+ IconMessageCircle,
10
12
  } from "@tabler/icons-react";
11
13
  import { useQuery } from "@tanstack/react-query";
12
- import { useMemo, useState } from "react";
14
+ import { useCallback, useMemo, useState } from "react";
13
15
 
14
16
  import {
15
17
  AlertDialog,
@@ -22,13 +24,24 @@ import {
22
24
  AlertDialogTitle,
23
25
  } from "@/components/ui/alert-dialog";
24
26
  import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
27
+ import {
28
+ DropdownMenu,
29
+ DropdownMenuContent,
30
+ DropdownMenuItem,
31
+ DropdownMenuTrigger,
32
+ } from "@/components/ui/dropdown-menu";
25
33
  import { Skeleton } from "@/components/ui/skeleton";
26
34
  import {
27
35
  Tooltip,
28
36
  TooltipContent,
29
37
  TooltipTrigger,
30
38
  } from "@/components/ui/tooltip";
39
+ import type {
40
+ DashboardPanelChatContextArgs,
41
+ SelectDashboardPanelOptions,
42
+ } from "@/hooks/use-dashboard-chat-context";
31
43
  import { useMetricsQuery } from "@/lib/query-metrics";
44
+ import { cn } from "@/lib/utils";
32
45
 
33
46
  import { ExplorerChart } from "../explorer/components/ExplorerChart";
34
47
  import { buildSql } from "../explorer/sql-builder";
@@ -42,6 +55,11 @@ interface ChartCardProps {
42
55
  onToggleWidth: () => void;
43
56
  onEdit: () => void;
44
57
  editable?: boolean;
58
+ selectedForChat?: boolean;
59
+ selectPanelForChat: (
60
+ panel: DashboardPanelChatContextArgs,
61
+ options?: SelectDashboardPanelOptions,
62
+ ) => void;
45
63
  }
46
64
 
47
65
  async function fetchConfig(id: string): Promise<ExplorerConfig | null> {
@@ -66,6 +84,8 @@ export function DashboardChartCard({
66
84
  onToggleWidth,
67
85
  onEdit,
68
86
  editable = true,
87
+ selectedForChat = false,
88
+ selectPanelForChat,
69
89
  }: ChartCardProps) {
70
90
  const t = useT();
71
91
  const [confirmOpen, setConfirmOpen] = useState(false);
@@ -100,15 +120,59 @@ export function DashboardChartCard({
100
120
  );
101
121
 
102
122
  const isLoading = !config || queryLoading;
123
+ const displayTitle = config?.name ?? configName;
124
+ const handleSelectForChat = useCallback(
125
+ (options?: SelectDashboardPanelOptions) => {
126
+ selectPanelForChat(
127
+ {
128
+ panelId: chart.id,
129
+ panelTitle: displayTitle,
130
+ panelKind: config?.chartType === "table" ? "table" : "chart",
131
+ chartType: config?.chartType,
132
+ configId: chart.configId,
133
+ },
134
+ options,
135
+ );
136
+ },
137
+ [
138
+ chart.configId,
139
+ chart.id,
140
+ config?.chartType,
141
+ displayTitle,
142
+ selectPanelForChat,
143
+ ],
144
+ );
145
+ const handleCardClick = useCallback(
146
+ (event: React.MouseEvent<HTMLDivElement>) => {
147
+ const target = event.target;
148
+ if (
149
+ target instanceof Element &&
150
+ target.closest(
151
+ "button, a, input, textarea, select, [role='menuitem'], [data-no-panel-chat-select]",
152
+ )
153
+ ) {
154
+ return;
155
+ }
156
+ handleSelectForChat({ focus: false });
157
+ },
158
+ [handleSelectForChat],
159
+ );
103
160
 
104
161
  return (
105
162
  <div
106
163
  ref={setNodeRef}
164
+ onClick={handleCardClick}
107
165
  style={style}
108
166
  data-dragging={isDragging ? "true" : undefined}
167
+ data-chat-selected={selectedForChat ? "true" : undefined}
109
168
  className={`explorer-dashboard-card group relative ${chart.width === 2 ? "explorer-dashboard-card-wide" : ""}`}
110
169
  >
111
- <Card className="h-full">
170
+ <Card
171
+ className={cn(
172
+ "h-full transition-colors",
173
+ selectedForChat && "border-foreground/35 ring-1 ring-foreground/10",
174
+ )}
175
+ >
112
176
  <CardHeader className="pb-2 flex flex-row items-center gap-2">
113
177
  {editable ? (
114
178
  <button
@@ -120,8 +184,37 @@ export function DashboardChartCard({
120
184
  </button>
121
185
  ) : null}
122
186
  <CardTitle className="text-sm font-medium flex-1 truncate">
123
- {config?.name ?? configName}
187
+ {displayTitle}
124
188
  </CardTitle>
189
+ <div className="opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100">
190
+ <DropdownMenu>
191
+ <Tooltip>
192
+ <TooltipTrigger asChild>
193
+ <DropdownMenuTrigger asChild>
194
+ <button
195
+ className="p-1 rounded text-muted-foreground hover:text-foreground transition-colors"
196
+ aria-label={t("sqlDashboard.panelOptions")}
197
+ >
198
+ <IconDotsVertical className="h-3.5 w-3.5" />
199
+ </button>
200
+ </DropdownMenuTrigger>
201
+ </TooltipTrigger>
202
+ <TooltipContent>
203
+ {t("sqlDashboard.panelOptions")}
204
+ </TooltipContent>
205
+ </Tooltip>
206
+ <DropdownMenuContent align="end" className="w-44">
207
+ <DropdownMenuItem
208
+ onSelect={() =>
209
+ handleSelectForChat({ openSidebar: true, focus: true })
210
+ }
211
+ >
212
+ <IconMessageCircle className="h-4 w-4 mr-2" />
213
+ {t("explorerDashboard.chatWithChart")}
214
+ </DropdownMenuItem>
215
+ </DropdownMenuContent>
216
+ </DropdownMenu>
217
+ </div>
125
218
  {editable ? (
126
219
  <div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
127
220
  <Tooltip>
@@ -205,7 +205,7 @@ export default function ExplorerDashboardPage() {
205
205
  );
206
206
  const canEdit = resourceCanEdit(resourceAccess);
207
207
  const canManage = resourceCanManage(resourceAccess);
208
- useDashboardChatContext({
208
+ const { selectedPanelId, selectPanelForChat } = useDashboardChatContext({
209
209
  id: dashboardId,
210
210
  kind: "explorer",
211
211
  title: dashboard?.name,
@@ -797,6 +797,8 @@ export default function ExplorerDashboardPage() {
797
797
  navigate(`/dashboards/explorer?config=${chart.configId}`)
798
798
  }
799
799
  editable={canEdit}
800
+ selectedForChat={selectedPanelId === chart.id}
801
+ selectPanelForChat={selectPanelForChat}
800
802
  />
801
803
  ))}
802
804
  </div>