@agent-native/core-corpus 0.210.0 → 0.210.1-nightly-20261020010058

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 (392) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +10 -0
  3. package/corpus/templates/analytics/.agents/skills/context-awareness/SKILL.md +5 -0
  4. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +11 -0
  5. package/corpus/templates/analytics/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  6. package/corpus/templates/analytics/actions/estimate-query-cost.ts +421 -0
  7. package/corpus/templates/analytics/actions/mutate-dashboard.ts +9 -1
  8. package/corpus/templates/analytics/changelog/2026-10-19-composer-focus-remains-safe-when-an-editor-changes-during-na.md +6 -0
  9. package/corpus/templates/analytics/changelog/2026-10-19-dashboard-api-guidance-works-without-an-open-dashboard.md +6 -0
  10. package/corpus/templates/analytics/server/lib/analytics-mcp.ts +1 -0
  11. package/corpus/templates/analytics/server/lib/bigquery.ts +20 -4
  12. package/corpus/templates/analytics/server/lib/dashboard-panel-verification.ts +38 -0
  13. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +30 -0
  14. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +35 -14
  15. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +66 -0
  16. package/corpus/templates/analytics/server/lib/query-cost-estimate.ts +311 -0
  17. package/corpus/templates/assets/.agents/skills/context-awareness/SKILL.md +5 -0
  18. package/corpus/templates/assets/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  19. package/corpus/templates/brain/.agents/skills/context-awareness/SKILL.md +5 -0
  20. package/corpus/templates/brain/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  21. package/corpus/templates/calendar/.agents/skills/context-awareness/SKILL.md +5 -0
  22. package/corpus/templates/calendar/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  23. package/corpus/templates/chat/.agents/skills/context-awareness/SKILL.md +5 -0
  24. package/corpus/templates/chat/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  25. package/corpus/templates/chat/app/components/chat/ChatHomeRedirect.tsx +2 -2
  26. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +51 -22
  27. package/corpus/templates/chat/server/plugins/agent-chat.ts +1 -0
  28. package/corpus/templates/clips/.agents/skills/recording/SKILL.md +17 -2
  29. package/corpus/templates/clips/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  30. package/corpus/templates/clips/AGENTS.md +1 -1
  31. package/corpus/templates/clips/actions/get-recording-player-data.ts +41 -9
  32. package/corpus/templates/clips/actions/import-loom-recording.ts +9 -3
  33. package/corpus/templates/clips/actions/lib/ensure-recording-filmstrip.ts +2 -1
  34. package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +2 -1
  35. package/corpus/templates/clips/actions/lib/native-media.ts +22 -6
  36. package/corpus/templates/clips/actions/lib/youtube-import.ts +247 -0
  37. package/corpus/templates/clips/actions/request-transcript.ts +11 -2
  38. package/corpus/templates/clips/actions/set-embed-duration.ts +55 -0
  39. package/corpus/templates/clips/actions/view-screen.ts +12 -1
  40. package/corpus/templates/clips/app/components/library/import-loom-dialog.tsx +13 -7
  41. package/corpus/templates/clips/app/components/player/player-controls.tsx +50 -15
  42. package/corpus/templates/clips/app/components/player/use-optimistic-reactions.ts +87 -0
  43. package/corpus/templates/clips/app/components/player/video-player.tsx +48 -68
  44. package/corpus/templates/clips/app/components/player/youtube-embed-player.tsx +690 -0
  45. package/corpus/templates/clips/app/hooks/use-player-shortcuts.ts +13 -21
  46. package/corpus/templates/clips/app/i18n/en-US.ts +12 -1
  47. package/corpus/templates/clips/app/lib/youtube-iframe-api.ts +135 -0
  48. package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +59 -24
  49. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +6 -4
  50. package/corpus/templates/clips/app/routes/import.tsx +13 -4
  51. package/corpus/templates/clips/app/routes/share.$shareId.tsx +16 -8
  52. package/corpus/templates/clips/changelog/2026-10-16-youtube-embeds.md +6 -0
  53. package/corpus/templates/clips/server/lib/agent-frame-request.ts +11 -6
  54. package/corpus/templates/clips/server/lib/ensure-recording-thumbnail.ts +7 -4
  55. package/corpus/templates/clips/server/lib/player-video-url.ts +9 -0
  56. package/corpus/templates/clips/server/lib/public-agent-context.ts +18 -21
  57. package/corpus/templates/clips/server/routes/api/agent-transcript.json.get.ts +3 -3
  58. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +15 -0
  59. package/corpus/templates/clips/shared/comment-transcript-context.ts +25 -0
  60. package/corpus/templates/clips/shared/embed-provider.ts +32 -0
  61. package/corpus/templates/clips/shared/youtube.ts +103 -0
  62. package/corpus/templates/content/.agents/skills/context-awareness/SKILL.md +5 -0
  63. package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +5 -3
  64. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +27 -6
  65. package/corpus/templates/content/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  66. package/corpus/templates/content/AGENTS.md +2 -0
  67. package/corpus/templates/content/actions/configure-document-property.ts +1 -1
  68. package/corpus/templates/content/actions/delete-document-property.ts +1 -1
  69. package/corpus/templates/content/actions/get-blocks-field-word-count.ts +1 -1
  70. package/corpus/templates/content/actions/list-content-database-blocks.ts +1 -1
  71. package/corpus/templates/content/actions/mutate-content-database-block.ts +1 -1
  72. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +3 -2
  73. package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +1090 -154
  74. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +69 -32
  75. package/corpus/templates/content/app/components/editor/blockFieldSaveRegistry.ts +13 -0
  76. package/corpus/templates/content/app/components/editor/blockFieldTabs.ts +315 -0
  77. package/corpus/templates/content/app/global.css +0 -5
  78. package/corpus/templates/content/app/hooks/use-document-properties.ts +16 -2
  79. package/corpus/templates/content/app/hooks/use-navigation-state.ts +28 -11
  80. package/corpus/templates/content/app/i18n-data.ts +15 -2
  81. package/corpus/templates/content/changelog/2026-10-18-collection-pages-with-more-than-one-blocks-field-show-each-f.md +6 -0
  82. package/corpus/templates/content/changelog/2026-10-18-renaming-a-blocks-field-from-a-collection-column-saves-again.md +6 -0
  83. package/corpus/templates/content/server/plugins/agent-chat.ts +1 -0
  84. package/corpus/templates/content/shared/properties.ts +2 -0
  85. package/corpus/templates/crm/.agents/skills/context-awareness/SKILL.md +5 -0
  86. package/corpus/templates/crm/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  87. package/corpus/templates/design/.agents/skills/context-awareness/SKILL.md +5 -0
  88. package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +14 -0
  89. package/corpus/templates/design/.agents/skills/native-effects/SKILL.md +25 -0
  90. package/corpus/templates/design/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  91. package/corpus/templates/design/.generated/bridge/native-builtin-metadata.generated.ts +301 -0
  92. package/corpus/templates/design/.generated/bridge/native-worker-source.generated.ts +6 -0
  93. package/corpus/templates/design/AGENTS.md +5 -1
  94. package/corpus/templates/design/actions/_native-local-export-server.ts +212 -0
  95. package/corpus/templates/design/actions/_native-render-contexts.ts +150 -0
  96. package/corpus/templates/design/actions/apply-builder-edits.ts +85 -32
  97. package/corpus/templates/design/actions/apply-component-prop-edit.ts +10 -0
  98. package/corpus/templates/design/actions/apply-motion-edit.ts +3 -0
  99. package/corpus/templates/design/actions/cancel-native-local-export.ts +85 -0
  100. package/corpus/templates/design/actions/claim-native-local-export.ts +80 -0
  101. package/corpus/templates/design/actions/edit-native-shader.ts +847 -0
  102. package/corpus/templates/design/actions/export-png.ts +5 -2
  103. package/corpus/templates/design/actions/finish-native-local-export.ts +171 -0
  104. package/corpus/templates/design/actions/get-native-local-export.ts +66 -0
  105. package/corpus/templates/design/actions/get-native-render-contexts.ts +16 -0
  106. package/corpus/templates/design/actions/get-shader.ts +219 -8
  107. package/corpus/templates/design/actions/list-builder-edits.ts +8 -3
  108. package/corpus/templates/design/actions/open-builder-branch-design.ts +4 -15
  109. package/corpus/templates/design/actions/prepare-native-scene-export.ts +138 -0
  110. package/corpus/templates/design/actions/register-native-render-context.ts +19 -0
  111. package/corpus/templates/design/actions/request-native-local-export.ts +99 -0
  112. package/corpus/templates/design/actions/send-builder-message.ts +4 -0
  113. package/corpus/templates/design/actions/take-design-screenshot.ts +12 -1
  114. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +73 -0
  115. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +49 -9
  116. package/corpus/templates/design/app/components/design/EditPanel.tsx +41 -15
  117. package/corpus/templates/design/app/components/design/MotionCodeView.tsx +405 -0
  118. package/corpus/templates/design/app/components/design/MotionDock.tsx +131 -164
  119. package/corpus/templates/design/app/components/design/MotionNativeStyleEditor.tsx +395 -149
  120. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +41 -14
  121. package/corpus/templates/design/app/components/design/bridge/codegen.ts +79 -13
  122. package/corpus/templates/design/app/components/design/bridge/native-authored-paint.ts +66 -0
  123. package/corpus/templates/design/app/components/design/bridge/native-bounded-frame-scheduler.ts +170 -0
  124. package/corpus/templates/design/app/components/design/bridge/native-camera-recorder.ts +170 -0
  125. package/corpus/templates/design/app/components/design/bridge/native-capture-roi.ts +125 -0
  126. package/corpus/templates/design/app/components/design/bridge/native-color-mode.ts +165 -0
  127. package/corpus/templates/design/app/components/design/bridge/native-composition-budget.ts +112 -0
  128. package/corpus/templates/design/app/components/design/bridge/native-composition-clock.ts +849 -0
  129. package/corpus/templates/design/app/components/design/bridge/native-composition-session.ts +83 -0
  130. package/corpus/templates/design/app/components/design/bridge/native-data-mipmaps.ts +81 -0
  131. package/corpus/templates/design/app/components/design/bridge/native-device-lifecycle.ts +158 -0
  132. package/corpus/templates/design/app/components/design/bridge/native-effect-extent.ts +321 -0
  133. package/corpus/templates/design/app/components/design/bridge/native-effect-output-geometry.ts +135 -0
  134. package/corpus/templates/design/app/components/design/bridge/native-export-selection.ts +65 -0
  135. package/corpus/templates/design/app/components/design/bridge/native-feedback-resume.ts +141 -0
  136. package/corpus/templates/design/app/components/design/bridge/native-frame-resource-scratch.ts +38 -0
  137. package/corpus/templates/design/app/components/design/bridge/native-gpu-profiler.ts +424 -0
  138. package/corpus/templates/design/app/components/design/bridge/native-gpu-sample-window.ts +286 -0
  139. package/corpus/templates/design/app/components/design/bridge/native-gpu-scope-profiler.ts +260 -0
  140. package/corpus/templates/design/app/components/design/bridge/native-group-local-backdrop-window.ts +299 -0
  141. package/corpus/templates/design/app/components/design/bridge/native-image-replay-safety.ts +134 -0
  142. package/corpus/templates/design/app/components/design/bridge/native-intrinsic-image.ts +126 -0
  143. package/corpus/templates/design/app/components/design/bridge/native-linear-golden.ts +91 -0
  144. package/corpus/templates/design/app/components/design/bridge/native-live-camera-source.ts +160 -0
  145. package/corpus/templates/design/app/components/design/bridge/native-mounted-benchmark.ts +730 -0
  146. package/corpus/templates/design/app/components/design/bridge/native-mounted-output-summary.ts +243 -0
  147. package/corpus/templates/design/app/components/design/bridge/native-packed-uniform-arena.ts +150 -0
  148. package/corpus/templates/design/app/components/design/bridge/native-parameter-preview-queue.ts +66 -0
  149. package/corpus/templates/design/app/components/design/bridge/native-pixel-readback.ts +45 -0
  150. package/corpus/templates/design/app/components/design/bridge/native-playback-clock.ts +29 -0
  151. package/corpus/templates/design/app/components/design/bridge/native-presentation-pair.ts +128 -0
  152. package/corpus/templates/design/app/components/design/bridge/native-presentation-readback.ts +104 -0
  153. package/corpus/templates/design/app/components/design/bridge/native-presentation-slots.ts +177 -0
  154. package/corpus/templates/design/app/components/design/bridge/native-preview-budget.ts +95 -0
  155. package/corpus/templates/design/app/components/design/bridge/native-preview-geometry.ts +165 -0
  156. package/corpus/templates/design/app/components/design/bridge/native-preview-policy.ts +235 -0
  157. package/corpus/templates/design/app/components/design/bridge/native-raf-interval.ts +21 -0
  158. package/corpus/templates/design/app/components/design/bridge/native-receiver-distance.ts +257 -0
  159. package/corpus/templates/design/app/components/design/bridge/native-region-export.ts +11 -0
  160. package/corpus/templates/design/app/components/design/bridge/native-render-placement.ts +41 -0
  161. package/corpus/templates/design/app/components/design/bridge/native-runtime-epoch.ts +20 -0
  162. package/corpus/templates/design/app/components/design/bridge/native-shader-runtime.bridge.ts +22595 -0
  163. package/corpus/templates/design/app/components/design/bridge/native-simulation-timeline.ts +86 -0
  164. package/corpus/templates/design/app/components/design/bridge/native-simulation-transaction.ts +165 -0
  165. package/corpus/templates/design/app/components/design/bridge/native-source-affine-geometry.ts +333 -0
  166. package/corpus/templates/design/app/components/design/bridge/native-source-coordinate-scale.ts +47 -0
  167. package/corpus/templates/design/app/components/design/bridge/native-source-frame-witness.ts +26 -0
  168. package/corpus/templates/design/app/components/design/bridge/native-source-local-geometry.ts +75 -0
  169. package/corpus/templates/design/app/components/design/bridge/native-source-provider.ts +6980 -0
  170. package/corpus/templates/design/app/components/design/bridge/native-source-sampling-cases.ts +687 -0
  171. package/corpus/templates/design/app/components/design/bridge/native-source-sampling.ts +135 -0
  172. package/corpus/templates/design/app/components/design/bridge/native-stateful-resource.ts +936 -0
  173. package/corpus/templates/design/app/components/design/bridge/native-stateless-compute.ts +226 -0
  174. package/corpus/templates/design/app/components/design/bridge/native-stateless-frame-transaction.ts +181 -0
  175. package/corpus/templates/design/app/components/design/bridge/native-submission-pipeline.ts +67 -0
  176. package/corpus/templates/design/app/components/design/bridge/native-svg-geometry.ts +90 -0
  177. package/corpus/templates/design/app/components/design/bridge/native-svg-pattern-fixtures.ts +114 -0
  178. package/corpus/templates/design/app/components/design/bridge/native-svg-pattern-work.ts +114 -0
  179. package/corpus/templates/design/app/components/design/bridge/native-svg-source.ts +1092 -0
  180. package/corpus/templates/design/app/components/design/bridge/native-texture-feedback.ts +916 -0
  181. package/corpus/templates/design/app/components/design/bridge/native-worker-backdrop-route.ts +9 -0
  182. package/corpus/templates/design/app/components/design/bridge/native-worker-broker.ts +242 -0
  183. package/corpus/templates/design/app/components/design/bridge/native-worker-compositor.ts +934 -0
  184. package/corpus/templates/design/app/components/design/bridge/native-worker-entry.ts +2295 -0
  185. package/corpus/templates/design/app/components/design/bridge/native-worker-fill.ts +479 -0
  186. package/corpus/templates/design/app/components/design/bridge/native-worker-gpu-wgsl.ts +650 -0
  187. package/corpus/templates/design/app/components/design/bridge/native-worker-gpu.ts +1059 -0
  188. package/corpus/templates/design/app/components/design/bridge/native-worker-host.ts +598 -0
  189. package/corpus/templates/design/app/components/design/bridge/native-worker-protocol.ts +185 -0
  190. package/corpus/templates/design/app/components/design/bridge/native-worker-scene-host.ts +1813 -0
  191. package/corpus/templates/design/app/components/design/bridge/native-worker-source-snapshot.ts +274 -0
  192. package/corpus/templates/design/app/components/design/design-canvas/interact-document.ts +9 -5
  193. package/corpus/templates/design/app/components/design/design-canvas/local-runtime.ts +18 -1
  194. package/corpus/templates/design/app/components/design/edit-panel/appearance-properties.tsx +27 -6
  195. package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +70 -9
  196. package/corpus/templates/design/app/components/design/edit-panel/fill-gradient-helpers.ts +1 -1
  197. package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +278 -14
  198. package/corpus/templates/design/app/components/design/edit-panel/motion-controls.ts +126 -0
  199. package/corpus/templates/design/app/components/design/edit-panel/motion-inspector-properties.tsx +1 -1
  200. package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +6 -0
  201. package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +18 -16
  202. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +13 -3
  203. package/corpus/templates/design/app/components/design/inspector/GlslShaderPanel.tsx +35 -3
  204. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +181 -118
  205. package/corpus/templates/design/app/components/design/inspector/NativeShaderCatalogPreview.tsx +191 -0
  206. package/corpus/templates/design/app/components/design/inspector/NativeShaderColorControls.tsx +301 -0
  207. package/corpus/templates/design/app/components/design/inspector/NativeShaderPaintControls.tsx +95 -0
  208. package/corpus/templates/design/app/components/design/inspector/NativeShaderPanel.tsx +1263 -0
  209. package/corpus/templates/design/app/components/design/inspector/color-picker-nested.ts +6 -0
  210. package/corpus/templates/design/app/components/design/inspector/color-picker-shader-pane.tsx +44 -3
  211. package/corpus/templates/design/app/components/design/inspector/native-catalog-display.ts +150 -0
  212. package/corpus/templates/design/app/components/design/inspector/native-shader-catalog-preview.ts +332 -0
  213. package/corpus/templates/design/app/components/design/inspector/native-shader-paint.ts +131 -0
  214. package/corpus/templates/design/app/components/design/inspector/native-shader-property-draft.ts +74 -0
  215. package/corpus/templates/design/app/components/design/native-preview-iframe-lifecycle.ts +23 -0
  216. package/corpus/templates/design/app/components/design/use-native-shader-approvals.ts +67 -0
  217. package/corpus/templates/design/app/i18n/en-US.ts +222 -0
  218. package/corpus/templates/design/app/lib/design-sync-invalidation.ts +17 -7
  219. package/corpus/templates/design/app/lib/svg-paste.ts +1 -1
  220. package/corpus/templates/design/app/pages/DesignEditor.tsx +29 -23
  221. package/corpus/templates/design/app/pages/design-editor/agent-chat-context-bookkeeping.tsx +18 -0
  222. package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +5 -1
  223. package/corpus/templates/design/app/pages/design-editor/clone-and-pen-edit.ts +56 -2
  224. package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +15 -3
  225. package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +3 -2
  226. package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +15 -2
  227. package/corpus/templates/design/app/pages/design-editor/commands/delete-selection.ts +7 -5
  228. package/corpus/templates/design/app/pages/design-editor/commands/duplicate-selection.ts +6 -0
  229. package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +12 -5
  230. package/corpus/templates/design/app/pages/design-editor/commands/paste-svg-layer.ts +27 -6
  231. package/corpus/templates/design/app/pages/design-editor/commands/render-png-blob.ts +64 -0
  232. package/corpus/templates/design/app/pages/design-editor/design-editor-view.tsx +188 -67
  233. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-export-and-handoff.ts +122 -0
  234. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-files-and-saving.ts +1 -0
  235. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-generation-and-access.ts +3 -0
  236. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-live-edits-and-presence.ts +11 -2
  237. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-tools-and-vectors.ts +5 -11
  238. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +17 -2
  239. package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +9 -2
  240. package/corpus/templates/design/app/pages/design-editor/export-capture.ts +12 -1
  241. package/corpus/templates/design/app/pages/design-editor/motion-add-menu.ts +213 -0
  242. package/corpus/templates/design/app/pages/design-editor/motion-code-model.ts +106 -0
  243. package/corpus/templates/design/app/pages/design-editor/native-current-frame-png.ts +219 -0
  244. package/corpus/templates/design/app/pages/design-editor/native-png-attachment-client.ts +50 -0
  245. package/corpus/templates/design/app/pages/design-editor/native-png-encoding.ts +172 -0
  246. package/corpus/templates/design/app/pages/design-editor/paste-placement.ts +45 -1
  247. package/corpus/templates/design/app/pages/design-editor/png-export-render.ts +82 -2
  248. package/corpus/templates/design/app/pages/design-editor/read-design-editor-source.ts +11 -3
  249. package/corpus/templates/design/app/pages/design-editor/screen-command-utils.ts +6 -2
  250. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +14 -2
  251. package/corpus/templates/design/app/pages/design-editor/use-native-local-export-requests.ts +356 -0
  252. package/corpus/templates/design/app/pages/design-editor/view/editor-canvas-area.tsx +23 -1
  253. package/corpus/templates/design/changelog/2026-10-14-add-liquid-metal-fluted-glass-image-dithering-and-waves-to-t.md +6 -0
  254. package/corpus/templates/design/changelog/2026-10-14-apply-curated-webgpu-fills-and-effects-to-design-layers-and-.md +6 -0
  255. package/corpus/templates/design/changelog/2026-10-14-choose-each-native-shader-once-and-customize-its-parameters.md +6 -0
  256. package/corpus/templates/design/changelog/2026-10-14-liquid-metal-adds-fluid-contours-and-separated-color-reflections.md +6 -0
  257. package/corpus/templates/design/changelog/2026-10-14-mesh-gradient-now-blends-four-deliberate-color-points-into-a.md +6 -0
  258. package/corpus/templates/design/changelog/2026-10-14-native-fills-can-combine-shader-and-css-layers-while-preserv.md +6 -0
  259. package/corpus/templates/design/changelog/2026-10-14-native-shader-choices-now-show-visual-previews-and-use-the-s.md +6 -0
  260. package/corpus/templates/design/changelog/2026-10-14-shader-controls-use-familiar-units-and-reliable-numeric-edit.md +6 -0
  261. package/corpus/templates/design/changelog/2026-10-14-static-content-extending-beyond-the-viewport-no-longer-preve.md +6 -0
  262. package/corpus/templates/design/changelog/2026-10-15-design-adds-nebula-and-glowing-waves.md +6 -0
  263. package/corpus/templates/design/changelog/2026-10-15-design-adds-original-webgpu-textures-patterns-and-effects.md +6 -0
  264. package/corpus/templates/design/changelog/2026-10-15-liquid-glass-refracts-the-backdrop-through-rounded-layers-an.md +6 -0
  265. package/corpus/templates/design/changelog/2026-10-15-liquid-metal-deforms-in-place-instead-of-drifting.md +6 -0
  266. package/corpus/templates/design/changelog/2026-10-15-liquid-metal-flows-as-a-continuous-reflective-surface-across.md +6 -0
  267. package/corpus/templates/design/changelog/2026-10-15-liquid-metal-flows-through-curved-chrome-bands-with-multicolor-rims.md +6 -0
  268. package/corpus/templates/design/changelog/2026-10-15-liquid-metal-gains-sculpted-reflective-cells-and-crisp-chrom.md +6 -0
  269. package/corpus/templates/design/changelog/2026-10-15-liquid-metal-reflections-wrap-around-svg-shapes.md +6 -0
  270. package/corpus/templates/design/changelog/2026-10-15-liquid-metal-separates-tint-from-solid-and-gradient-fills.md +6 -0
  271. package/corpus/templates/design/changelog/2026-10-15-native-shader-fills-follow-svg-artwork-including-transparent.md +6 -0
  272. package/corpus/templates/design/changelog/2026-10-15-pasted-svg-artwork-no-longer-hides-native-shader-fills-and-e.md +6 -0
  273. package/corpus/templates/design/changelog/2026-10-15-svg-artwork-stays-sharp-when-zooming-in-on-the-canvas.md +6 -0
  274. package/corpus/templates/design/changelog/2026-10-16-animated-shader-fills-render-together-more-efficiently-and-p.md +6 -0
  275. package/corpus/templates/design/changelog/2026-10-16-create-custom-webgpu-shaders-from-the-shader-picker-with-ai.md +6 -0
  276. package/corpus/templates/design/changelog/2026-10-16-export-selected-shader-frames-and-liquid-glass-as-transparen.md +6 -0
  277. package/corpus/templates/design/changelog/2026-10-16-glass-backdrops-and-animated-shaders-stay-stable-on-large-de.md +6 -0
  278. package/corpus/templates/design/changelog/2026-10-16-hidden-layers-no-longer-interrupt-effects-on-visible-layers.md +6 -0
  279. package/corpus/templates/design/changelog/2026-10-16-new-glowing-waves-lens-distortion-and-water-shaders-preserve.md +6 -0
  280. package/corpus/templates/design/changelog/2026-10-16-pasted-svgs-keep-their-position-inside-freeform-frames.md +6 -0
  281. package/corpus/templates/design/changelog/2026-10-16-shader-fills-stay-visible-when-frames-are-wrapped-or-moved-i.md +6 -0
  282. package/corpus/templates/design/changelog/2026-10-16-shader-previews-remain-active-when-the-canvas-viewport-chang.md +6 -0
  283. package/corpus/templates/design/changelog/2026-10-16-shader-property-sliders-preview-changes-while-dragging.md +6 -0
  284. package/corpus/templates/design/changelog/2026-10-19-motion-shows-a-layer-s-animation-as-read-only-css-or-data-in.md +6 -0
  285. package/corpus/templates/design/changelog/2026-10-19-right-click-selected-layers-to-add-an-animation-and-the-anim.md +6 -0
  286. package/corpus/templates/design/changelog/2026-10-19-text-stagger-has-a-settings-panel-with-overlap-order-crop-an.md +6 -0
  287. package/corpus/templates/design/package.json +6 -6
  288. package/corpus/templates/design/public/shaders/gate-image-contrast.svg +8 -0
  289. package/corpus/templates/design/scripts/runtime-budget.ts +88 -10
  290. package/corpus/templates/design/server/db/schema.ts +5 -1
  291. package/corpus/templates/design/server/lib/builder-identity.ts +37 -5
  292. package/corpus/templates/design/server/lib/design-export.ts +29 -7
  293. package/corpus/templates/design/server/lib/design-response-guard.ts +4 -3
  294. package/corpus/templates/design/server/routes/api/native-png-attachment.get.ts +76 -0
  295. package/corpus/templates/design/server/routes/api/native-png-attachment.post.ts +195 -0
  296. package/corpus/templates/design/server/source-workspace.ts +25 -1
  297. package/corpus/templates/design/shared/code-layer.ts +5 -1
  298. package/corpus/templates/design/shared/css-box-shadow.ts +52 -0
  299. package/corpus/templates/design/shared/effect-graph.ts +790 -0
  300. package/corpus/templates/design/shared/html-integrity.ts +21 -0
  301. package/corpus/templates/design/shared/motion-layer-code.ts +167 -0
  302. package/corpus/templates/design/shared/motion-native-style-runtime.ts +46 -27
  303. package/corpus/templates/design/shared/motion-text-code.ts +68 -0
  304. package/corpus/templates/design/shared/native-authored-source-bindings.ts +20 -0
  305. package/corpus/templates/design/shared/native-benchmark-contract.ts +2 -0
  306. package/corpus/templates/design/shared/native-capture-cache.ts +125 -0
  307. package/corpus/templates/design/shared/native-clip-geometry.ts +201 -0
  308. package/corpus/templates/design/shared/native-css-paint-outsets.ts +134 -0
  309. package/corpus/templates/design/shared/native-draft-preview-contract.ts +63 -0
  310. package/corpus/templates/design/shared/native-editor-preferences.ts +54 -0
  311. package/corpus/templates/design/shared/native-effect-animation-capability.ts +526 -0
  312. package/corpus/templates/design/shared/native-effect-catalog-generators.ts +342 -0
  313. package/corpus/templates/design/shared/native-effect-catalog-kit.ts +271 -0
  314. package/corpus/templates/design/shared/native-effect-catalog-presets.ts +629 -0
  315. package/corpus/templates/design/shared/native-effect-catalog-processors.ts +443 -0
  316. package/corpus/templates/design/shared/native-effect-cloning.ts +141 -0
  317. package/corpus/templates/design/shared/native-effect-color-grade-v2.ts +89 -0
  318. package/corpus/templates/design/shared/native-effect-density-corrected.ts +87 -0
  319. package/corpus/templates/design/shared/native-effect-document-pixels-v2.ts +55 -0
  320. package/corpus/templates/design/shared/native-effect-edits.ts +723 -0
  321. package/corpus/templates/design/shared/native-effect-frame-policy.ts +58 -0
  322. package/corpus/templates/design/shared/native-effect-gallery-additions.ts +651 -0
  323. package/corpus/templates/design/shared/native-effect-liquid-glass-v1.ts +105 -0
  324. package/corpus/templates/design/shared/native-effect-liquid-glass-v2.ts +107 -0
  325. package/corpus/templates/design/shared/native-effect-liquid-glass-v3.ts +108 -0
  326. package/corpus/templates/design/shared/native-effect-liquid-metal-v1.ts +109 -0
  327. package/corpus/templates/design/shared/native-effect-liquid-metal-v10.ts +155 -0
  328. package/corpus/templates/design/shared/native-effect-liquid-metal-v11.ts +167 -0
  329. package/corpus/templates/design/shared/native-effect-liquid-metal-v2.ts +111 -0
  330. package/corpus/templates/design/shared/native-effect-liquid-metal-v3.ts +129 -0
  331. package/corpus/templates/design/shared/native-effect-liquid-metal-v4.ts +143 -0
  332. package/corpus/templates/design/shared/native-effect-liquid-metal-v5.ts +151 -0
  333. package/corpus/templates/design/shared/native-effect-liquid-metal-v6.ts +176 -0
  334. package/corpus/templates/design/shared/native-effect-liquid-metal-v7.ts +184 -0
  335. package/corpus/templates/design/shared/native-effect-liquid-metal-v8.ts +184 -0
  336. package/corpus/templates/design/shared/native-effect-liquid-metal-v9.ts +159 -0
  337. package/corpus/templates/design/shared/native-effect-multipass.ts +207 -0
  338. package/corpus/templates/design/shared/native-effect-owned-cc-source-glints.ts +190 -0
  339. package/corpus/templates/design/shared/native-effect-owned-next-edge-sampling.ts +79 -0
  340. package/corpus/templates/design/shared/native-effect-paint.ts +270 -0
  341. package/corpus/templates/design/shared/native-effect-parameter-constraints.ts +274 -0
  342. package/corpus/templates/design/shared/native-effect-position.ts +159 -0
  343. package/corpus/templates/design/shared/native-effect-presets.ts +456 -0
  344. package/corpus/templates/design/shared/native-effect-property-presentation.ts +522 -0
  345. package/corpus/templates/design/shared/native-effect-pruning.ts +56 -0
  346. package/corpus/templates/design/shared/native-effect-raster-density-policy.ts +17 -0
  347. package/corpus/templates/design/shared/native-effect-transform.ts +71 -0
  348. package/corpus/templates/design/shared/native-effect-trust.ts +165 -0
  349. package/corpus/templates/design/shared/native-effect-v1-graphics.ts +222 -0
  350. package/corpus/templates/design/shared/native-effect-v1-materials.ts +271 -0
  351. package/corpus/templates/design/shared/native-effect-wgsl.ts +42 -0
  352. package/corpus/templates/design/shared/native-effect-wide-color.ts +54 -0
  353. package/corpus/templates/design/shared/native-effects.ts +2819 -0
  354. package/corpus/templates/design/shared/native-embedded-assets.ts +182 -0
  355. package/corpus/templates/design/shared/native-export-region.ts +52 -0
  356. package/corpus/templates/design/shared/native-feedback-plan.ts +279 -0
  357. package/corpus/templates/design/shared/native-input-resources.ts +269 -0
  358. package/corpus/templates/design/shared/native-instance-preview-contract.ts +55 -0
  359. package/corpus/templates/design/shared/native-linear-resource-graph.ts +249 -0
  360. package/corpus/templates/design/shared/native-local-export.ts +153 -0
  361. package/corpus/templates/design/shared/native-parameter-animation.ts +290 -0
  362. package/corpus/templates/design/shared/native-pipeline-cache.ts +148 -0
  363. package/corpus/templates/design/shared/native-pointer-history.ts +193 -0
  364. package/corpus/templates/design/shared/native-pointer-input.ts +199 -0
  365. package/corpus/templates/design/shared/native-presentation-fault-gate.ts +99 -0
  366. package/corpus/templates/design/shared/native-presentation-fault-pin.ts +16 -0
  367. package/corpus/templates/design/shared/native-shader-validation.ts +1356 -0
  368. package/corpus/templates/design/shared/native-source-clip-plan.ts +484 -0
  369. package/corpus/templates/design/shared/native-source-composition-tree.ts +228 -0
  370. package/corpus/templates/design/shared/native-source-composition.ts +136 -0
  371. package/corpus/templates/design/shared/native-source-sizing.ts +141 -0
  372. package/corpus/templates/design/shared/native-stateful-reset-values.ts +190 -0
  373. package/corpus/templates/design/shared/native-stateful-resource-graph.ts +334 -0
  374. package/corpus/templates/design/shared/native-stateless-compute.ts +334 -0
  375. package/corpus/templates/design/shared/native-static-generator-pass-cache.ts +122 -0
  376. package/corpus/templates/design/shared/native-uniform-timing.ts +44 -0
  377. package/corpus/templates/design/shared/shader-fills.ts +105 -0
  378. package/corpus/templates/design/vitest.config.ts +1 -0
  379. package/corpus/templates/design/vitest.setup.ts +8 -0
  380. package/corpus/templates/dispatch/.agents/skills/context-awareness/SKILL.md +5 -0
  381. package/corpus/templates/dispatch/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  382. package/corpus/templates/factory/.agents/skills/context-awareness/SKILL.md +5 -0
  383. package/corpus/templates/forms/.agents/skills/context-awareness/SKILL.md +5 -0
  384. package/corpus/templates/forms/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  385. package/corpus/templates/mail/.agents/skills/context-awareness/SKILL.md +5 -0
  386. package/corpus/templates/mail/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  387. package/corpus/templates/plan/.agents/skills/context-awareness/SKILL.md +5 -0
  388. package/corpus/templates/plan/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  389. package/corpus/templates/slides/.agents/skills/context-awareness/SKILL.md +5 -0
  390. package/corpus/templates/slides/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
  391. package/corpus/templates/tasks/.agents/skills/context-awareness/SKILL.md +5 -0
  392. package/package.json +1 -1
package/corpus/README.md CHANGED
@@ -32,4 +32,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core-corpus/corpu
32
32
 
33
33
  ## Generated Counts
34
34
 
35
- - template files: 12899
35
+ - template files: 13180
@@ -78,10 +78,20 @@ Never label a current partial-month snapshot as last month's completed usage.
78
78
  | `data-source-status --key bigquery` | Check whether BigQuery credentials and project are configured. |
79
79
  | `find-data --question <topic>` | Find ranked metric definitions and saved query examples before SQL. |
80
80
  | `search-bigquery-schema` | List datasets, list tables in a dataset, or describe table columns. |
81
+ | `estimate-query-cost --sql "<sql>"` | Free dry run: bytes, $ per run, and $ per month for scheduled runs. |
81
82
  | `bigquery --sql "<sql>"` | Run a real warehouse query after table/column names are known. |
82
83
  | `query-dbt-semantic-metric --metricName <exact dbt name>` | Run an owner-defined dbt Semantic Layer metric before warehouse SQL. |
83
84
  | `get-dbt-connection` | Check dbt readiness (`readiness`) and the missing setup step. |
84
85
 
86
+ ## Check Cost Before Big Queries
87
+
88
+ Before running a query over a large event or pageview table, call
89
+ `estimate-query-cost` with the same SQL. It dry-runs the query (BigQuery reads
90
+ and bills nothing) and prices it at on-demand rates. Pass `runsPerMonth` for
91
+ anything scheduled, such as 8640 for an alert that polls every 5 minutes.
92
+ Estimates over $1 per run or $50 per month are flagged: tell the user the number
93
+ before going ahead.
94
+
85
95
  For direct Amplitude/PostHog/Mixpanel product-event data (outside the warehouse
86
96
  copy), there is no first-class action — call `provider-api-catalog` /
87
97
  `provider-api-docs` then `provider-api-request` (provider `amplitude`, `posthog`,
@@ -196,6 +196,11 @@ changes. If a command can arrive while a chat stream is rendering, prefer
196
196
  `navigate(path, { replace: true, flushSync: true })` over a view-transition
197
197
  wrapper so the URL and visible route commit together.
198
198
 
199
+ Keep `path` router-local. A segment matching the app mount prefix remains part
200
+ of the local route unless a matching `view` route or explicit `publicPath`
201
+ identifies the mounted URL. Carry the mounted form separately in `publicPath`;
202
+ never infer that `path` is mounted from its prefix alone.
203
+
199
204
  ## Jitter Prevention
200
205
 
201
206
  Agent-side application-state writes are tagged with
@@ -944,6 +944,17 @@ unavailable" placeholder.
944
944
  `mutate-dashboard` for existing edits, or `update-dashboard` for new/full
945
945
  config saves, and fix the action arguments.
946
946
  - Never set `panel.source` to a table name or unsupported backend.
947
+ - Before saving a BigQuery or first-party panel that reads a large table, or
948
+ adding an email report to a dashboard, check its cost with
949
+ `estimate-query-cost --dashboardId <id>` (add `--panelId` for one panel). It
950
+ is a free dry run; tell the user any panel flagged over $1 per run or $50 per
951
+ month. Dashboard estimates count email reports but not alert rules: before
952
+ adding an alert, estimate an `analytics_events` query with the alert's
953
+ filters and its window's `event_date` and `timestamp` bounds, as alerts
954
+ send both (the dry run skips only partitions the `event_date` filter rules
955
+ out), using `--source first-party --eventsSource raw` (alerts run as
956
+ first-party SQL on the raw table) and `--runsPerMonth` set from the poll
957
+ interval (8640 for every 5 minutes).
947
958
  - Use `first-party` for `/track` data and `query-agent-native-analytics` for ad-hoc first-party event questions.
948
959
  - Use `update-dashboard` for new dashboard config saves and full config
949
960
  replacements. Use `mutate-dashboard` for existing dashboard edits.
@@ -0,0 +1,10 @@
1
+ // AUTO-GENERATED by @agent-native/core deploy build
2
+ import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
3
+
4
+ const pluginStems = ["agent-chat","analytics-alert-jobs","analytics-rollup-backfill-jobs","auth","collab","config","core-routes","creative-context","dashboard-report-jobs","db","feature-flags","labs","onboarding","otel","session-replay-retention-jobs","transactional-emails","uptime-monitor-jobs"];
5
+
6
+ export default function markBuildDiscoveredPlugins(nitroApp) {
7
+ for (const stem of pluginStems) {
8
+ markDefaultPluginProvided(nitroApp, stem);
9
+ }
10
+ }
@@ -0,0 +1,421 @@
1
+ import { defineAction, fail } from "@agent-native/core/action";
2
+ import type { ActionRunContext } from "@agent-native/core/action";
3
+ import {
4
+ getCredentialContext,
5
+ getRequestOrgId,
6
+ getRequestUserEmail,
7
+ } from "@agent-native/core/server";
8
+ import { z } from "zod";
9
+
10
+ import { isSafeDashboardId } from "../server/lib/dashboard-id";
11
+ import {
12
+ pageDashboardConfig,
13
+ resolveDashboardPanelQueries,
14
+ type ResolvedDashboardPanelQuery,
15
+ } from "../server/lib/dashboard-panel-verification";
16
+ import { countEnabledDashboardReportSubscriptions } from "../server/lib/dashboard-report-subscriptions";
17
+ import { loadDashboardSeed } from "../server/lib/dashboard-seeds";
18
+ import { getDashboard } from "../server/lib/dashboards-store";
19
+ import type { AnalyticsScope } from "../server/lib/first-party-analytics";
20
+ import {
21
+ DAYS_PER_MONTH,
22
+ estimateBigQuerySql,
23
+ estimateFirstPartySql,
24
+ estimateResolvedPanel,
25
+ formatBytes,
26
+ formatUsd,
27
+ ON_DEMAND_USD_PER_TIB,
28
+ QUERY_COST_CAVEATS,
29
+ QUERY_COST_THRESHOLDS,
30
+ totalCost,
31
+ type PanelCostEstimate,
32
+ type QueryCostEstimate,
33
+ } from "../server/lib/query-cost-estimate";
34
+ import { clipHead } from "../shared/panel-render-contract";
35
+
36
+ const MAX_PANELS = 60;
37
+ const DRY_RUN_CONCURRENCY = 6;
38
+ /** Stop starting dry runs here so the action returns before its 55 s timeout. */
39
+ const DASHBOARD_DEADLINE_MS = 40_000;
40
+
41
+ function timedOutPanel(
42
+ panel: { panelId: string; title: string; source: string },
43
+ error: string,
44
+ ): PanelCostEstimate {
45
+ return {
46
+ panelId: panel.panelId,
47
+ title: panel.title,
48
+ source: panel.source,
49
+ status: "failed",
50
+ failure: "timeout",
51
+ error,
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Estimate one panel, but give up when the dashboard deadline passes, even
57
+ * mid-way through credential, table, or backend lookups, so finished panels
58
+ * still come back before the action's own timeout.
59
+ */
60
+ async function estimatePanelBefore(
61
+ deadline: number,
62
+ panel: ResolvedDashboardPanelQuery,
63
+ scope: AnalyticsScope,
64
+ runsPerMonth: number | null,
65
+ signal?: AbortSignal,
66
+ ): Promise<PanelCostEstimate> {
67
+ const remaining = deadline - Date.now();
68
+ if (remaining <= 0) {
69
+ return timedOutPanel(
70
+ panel,
71
+ "Skipped: this request ran out of time. Estimate this panel on its own with panelId.",
72
+ );
73
+ }
74
+ const controller = new AbortController();
75
+ const forwardAbort = () => controller.abort(signal?.reason);
76
+ if (signal?.aborted) forwardAbort();
77
+ signal?.addEventListener("abort", forwardAbort, { once: true });
78
+ let timer: ReturnType<typeof setTimeout> | undefined;
79
+ const timedOut = new Promise<PanelCostEstimate>((resolve) => {
80
+ timer = setTimeout(() => {
81
+ resolve(
82
+ timedOutPanel(
83
+ panel,
84
+ "Stopped: this panel's dry run didn't finish in time. Estimate it on its own with panelId.",
85
+ ),
86
+ );
87
+ controller.abort();
88
+ }, remaining);
89
+ });
90
+ try {
91
+ return await Promise.race([
92
+ estimateResolvedPanel(panel, scope, runsPerMonth, controller.signal),
93
+ timedOut,
94
+ ]);
95
+ } finally {
96
+ clearTimeout(timer);
97
+ signal?.removeEventListener("abort", forwardAbort);
98
+ }
99
+ }
100
+
101
+ async function mapPool<T, R>(
102
+ items: readonly T[],
103
+ concurrency: number,
104
+ fn: (item: T) => Promise<R>,
105
+ ): Promise<R[]> {
106
+ const results: R[] = Array(items.length);
107
+ let next = 0;
108
+ const worker = async () => {
109
+ while (next < items.length) {
110
+ const index = next++;
111
+ results[index] = await fn(items[index]);
112
+ }
113
+ };
114
+ await Promise.all(
115
+ Array.from({ length: Math.min(concurrency, items.length) }, worker),
116
+ );
117
+ return results;
118
+ }
119
+
120
+ function sentence(text: string): string {
121
+ return /[.!?]$/.test(text) ? text : `${text}.`;
122
+ }
123
+
124
+ function describeEstimate(estimate: QueryCostEstimate): string {
125
+ if (
126
+ estimate.status === "not_bigquery" ||
127
+ estimate.status === "not_estimated"
128
+ ) {
129
+ return estimate.reason;
130
+ }
131
+ if (estimate.status === "failed") {
132
+ return `no estimate (${estimate.failure}): ${estimate.error}`;
133
+ }
134
+ const monthly =
135
+ estimate.usdPerMonth === null
136
+ ? "not scheduled"
137
+ : `~${formatUsd(estimate.usdPerMonth)}/month over ${estimate.runsPerMonth} scheduled runs`;
138
+ const flags = [
139
+ estimate.overPerRunThreshold
140
+ ? `over the ${formatUsd(QUERY_COST_THRESHOLDS.perRunUsd)}/run threshold`
141
+ : null,
142
+ estimate.overPerMonthThreshold
143
+ ? `over the ${formatUsd(QUERY_COST_THRESHOLDS.perMonthUsd)}/month threshold`
144
+ : null,
145
+ ].filter(Boolean);
146
+ return `~${formatBytes(estimate.estimatedBytes)}, ${formatUsd(estimate.usdPerRun)} per run, ${monthly}${flags.length ? ` (${flags.join("; ")})` : ""}`;
147
+ }
148
+
149
+ export default defineAction({
150
+ description:
151
+ "Free cost estimate for BigQuery SQL. Dry-runs the query through Analytics' own BigQuery connection (BigQuery reads and bills nothing) and returns the bytes it would scan, dollars per run at on-demand pricing, and dollars per month for scheduled runs. " +
152
+ "Pass `sql` to estimate any query (source 'bigquery' for warehouse SQL, 'first-party' for analytics_events SQL), or `dashboardId` (plus optional `panelId`) to estimate saved panels exactly as the dashboard runs them. " +
153
+ `Call it before running or saving a query that may scan a large table, and before setting a byte cap (about 1.5x the estimate is common). Results over $${QUERY_COST_THRESHOLDS.perRunUsd}/run or $${QUERY_COST_THRESHOLDS.perMonthUsd}/month are flagged; tell the user the number before going ahead.`,
154
+ schema: z.object({
155
+ sql: z
156
+ .string()
157
+ .min(1)
158
+ .optional()
159
+ .describe(
160
+ "SQL to estimate. Use this or dashboardId, not both. Dashboard {{filter}} tokens are not resolved here; pass dashboardId for saved panels.",
161
+ ),
162
+ source: z
163
+ .enum(["bigquery", "first-party"])
164
+ .optional()
165
+ .default("bigquery")
166
+ .describe(
167
+ "Dialect of `sql`: 'bigquery' (standard SQL against the warehouse, the default) or 'first-party' (Analytics' analytics_events SQL, rendered the way first-party panels send it).",
168
+ ),
169
+ eventsSource: z
170
+ .enum(["raw"])
171
+ .optional()
172
+ .describe(
173
+ "First-party sql only: 'raw' prices the raw events table even when the events model covers the query. Alerts read the raw table, so pass it when estimating an alert.",
174
+ ),
175
+ dashboardId: z
176
+ .string()
177
+ .min(1)
178
+ .optional()
179
+ .describe(
180
+ "Saved SQL dashboard to estimate. Without panelId, every queryable panel is estimated.",
181
+ ),
182
+ panelId: z
183
+ .string()
184
+ .min(1)
185
+ .optional()
186
+ .describe("One panel inside dashboardId."),
187
+ filters: z
188
+ .record(z.string(), z.string())
189
+ .optional()
190
+ .describe(
191
+ "Dashboard filter values keyed by filter id, e.g. {timeRange:'90d'}. Omit for the defaults a fresh tab shows.",
192
+ ),
193
+ // null and "" mean "not given", not 0, so the report-schedule default holds.
194
+ runsPerMonth: z
195
+ .preprocess(
196
+ (value) => (value === null || value === "" ? undefined : value),
197
+ z.coerce.number().int().min(0).max(100_000).optional(),
198
+ )
199
+ .describe(
200
+ "Scheduled runs per month, e.g. 30 for a daily job or 8640 for a 5-minute alert. For a dashboard this defaults to one run a day per enabled email report; for raw SQL there is no monthly figure without it.",
201
+ ),
202
+ }),
203
+ http: { method: "POST" },
204
+ readOnly: true,
205
+ mcpTool: true,
206
+ publicAgent: { expose: true, readOnly: true, requiresAuth: true },
207
+ timeoutMs: 55_000,
208
+ run: async (args, context?: ActionRunContext) => {
209
+ const startedAt = Date.now();
210
+ if (Boolean(args.sql) === Boolean(args.dashboardId)) {
211
+ fail("Pass exactly one of sql or dashboardId.", {
212
+ errorCode: "invalid_target",
213
+ statusCode: 400,
214
+ });
215
+ }
216
+ if (args.panelId && !args.dashboardId) {
217
+ fail("panelId needs dashboardId.", {
218
+ errorCode: "invalid_target",
219
+ statusCode: 400,
220
+ });
221
+ }
222
+ if (args.eventsSource && !(args.sql && args.source === "first-party")) {
223
+ fail("eventsSource applies only to first-party sql.", {
224
+ errorCode: "invalid_target",
225
+ statusCode: 400,
226
+ });
227
+ }
228
+ const userEmail = getRequestUserEmail();
229
+ if (!userEmail) {
230
+ fail("Sign in to use this action.", {
231
+ errorCode: "unauthenticated",
232
+ statusCode: 401,
233
+ });
234
+ }
235
+ const orgId = getRequestOrgId() || null;
236
+ const credentialContext = getCredentialContext();
237
+ const scope: AnalyticsScope = {
238
+ userEmail,
239
+ orgId,
240
+ ...(credentialContext?.credentialScope === "org"
241
+ ? { credentialScope: "org" as const }
242
+ : {}),
243
+ };
244
+ const signal = context?.signal;
245
+ const pricing = {
246
+ model: "on-demand",
247
+ usdPerTiB: ON_DEMAND_USD_PER_TIB,
248
+ thresholds: QUERY_COST_THRESHOLDS,
249
+ };
250
+
251
+ if (args.sql) {
252
+ const runsPerMonth = args.runsPerMonth ?? null;
253
+ const estimate =
254
+ args.source === "first-party"
255
+ ? await estimateFirstPartySql(args.sql, scope, runsPerMonth, signal, {
256
+ eventsSource: args.eventsSource,
257
+ })
258
+ : await estimateBigQuerySql(args.sql, runsPerMonth, signal);
259
+ return {
260
+ target: "sql",
261
+ source: args.source,
262
+ ...estimate,
263
+ pricing,
264
+ caveats: QUERY_COST_CAVEATS,
265
+ summary: sentence(`Estimate: ${describeEstimate(estimate)}`),
266
+ };
267
+ }
268
+
269
+ const dashboardId = args.dashboardId!;
270
+ if (!isSafeDashboardId(dashboardId)) {
271
+ fail(
272
+ `${JSON.stringify(clipHead(dashboardId, 60))} is not a dashboard id: ids hold only letters, digits, dot, dash and underscore.`,
273
+ { errorCode: "invalid_dashboard_id", statusCode: 400 },
274
+ );
275
+ }
276
+ const dashboard = await getDashboard(dashboardId, {
277
+ email: userEmail,
278
+ orgId,
279
+ });
280
+ // Like get-sql-dashboard, a seed with the same id stands in for a stored
281
+ // dashboard that isn't SQL.
282
+ const stored = dashboard?.kind === "sql" ? dashboard : null;
283
+ const seed = stored ? null : loadDashboardSeed(dashboardId);
284
+ if (!stored && !seed) {
285
+ if (dashboard) {
286
+ fail(
287
+ `estimate-query-cost only supports SQL dashboards; "${dashboardId}" is ${dashboard.kind}.`,
288
+ { errorCode: "dashboard_not_sql", statusCode: 400 },
289
+ );
290
+ }
291
+ fail(
292
+ `Dashboard "${dashboardId}" was not found, or you don't have access to it.`,
293
+ { errorCode: "dashboard_not_found", statusCode: 404 },
294
+ );
295
+ }
296
+
297
+ const config = pageDashboardConfig(
298
+ stored ? stored.config : seed!,
299
+ dashboardId,
300
+ );
301
+ const resolved = resolveDashboardPanelQueries(config, args.filters);
302
+ const selected = args.panelId
303
+ ? resolved.filter((panel) => panel.panelId === args.panelId)
304
+ : resolved;
305
+ if (args.panelId && selected.length === 0) {
306
+ fail(
307
+ `Panel "${args.panelId}" is not a queryable panel in dashboard "${dashboardId}". Queryable panel ids: ${resolved
308
+ .slice(0, 40)
309
+ .map((panel) => panel.panelId)
310
+ .join(", ")}.`,
311
+ { errorCode: "panel_not_found", statusCode: 404 },
312
+ );
313
+ }
314
+
315
+ const reportSchedules = await countEnabledDashboardReportSubscriptions(
316
+ dashboardId,
317
+ { email: userEmail, orgId },
318
+ );
319
+ const runsPerMonth =
320
+ args.runsPerMonth ??
321
+ (reportSchedules > 0 ? reportSchedules * DAYS_PER_MONTH : null);
322
+ const estimated = selected.slice(0, MAX_PANELS);
323
+ const deadline = startedAt + DASHBOARD_DEADLINE_MS;
324
+ const panels: PanelCostEstimate[] = await mapPool(
325
+ estimated,
326
+ DRY_RUN_CONCURRENCY,
327
+ (panel) =>
328
+ estimatePanelBefore(deadline, panel, scope, runsPerMonth, signal),
329
+ );
330
+ const total = totalCost(panels);
331
+ const flagged = panels.filter(
332
+ (panel) =>
333
+ panel.status === "estimated" &&
334
+ (panel.overPerRunThreshold || panel.overPerMonthThreshold),
335
+ );
336
+ const failed = panels.filter((panel) => panel.status === "failed").length;
337
+ const priced = panels.filter(
338
+ (panel) => panel.status === "estimated",
339
+ ).length;
340
+ const notEstimated = panels.filter(
341
+ (panel) => panel.status === "not_estimated",
342
+ ).length;
343
+ const omitted = Math.max(0, selected.length - MAX_PANELS);
344
+ // Panels outside BigQuery cost nothing; any other gap makes the total partial.
345
+ const partial = failed + notEstimated + omitted > 0;
346
+ // With panelId the total is that panel's, never the dashboard's.
347
+ const onePanel = args.panelId !== undefined;
348
+ const totalScope = onePanel
349
+ ? "per refresh of this panel"
350
+ : partial
351
+ ? "per refresh of the priced panels only"
352
+ : "per full refresh";
353
+ // Report schedules keep their own saved filters; this prices them at the
354
+ // filters passed here (or the defaults), so say so.
355
+ const monthly =
356
+ total.usdPerMonth === null
357
+ ? "no scheduled runs"
358
+ : args.runsPerMonth === undefined
359
+ ? `~${formatUsd(total.usdPerMonth)}/month if its email reports use these filters`
360
+ : `~${formatUsd(total.usdPerMonth)}/month in scheduled runs`;
361
+ const totalFlags = {
362
+ overPerRunThreshold: total.usdPerRun > QUERY_COST_THRESHOLDS.perRunUsd,
363
+ overPerMonthThreshold:
364
+ total.usdPerMonth !== null &&
365
+ total.usdPerMonth > QUERY_COST_THRESHOLDS.perMonthUsd,
366
+ };
367
+ const totalOver = [
368
+ totalFlags.overPerRunThreshold &&
369
+ `the ${formatUsd(QUERY_COST_THRESHOLDS.perRunUsd)}/run`,
370
+ totalFlags.overPerMonthThreshold &&
371
+ `the ${formatUsd(QUERY_COST_THRESHOLDS.perMonthUsd)}/month`,
372
+ ].filter(Boolean);
373
+
374
+ return {
375
+ target: "dashboard",
376
+ dashboardId,
377
+ filterState:
378
+ args.filters && Object.keys(args.filters).length > 0
379
+ ? "overridden"
380
+ : "defaults",
381
+ runsPerMonth,
382
+ runsPerMonthBasis:
383
+ args.runsPerMonth !== undefined
384
+ ? "caller"
385
+ : reportSchedules > 0
386
+ ? `${reportSchedules} enabled daily email report${reportSchedules === 1 ? "" : "s"} ${orgId ? "in your org" : "of yours"}`
387
+ : "none",
388
+ total: {
389
+ ...total,
390
+ ...totalFlags,
391
+ partial,
392
+ scope: onePanel ? "panel" : "dashboard",
393
+ },
394
+ panels,
395
+ ...(selected.length > MAX_PANELS
396
+ ? { omittedPanelIds: selected.slice(MAX_PANELS).map((p) => p.panelId) }
397
+ : {}),
398
+ pricing,
399
+ caveats: QUERY_COST_CAVEATS,
400
+ summary:
401
+ (priced === 0
402
+ ? `${panels.length} panel${panels.length === 1 ? "" : "s"}: ${partial ? "none could be priced." : "none read BigQuery, so nothing was priced."}`
403
+ : `${panels.length} panel${panels.length === 1 ? "" : "s"} (${priced} priced): ~${formatBytes(total.estimatedBytes)} and ${formatUsd(total.usdPerRun)} ${totalScope}, ${monthly}.`) +
404
+ (totalOver.length && !onePanel
405
+ ? ` The dashboard as a whole is over ${totalOver.join(" and ")} threshold${totalOver.length > 1 ? "s" : ""}${partial ? ", even counting only the priced panels" : ""}.`
406
+ : "") +
407
+ (flagged.length
408
+ ? ` Over threshold: ${flagged.map((panel) => `"${panel.title}" (${describeEstimate(panel)})`).join("; ")}.`
409
+ : "") +
410
+ (failed
411
+ ? ` ${failed} panel${failed === 1 ? "" : "s"} could not be estimated.`
412
+ : "") +
413
+ (notEstimated
414
+ ? ` ${notEstimated} panel${notEstimated === 1 ? "" : "s"} may read BigQuery but ${notEstimated === 1 ? "isn't" : "aren't"} priced here.`
415
+ : "") +
416
+ (omitted
417
+ ? ` ${omitted} panel${omitted === 1 ? "" : "s"} past the first ${MAX_PANELS} ${omitted === 1 ? "wasn't" : "weren't"} estimated (see omittedPanelIds).`
418
+ : ""),
419
+ };
420
+ },
421
+ });
@@ -233,7 +233,11 @@ const allowEmptyResultHelp =
233
233
  "Set true only when the user expects an edited panel to have no rows right now; the save then reports verified:false. It never overrides missing columns or query errors.";
234
234
 
235
235
  const agentInputSchema = z.object({
236
- dashboardId: z.string().min(1).describe("Dashboard id."),
236
+ dashboardId: z
237
+ .string()
238
+ .min(1)
239
+ .optional()
240
+ .describe("Dashboard id. Omit only when requesting returnTypes."),
237
241
  operations: z
238
242
  .array(mutationOperationSchema)
239
243
  .max(MAX_DASHBOARD_MUTATION_OPERATIONS)
@@ -250,6 +254,10 @@ const agentInputSchema = z.object({
250
254
  .boolean()
251
255
  .optional()
252
256
  .describe("Include the full resulting config only when needed."),
257
+ returnTypes: z
258
+ .boolean()
259
+ .optional()
260
+ .describe("With no dashboardId, return the `code` API and examples."),
253
261
  });
254
262
 
255
263
  function resolveScope() {
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-19
4
+ ---
5
+
6
+ Composer focus remains safe when an editor changes during navigation.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-19
4
+ ---
5
+
6
+ Dashboard API guidance works without an open dashboard
@@ -4,6 +4,7 @@ import type { AgentChatMcpOptions } from "@agent-native/core/server";
4
4
  // framework's cross-app builtins. `mcp-action-contract.spec.ts` serves this
5
5
  // config through the real MCP handler and pins the resulting tools/list.
6
6
  export const ANALYTICS_MCP = {
7
+ connectorCatalog: [],
7
8
  externalAgents: { writes: "allowlisted" },
8
9
  keyToolNames: [
9
10
  "list-sql-dashboards",
@@ -1121,15 +1121,24 @@ export interface DryRunQueryOptions {
1121
1121
  }
1122
1122
 
1123
1123
  export class BigQueryDryRunPreparationError extends Error {
1124
- constructor() {
1124
+ /** True when the failure was missing BigQuery credentials or project. */
1125
+ readonly notConfigured: boolean;
1126
+
1127
+ constructor(options: { notConfigured?: boolean } = {}) {
1125
1128
  super("BigQuery dry-run request preparation failed");
1126
1129
  this.name = "BigQueryDryRunPreparationError";
1130
+ this.notConfigured = options.notConfigured === true;
1127
1131
  }
1128
1132
  }
1129
1133
 
1134
+ const BIGQUERY_NOT_CONFIGURED_PATTERN =
1135
+ /GOOGLE_APPLICATION_CREDENTIALS_JSON not configured|BIGQUERY_PROJECT_ID|service account|Token exchange failed/i;
1136
+
1130
1137
  export interface DryRunQueryResult {
1131
1138
  error: string | null;
1132
1139
  timedOut?: true;
1140
+ /** HTTP status of a failed dry-run request; 400 means BigQuery rejected the SQL. */
1141
+ status?: number;
1133
1142
  /** Absent when BigQuery's dry-run response carried no schema. */
1134
1143
  schema?: { name: string; type: string }[];
1135
1144
  /** Absent when BigQuery's dry-run response carried no byte estimate. */
@@ -1208,7 +1217,11 @@ export async function dryRunQuerySchema(
1208
1217
  throw error;
1209
1218
  }
1210
1219
  if (options.wrapPreparationErrors) {
1211
- throw new BigQueryDryRunPreparationError();
1220
+ throw new BigQueryDryRunPreparationError({
1221
+ notConfigured:
1222
+ error instanceof Error &&
1223
+ BIGQUERY_NOT_CONFIGURED_PATTERN.test(error.message),
1224
+ });
1212
1225
  }
1213
1226
  throw error;
1214
1227
  }
@@ -1252,12 +1265,15 @@ export async function dryRunQuerySchema(
1252
1265
  error?: { message?: string };
1253
1266
  };
1254
1267
  const msg = parsed.error?.message?.trim();
1255
- if (msg) return { error: msg };
1268
+ if (msg) return { error: msg, status: res.status };
1256
1269
  // coercion-ok: malformed BigQuery error bodies use the status fallback below.
1257
1270
  } catch {
1258
1271
  // Fall through
1259
1272
  }
1260
- return { error: `BigQuery validation failed (${res.status})` };
1273
+ return {
1274
+ error: `BigQuery validation failed (${res.status})`,
1275
+ status: res.status,
1276
+ };
1261
1277
  } catch (error) {
1262
1278
  if (timedOut) return { error: timeoutMessage, timedOut: true };
1263
1279
  throw error;
@@ -350,6 +350,44 @@ function interpolationFailure(
350
350
  return null;
351
351
  }
352
352
 
353
+ export type ResolvedDashboardPanelQuery =
354
+ | { panelId: string; title: string; source: string; query: string }
355
+ | { panelId: string; title: string; source: string; error: string };
356
+
357
+ /**
358
+ * The SQL each queryable panel sends for the given filters (dashboard defaults
359
+ * when omitted), resolved the way verification does, without running anything.
360
+ * Section and extension panels have no query and are left out.
361
+ */
362
+ export function resolveDashboardPanelQueries(
363
+ rawConfig: Record<string, unknown>,
364
+ filters?: Record<string, string>,
365
+ ): ResolvedDashboardPanelQuery[] {
366
+ const config = normalizeDashboardConfig(rawConfig);
367
+ const vars = resolveVerificationVars(config, filters);
368
+ return panelsOf(config)
369
+ .filter((panel) => typeof panel.id === "string" && hasSqlToRun(panel))
370
+ .map((panel) => {
371
+ const panelId = String(panel.id);
372
+ const title = typeof panel.title === "string" ? panel.title : panelId;
373
+ const source = typeof panel.source === "string" ? panel.source : "";
374
+ try {
375
+ const query = buildPanelQuery(panel as unknown as SqlPanel, vars);
376
+ const failure = interpolationFailure(query, panel.sql, vars);
377
+ return failure
378
+ ? { panelId, title, source, error: failure }
379
+ : { panelId, title, source, query };
380
+ } catch (error) {
381
+ return {
382
+ panelId,
383
+ title,
384
+ source,
385
+ error: error instanceof Error ? error.message : String(error),
386
+ };
387
+ }
388
+ });
389
+ }
390
+
353
391
  function truncateCell(value: unknown): unknown {
354
392
  const text =
355
393
  typeof value === "string"
@@ -434,6 +434,36 @@ export async function listDashboardReportSubscriptions(
434
434
  return rows.map(rowToSubscription);
435
435
  }
436
436
 
437
+ /**
438
+ * Enabled daily report schedules on a dashboard in the caller's tenant: every
439
+ * owner's in the caller's org, or only the caller's own without an org. Each
440
+ * one re-runs the dashboard's panels once a day on its owner's BigQuery
441
+ * connection, so other tenants' schedules bill other tenants and never count.
442
+ * Only the number is returned, never the subscriptions themselves.
443
+ */
444
+ export async function countEnabledDashboardReportSubscriptions(
445
+ dashboardId: string,
446
+ ctx: AccessCtx,
447
+ ): Promise<number> {
448
+ const db = getDb() as any;
449
+ const [row] = await db
450
+ .select({ count: sql<number>`count(*)` })
451
+ .from(schema.dashboardReportSubscriptions)
452
+ .where(
453
+ and(
454
+ eq(schema.dashboardReportSubscriptions.dashboardId, dashboardId),
455
+ eq(schema.dashboardReportSubscriptions.enabled, true),
456
+ ctx.orgId
457
+ ? eq(schema.dashboardReportSubscriptions.orgId, ctx.orgId)
458
+ : and(
459
+ isNull(schema.dashboardReportSubscriptions.orgId),
460
+ sql`lower(${schema.dashboardReportSubscriptions.ownerEmail}) = ${ctx.email.toLowerCase()}`,
461
+ ),
462
+ ),
463
+ );
464
+ return Number(row?.count ?? 0);
465
+ }
466
+
437
467
  export async function getDashboardReportSubscription(
438
468
  id: string,
439
469
  ctx: AccessCtx,