@agent-native/core 0.189.0 → 0.190.0-nightly-20260925215540

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 (234) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +10 -0
  3. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +1 -1
  4. package/corpus/templates/analytics/AGENTS.md +11 -22
  5. package/corpus/templates/analytics/actions/list-data-dictionary.ts +7 -9
  6. package/corpus/templates/analytics/actions/search-analytics-query-catalog.ts +1 -1
  7. package/corpus/templates/analytics/app/components/AnalyticsReviewArtifactPreview.tsx +201 -0
  8. package/corpus/templates/analytics/app/i18n/en-US.ts +2 -0
  9. package/corpus/templates/analytics/app/pages/Settings.tsx +50 -3
  10. package/corpus/templates/analytics/changelog/2026-09-25-first-run-onboarding-records-setup-choices-and-builder-conne.md +6 -0
  11. package/corpus/templates/analytics/changelog/2026-09-25-human-review-previews-analytics-dashboards-as-real-charts.md +6 -0
  12. package/corpus/templates/analytics/changelog/2026-09-25-org-admins-can-review-agent-runs-from-settings.md +6 -0
  13. package/corpus/templates/analytics/changelog/2026-09-25-proactive-query-context.md +6 -0
  14. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +98 -2
  15. package/corpus/templates/analytics/server/lib/analytics-agent-context.ts +557 -0
  16. package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +217 -46
  17. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +2 -2
  18. package/corpus/templates/analytics/server/lib/dashboards-store.ts +39 -5
  19. package/corpus/templates/analytics/server/lib/data-dictionary-context.ts +4 -0
  20. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +268 -2
  21. package/corpus/templates/analytics/server/plugins/agent-chat.ts +44 -9
  22. package/corpus/templates/calendar/AGENTS.md +5 -0
  23. package/corpus/templates/calendar/CHANGELOG.md +6 -0
  24. package/corpus/templates/calendar/actions/get-event-rules-status.ts +47 -0
  25. package/corpus/templates/calendar/actions/list-events.ts +50 -4
  26. package/corpus/templates/calendar/actions/undo-calendar-event-rule.ts +229 -0
  27. package/corpus/templates/calendar/actions/update-settings.ts +8 -0
  28. package/corpus/templates/calendar/app/i18n/en-US.ts +27 -0
  29. package/corpus/templates/calendar/app/pages/Settings.tsx +196 -1
  30. package/corpus/templates/calendar/changelog/2026-09-25-calendar-feeds-with-the-same-url-keep-their-own-names-and-co.md +6 -0
  31. package/corpus/templates/calendar/changelog/2026-09-25-calendar-invitation-rules-surface-expired-connections-and-un.md +6 -0
  32. package/corpus/templates/calendar/changelog/2026-09-25-restore-locally-hidden-events-from-activity-after-disconnect.md +6 -0
  33. package/corpus/templates/calendar/server/lib/calendar-settings.ts +44 -10
  34. package/corpus/templates/calendar/server/lib/google-api.ts +15 -1
  35. package/corpus/templates/calendar/server/lib/google-calendar.ts +1 -1
  36. package/corpus/templates/calendar/server/plugins/event-rules.ts +628 -0
  37. package/corpus/templates/calendar/shared/api.ts +13 -0
  38. package/corpus/templates/calendar/shared/settings.ts +71 -1
  39. package/corpus/templates/clips/actions/create-recording.ts +83 -2
  40. package/corpus/templates/clips/actions/finalize-recording.ts +610 -110
  41. package/corpus/templates/clips/actions/get-recording-player-data.ts +6 -0
  42. package/corpus/templates/clips/actions/import-loom-recording.ts +2 -0
  43. package/corpus/templates/clips/actions/lib/create-recording-schema.ts +7 -0
  44. package/corpus/templates/clips/actions/lib/loom-import-job.ts +15 -1
  45. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +126 -26
  46. package/corpus/templates/clips/app/hooks/use-drop-video-upload.ts +75 -15
  47. package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +5 -1
  48. package/corpus/templates/clips/app/routes/record.tsx +134 -40
  49. package/corpus/templates/clips/app/routes/share.$shareId.tsx +13 -1
  50. package/corpus/templates/clips/changelog/2026-09-25-signed-in-viewers-who-hit-an-unavailable-expired-or-private-.md +6 -0
  51. package/corpus/templates/clips/chrome-extension/src/background.ts +3 -0
  52. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +73 -16
  53. package/corpus/templates/clips/desktop/src/lib/recorder.ts +188 -18
  54. package/corpus/templates/clips/desktop/src/lib/recording-request.ts +1 -0
  55. package/corpus/templates/clips/server/db/schema.ts +4 -0
  56. package/corpus/templates/clips/server/jobs/media-verification.ts +78 -4
  57. package/corpus/templates/clips/server/jobs/recording-failure-backfill.ts +142 -0
  58. package/corpus/templates/clips/server/lib/media-verification-state.ts +29 -0
  59. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +2 -0
  60. package/corpus/templates/clips/server/lib/recording-failures.ts +111 -0
  61. package/corpus/templates/clips/server/lib/recordings.ts +6 -1
  62. package/corpus/templates/clips/server/lib/s3-upload-provider.ts +8 -3
  63. package/corpus/templates/clips/server/lib/upload-lease.ts +25 -6
  64. package/corpus/templates/clips/server/plugins/calendar-jobs.ts +2 -0
  65. package/corpus/templates/clips/server/plugins/db.ts +18 -0
  66. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +48 -5
  67. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +322 -31
  68. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +223 -61
  69. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +62 -4
  70. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +74 -7
  71. package/corpus/templates/clips/shared/recording-core.ts +27 -0
  72. package/corpus/templates/design/actions/get-design.ts +35 -6
  73. package/corpus/templates/mail/.agents/skills/inbox-automations/SKILL.md +4 -0
  74. package/corpus/templates/mail/actions/consolidate-ai-filter-rules.ts +41 -0
  75. package/corpus/templates/mail/actions/get-ai-priority.ts +48 -8
  76. package/corpus/templates/mail/actions/record-ai-priority-feedback.ts +69 -0
  77. package/corpus/templates/mail/actions/update-mail-preferences.ts +2 -0
  78. package/corpus/templates/mail/app/components/email/EmailList.tsx +179 -32
  79. package/corpus/templates/mail/app/components/email/EmailListItem.tsx +97 -9
  80. package/corpus/templates/mail/app/components/email/EmailThread.tsx +55 -1
  81. package/corpus/templates/mail/app/components/email/ImportanceFeedbackMenu.tsx +52 -0
  82. package/corpus/templates/mail/app/components/email/compose-autocomplete.ts +2 -1
  83. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +219 -188
  84. package/corpus/templates/mail/app/components/onboarding/AiInboxSetup.tsx +338 -0
  85. package/corpus/templates/mail/app/components/settings/AiFilterSection.tsx +597 -781
  86. package/corpus/templates/mail/app/components/settings/AiRulePromptField.tsx +37 -0
  87. package/corpus/templates/mail/app/global.css +42 -26
  88. package/corpus/templates/mail/app/hooks/use-ai-priority-feedback.ts +43 -0
  89. package/corpus/templates/mail/app/hooks/use-automations.ts +23 -0
  90. package/corpus/templates/mail/app/i18n/en-US.ts +58 -3
  91. package/corpus/templates/mail/app/pages/InboxPage.tsx +47 -10
  92. package/corpus/templates/mail/changelog/2026-09-25-editing-importance-rules-preserves-disabled-instructions-and.md +6 -0
  93. package/corpus/templates/mail/changelog/2026-09-25-handle-astral-unicode-letters-in-autocomplete-word-boundarie.md +6 -0
  94. package/corpus/templates/mail/changelog/2026-09-25-jev-priority-feedback-and-inbox-settings.md +6 -0
  95. package/corpus/templates/mail/changelog/2026-09-25-keep-existing-ai-filter-rules-intact-when-saving-a-prompt.md +6 -0
  96. package/corpus/templates/mail/server/lib/automation-engine.ts +21 -12
  97. package/corpus/templates/mail/server/lib/automations.ts +100 -1
  98. package/corpus/templates/mail/shared/types.ts +3 -0
  99. package/corpus/templates/plan/app/i18n/en-US.ts +6 -0
  100. package/corpus/templates/plan/app/lib/plan-invite-suggestion.ts +43 -0
  101. package/corpus/templates/plan/app/pages/PlansPage.tsx +249 -4
  102. package/corpus/templates/slides/actions/create-deck.ts +11 -1
  103. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +117 -1
  104. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +373 -330
  105. package/corpus/templates/slides/app/components/design-system/builder-index-response.ts +36 -5
  106. package/corpus/templates/slides/app/components/editor/BlockBubbleMenu.tsx +21 -53
  107. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +347 -671
  108. package/corpus/templates/slides/app/components/editor/bullet-editing.ts +55 -8
  109. package/corpus/templates/slides/app/components/editor/in-place-text-session.ts +2082 -0
  110. package/corpus/templates/slides/app/components/editor/list-editing.ts +174 -16
  111. package/corpus/templates/slides/app/components/editor/rich-text-selection.ts +497 -62
  112. package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +102 -20
  113. package/corpus/templates/slides/app/context/DeckContext.tsx +9 -4
  114. package/corpus/templates/slides/app/global.css +7 -219
  115. package/corpus/templates/slides/app/i18n/en-US.ts +3 -0
  116. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +7 -0
  117. package/corpus/templates/slides/app/lib/slide-image-replacement.ts +203 -1
  118. package/corpus/templates/slides/app/lib/slide-source-map.ts +43 -0
  119. package/corpus/templates/slides/app/pages/DeckEditor.tsx +182 -4
  120. package/corpus/templates/slides/app/routes/settings.tsx +33 -2
  121. package/corpus/templates/slides/changelog/2026-09-25-improve-slides-design-system-setup-feedback.md +6 -0
  122. package/corpus/templates/slides/changelog/2026-09-25-org-admins-can-review-agent-runs-from-settings.md +6 -0
  123. package/corpus/templates/slides/changelog/2026-09-25-text-on-a-slide-is-now-edited-in-place-clicking-into-it-chan.md +6 -0
  124. package/corpus/templates/slides/package.json +0 -12
  125. package/corpus/templates/slides/scripts/edit-fidelity/README.md +4 -2
  126. package/corpus/templates/slides/scripts/edit-fidelity/run.ts +12 -3
  127. package/corpus/templates/slides/vite.config.ts +1 -10
  128. package/dist/agent/jev-tool-prefetch.d.ts +29 -3
  129. package/dist/agent/jev-tool-prefetch.js +161 -34
  130. package/dist/agent/production-agent.d.ts +11 -0
  131. package/dist/agent/production-agent.js +39 -8
  132. package/dist/app-config/runtime.d.ts +1 -0
  133. package/dist/app-config/runtime.js +4 -0
  134. package/dist/app-config/schema.d.ts +1 -0
  135. package/dist/client/AgentSidebar.d.ts +3 -1
  136. package/dist/client/AgentSidebar.js +8 -12
  137. package/dist/client/analytics/index.d.ts +1 -1
  138. package/dist/client/analytics/index.js +1 -1
  139. package/dist/client/analytics.d.ts +2 -0
  140. package/dist/client/analytics.js +9 -0
  141. package/dist/client/api-path.js +5 -2
  142. package/dist/client/chat/run-recovery.d.ts +0 -3
  143. package/dist/client/chat/run-recovery.js +13 -23
  144. package/dist/client/index.d.ts +1 -1
  145. package/dist/client/index.js +1 -1
  146. package/dist/client/observability/ObservabilityDashboard.d.ts +3 -0
  147. package/dist/client/observability/ObservabilityDashboard.js +366 -71
  148. package/dist/client/observability/ObservabilityReviewSummaryButton.d.ts +4 -1
  149. package/dist/client/observability/ObservabilityReviewSummaryButton.js +13 -9
  150. package/dist/client/observability/OutputPreview.d.ts +9 -4
  151. package/dist/client/observability/OutputPreview.js +230 -52
  152. package/dist/client/onboarding/FirstRunOnboarding.js +67 -4
  153. package/dist/client/onboarding/use-onboarding.js +2 -0
  154. package/dist/client/sharing/ShareButton.d.ts +2 -0
  155. package/dist/client/sharing/ShareButton.js +1 -0
  156. package/dist/client/sharing/useShareButtonController.d.ts +1 -0
  157. package/dist/client/sharing/useShareButtonController.js +29 -8
  158. package/dist/collab/awareness.d.ts +2 -2
  159. package/dist/collab/struct-routes.d.ts +1 -1
  160. package/dist/deploy/build.js +9 -1
  161. package/dist/embeddings/index.d.ts +3 -1
  162. package/dist/embeddings/index.js +20 -10
  163. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  164. package/dist/jobs/sweep-hooks.d.ts +7 -0
  165. package/dist/jobs/sweep-hooks.js +28 -0
  166. package/dist/localization/default-messages.d.ts +1 -0
  167. package/dist/localization/default-messages.js +1 -0
  168. package/dist/notifications/routes.d.ts +6 -6
  169. package/dist/observability/actions/authorization.d.ts +1 -0
  170. package/dist/observability/actions/authorization.js +22 -0
  171. package/dist/observability/actions/get-observability-review-detail.d.ts +5 -0
  172. package/dist/observability/actions/get-observability-review-detail.js +10 -2
  173. package/dist/observability/actions/get-observability-review-summary-source.d.ts +2 -0
  174. package/dist/observability/actions/get-observability-review-summary-source.js +3 -2
  175. package/dist/observability/actions/save-observability-instruction-update.js +2 -1
  176. package/dist/observability/actions/save-observability-review-summary.js +21 -10
  177. package/dist/observability/migrations.js +25 -0
  178. package/dist/observability/reviews.d.ts +3 -1
  179. package/dist/observability/reviews.js +410 -53
  180. package/dist/observability/routes.d.ts +6 -6
  181. package/dist/observability/store.d.ts +15 -0
  182. package/dist/observability/store.js +131 -11
  183. package/dist/observability/types.d.ts +18 -0
  184. package/dist/org/handlers.d.ts +1 -1
  185. package/dist/org/index.d.ts +1 -1
  186. package/dist/progress/routes.d.ts +1 -1
  187. package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
  188. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  189. package/dist/server/agent-chat/plugin-options.d.ts +4 -20
  190. package/dist/server/agent-chat/prompt-resources.d.ts +16 -0
  191. package/dist/server/agent-chat/prompt-resources.js +385 -22
  192. package/dist/server/agent-chat-plugin.d.ts +3 -1
  193. package/dist/server/agent-chat-plugin.js +149 -27
  194. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  195. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  196. package/dist/server/index.d.ts +3 -0
  197. package/dist/server/index.js +3 -0
  198. package/dist/server/prompts/framework-core-compact.js +1 -1
  199. package/dist/server/prompts/framework-core.js +1 -1
  200. package/dist/server/request-context.d.ts +6 -3
  201. package/dist/settings/org-settings.d.ts +4 -2
  202. package/dist/settings/org-settings.js +3 -3
  203. package/dist/settings/store.d.ts +3 -1
  204. package/dist/settings/store.js +8 -3
  205. package/dist/styles/agent-native.css +5 -0
  206. package/dist/templates/default/app/i18n/ar-SA.ts +1 -0
  207. package/dist/templates/default/app/i18n/de-DE.ts +1 -0
  208. package/dist/templates/default/app/i18n/en-US.ts +1 -0
  209. package/dist/templates/default/app/i18n/es-ES.ts +1 -0
  210. package/dist/templates/default/app/i18n/fr-FR.ts +1 -0
  211. package/dist/templates/default/app/i18n/hi-IN.ts +1 -0
  212. package/dist/templates/default/app/i18n/ja-JP.ts +1 -0
  213. package/dist/templates/default/app/i18n/ko-KR.ts +1 -0
  214. package/dist/templates/default/app/i18n/pt-BR.ts +1 -0
  215. package/dist/templates/default/app/i18n/zh-CN.ts +1 -0
  216. package/dist/templates/default/app/i18n/zh-TW.ts +1 -0
  217. package/dist/tracking/registry.js +11 -4
  218. package/dist/vite/client.js +6 -0
  219. package/package.json +4 -3
  220. package/src/templates/default/app/i18n/ar-SA.ts +1 -0
  221. package/src/templates/default/app/i18n/de-DE.ts +1 -0
  222. package/src/templates/default/app/i18n/en-US.ts +1 -0
  223. package/src/templates/default/app/i18n/es-ES.ts +1 -0
  224. package/src/templates/default/app/i18n/fr-FR.ts +1 -0
  225. package/src/templates/default/app/i18n/hi-IN.ts +1 -0
  226. package/src/templates/default/app/i18n/ja-JP.ts +1 -0
  227. package/src/templates/default/app/i18n/ko-KR.ts +1 -0
  228. package/src/templates/default/app/i18n/pt-BR.ts +1 -0
  229. package/src/templates/default/app/i18n/zh-CN.ts +1 -0
  230. package/src/templates/default/app/i18n/zh-TW.ts +1 -0
  231. package/corpus/templates/slides/app/components/editor/SlideBubbleMenu.tsx +0 -488
  232. package/corpus/templates/slides/app/components/editor/SlideInlineEditor.tsx +0 -589
  233. package/corpus/templates/slides/app/components/editor/SlideRichTextEditor.tsx +0 -1347
  234. package/corpus/templates/slides/app/components/editor/SlideSlashMenu.tsx +0 -373
package/corpus/README.md CHANGED
@@ -31,4 +31,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
31
31
 
32
32
  ## Generated Counts
33
33
 
34
- - template files: 9963
34
+ - template files: 9989
@@ -92,6 +92,16 @@ Inside `run-code`, use the workspace helper functions:
92
92
  download must appear in chat; do not answer with only a path or navigation
93
93
  instructions.
94
94
 
95
+ ## CSV and XLSX Exports
96
+
97
+ - For a compact result, use `query-agent-native-analytics` and its Download
98
+ CSV control. For a durable CSV, use `run-code` with `workspaceWrite` in a
99
+ normal Resources folder, then call `show-workspace-file` with that path. If
100
+ `run-code` is not available, discover it once with tool search.
101
+ - For an explicit `.xlsx` request, call `docs-search` once for `xlsx export`
102
+ and follow the returned workflow. The QuickJS `run-code` sandbox has no Node
103
+ imports; do not try to load `xlsx` or `exceljs` there.
104
+
95
105
  ## Chunked Batch Analysis (30+ items)
96
106
 
97
107
  For large fan-outs (account deep dives, Gong call reviews, deal cohorts):
@@ -11,7 +11,7 @@ The analytics app connects to multiple data sources. This skill covers general p
11
11
 
12
12
  ## Approach
13
13
 
14
- 0. **Orient catalog-first** — before querying, consult what already exists: the injected `<data-dictionary>` and data-source status tell you which sources are configured and which table/columns/join paths to use. Use them to pick the one source that owns the fact instead of fanning out blind queries.
14
+ 0. **Use retrieved references first** — data questions may start with a small set of relevant data-dictionary entries and saved dashboard panels in `<resource scope="analytics-catalog">`. Treat them as definitions and query examples, never live results. If they do not fit, call `search-analytics-query-catalog` before querying; use data-source status when provider availability matters.
15
15
  1. **Route named account health deliberately** — for a customer/org health, QBR, renewal, contract-utilization, risk, or adoption request, read `account-health` before writing SQL. It adds identity-lock and metric-definition checks that an ordinary lookup does not need.
16
16
  2. **Read the relevant provider skill first** — check `.agents/skills/<provider>/SKILL.md` for table names, column mappings, auth, and gotchas. For BigQuery, read `.agents/skills/bigquery/SKILL.md` and use `search-bigquery-schema` before guessing table or column names.
17
17
  3. **Clarify if ambiguous** — if the metric definition, date range, or grain is unclear and a wrong guess would change the numbers, use the `ask-question` clarifying tool (multiple-choice) before querying. Ask at most once per turn; skip it when the dictionary or the user already answered.
@@ -17,8 +17,8 @@ Read the relevant skill before deeper work:
17
17
  de-duplication).
18
18
  - `dashboard-management` for dashboard/panel storage, layout, extensions,
19
19
  mutation and sharing.
20
- - `adhoc-analysis` and `analysis-workspace` for one-off answers and large
21
- multi-source work.
20
+ - `adhoc-analysis` for one-off answers; `analysis-workspace` for large work and
21
+ CSV/XLSX exports.
22
22
  - `provider-api` and `data-programs` for the escape hatch and durable,
23
23
  refreshable data sources.
24
24
  - `creative-context` for governed contexts and immutable dashboard revisions.
@@ -26,13 +26,13 @@ Read the relevant skill before deeper work:
26
26
 
27
27
  ## How To Answer A Data Question
28
28
 
29
- 1. **Search existing work first.** For a metric question, call
30
- `search-analytics-query-catalog`; for dashboard replication or adaptation,
31
- call `search-dashboard-references` first. Inspect each returned reference
32
- with `get-sql-dashboard` or `get-explorer-dashboard` by its `kind`; a match
33
- is context, not authoritative source data. Then adapt the closest saved SQL
34
- to the requested filters/window, run it once, and stop. Prefer a current
35
- `certified` dashboard result; a dashboard starred by you is a weaker
29
+ 1. **Use the closest query example.** For a metric question, adapt a relevant
30
+ preloaded reference; if none fits, call `search-analytics-query-catalog`.
31
+ For dashboard replication or adaptation, call `search-dashboard-references`
32
+ first and inspect each result with `get-sql-dashboard` or
33
+ `get-explorer-dashboard` by its `kind`. A match is context, not live data.
34
+ Adapt the closest saved SQL to the requested filters/window, run it once,
35
+ and stop. Prefer a current `certified` dashboard; a favorite is a weaker
36
36
  relevance signal. Certification becomes stale after a dashboard edit.
37
37
  2. **One bounded call.** List/filter/count/cohort questions are one SQL statement
38
38
  or one server-side `run-code` script; never page or fan out per item.
@@ -66,9 +66,8 @@ certified ones); label figures "Unverified" when no live query ran.
66
66
  absence-sensitive Gong work, stage raw API data and use `query-staged-dataset`
67
67
  or a Data Program; see `provider-api`, `data-programs`, and `gong` for secure
68
68
  provider and hosted-endpoint boundaries.
69
- - Create dashboards, panels, or saved artifacts only when explicitly asked;
70
- suggest and wait otherwise. Scope them to the question, avoid decorative
71
- metrics, and never modify existing dashboards without a directive.
69
+ - Create dashboards or saved artifacts only when asked; keep them focused and
70
+ never modify existing dashboards without direction.
72
71
  - For named account/deal deep dives, call `account-deep-dive` first.
73
72
  - For named account health, read `account-health` before querying.
74
73
  - When the user challenges coverage or asks why records are missing, rerun from
@@ -85,16 +84,6 @@ certified ones); label figures "Unverified" when no live query ran.
85
84
  multi-step work, unavailable actions, or unsupported writes.
86
85
  - Reports/alerts use SQL actions; cap at five recipients.
87
86
 
88
- ## Actions
89
-
90
- | Action | Use |
91
- | --- | --- |
92
- | `search-analytics-query-catalog` | Search saved metric examples first. |
93
- | `search-dashboard-references` | Find dashboards to replicate. |
94
- | `get-sql-dashboard` | Read the dashboard and exact panel SQL. |
95
- | `certify-dashboard` | Admin-only approval of its current version. |
96
- | DB | `list-db-admin-connections`, `list-connected-database-tables`, `db-admin-federated-read`: registry, schema, bounded joins. |
97
-
98
87
  ## Application State
99
88
 
100
89
  - `navigation` exposes the current dashboard, analysis, source, chart, and
@@ -3,7 +3,10 @@ import {
3
3
  getRequestUserEmail,
4
4
  getRequestOrgId,
5
5
  } from "@agent-native/core/server";
6
- import { getAllSettings, listOrgSettings } from "@agent-native/core/settings";
6
+ import {
7
+ listOrgSettings,
8
+ listSettingsByPrefix,
9
+ } from "@agent-native/core/settings";
7
10
  import { z } from "zod";
8
11
 
9
12
  const KEY_PREFIX = "data-dict-";
@@ -46,15 +49,10 @@ export default defineAction({
46
49
  for (const value of Object.values(orgEntries)) collect(value);
47
50
  }
48
51
 
49
- // User-scoped entries — iterate once, filter by exact user prefix.
50
- // See list-analyses.ts for the rationale (substring matches leak across
51
- // users).
52
+ // Scope the read in SQL so other users' settings never enter this action.
52
53
  const userPrefix = `u:${email}:${KEY_PREFIX}`;
53
- const all = await getAllSettings();
54
- for (const [fullKey, value] of Object.entries(all)) {
55
- if (!fullKey.startsWith(userPrefix)) continue;
56
- collect(value);
57
- }
54
+ const userEntries = await listSettingsByPrefix(userPrefix);
55
+ for (const { value } of userEntries) collect(value);
58
56
 
59
57
  const q = (args.search ?? "").trim().toLowerCase();
60
58
  const dept = (args.department ?? "").trim().toLowerCase();
@@ -10,7 +10,7 @@ import { searchAnalyticsQueryCatalog } from "../server/lib/analytics-query-catal
10
10
  export default defineAction({
11
11
  description:
12
12
  "Prefer a current certified dashboard panel before other matches; a dashboard starred by the requesting user is a weaker relevance signal. " +
13
- "Search Analytics' existing query knowledge before writing a new query. This is the analytics equivalent of grepping for similar code: one bounded call searches accessible saved dashboard names, chart titles/descriptions/queries, shipped dashboard patterns, and data-dictionary definitions. Use it first for an ordinary metric lookup unless the user supplied an exact source and query. Prefer the highest-trust close match, adapt its saved query only for the requested filters/time window, run one authoritative source query, and stop on success. Do not separately list every dashboard or scan provider catalogs after a strong match.",
13
+ "Search Analytics' existing query knowledge before writing a new query. This is the analytics equivalent of grepping for similar code: one bounded call searches accessible saved dashboard names, chart titles/descriptions/queries, shipped dashboard patterns, and data-dictionary definitions. The result reports `searchedDashboardCount`, `dashboardSearchTruncated`, `dashboardSearchStatus`, `searchedDictionaryEntryCount`, `dictionarySearchTruncated`, and `dictionarySearchStatus`. If dashboard search is truncated or unavailable and no close saved-dashboard match appears, use `search-dashboard-references` with focused terms; if dictionary search is truncated, partial, or unavailable and no close definition appears, use `list-data-dictionary` with focused terms before concluding there is no saved example. Use it first for an ordinary metric lookup unless the user supplied an exact source and query. Prefer the highest-trust close match, adapt its saved query only for the requested filters/time window, run one authoritative source query, and stop on success. Do not separately list every dashboard or scan provider catalogs after a strong match.",
14
14
  schema: z.object({
15
15
  search: z
16
16
  .string()
@@ -0,0 +1,201 @@
1
+ import { useActionQuery } from "@agent-native/core/client/hooks";
2
+ import { useT } from "@agent-native/core/client/i18n";
3
+
4
+ import { SqlChart } from "@/components/dashboard/SqlChart";
5
+ import { resolveFilterVars } from "@/pages/adhoc/sql-dashboard/DashboardFilterBar";
6
+ import { interpolate } from "@/pages/adhoc/sql-dashboard/interpolate";
7
+ import { serializePanelSql } from "@/pages/adhoc/sql-dashboard/panel-sql";
8
+ import { timeRangeDays } from "@/pages/adhoc/sql-dashboard/pivot";
9
+ import type {
10
+ DashboardFilter,
11
+ DataSourceType,
12
+ ChartType,
13
+ SqlPanel,
14
+ } from "@/pages/adhoc/sql-dashboard/types";
15
+
16
+ const DATA_SOURCES: DataSourceType[] = [
17
+ "bigquery",
18
+ "ga4",
19
+ "amplitude",
20
+ "first-party",
21
+ "demo",
22
+ "prometheus",
23
+ "program",
24
+ ];
25
+ const CHART_TYPES: ChartType[] = [
26
+ "line",
27
+ "area",
28
+ "bar",
29
+ "metric",
30
+ "table",
31
+ "pie",
32
+ "section",
33
+ "funnel",
34
+ "heatmap",
35
+ "callout",
36
+ "extension",
37
+ ];
38
+ const FILTER_TYPES: DashboardFilter["type"][] = [
39
+ "date",
40
+ "date-range",
41
+ "select",
42
+ "toggle",
43
+ "text",
44
+ "toggle-date",
45
+ ];
46
+
47
+ function isRecord(value: unknown): value is Record<string, unknown> {
48
+ return typeof value === "object" && value !== null && !Array.isArray(value);
49
+ }
50
+
51
+ function isSqlPanel(value: unknown): value is SqlPanel {
52
+ if (!isRecord(value)) return false;
53
+ return (
54
+ typeof value.id === "string" &&
55
+ typeof value.title === "string" &&
56
+ typeof value.sql === "string" &&
57
+ typeof value.width === "number" &&
58
+ DATA_SOURCES.includes(value.source as DataSourceType) &&
59
+ CHART_TYPES.includes(value.chartType as ChartType) &&
60
+ (value.config === undefined || isRecord(value.config))
61
+ );
62
+ }
63
+
64
+ function isDashboardFilter(value: unknown): value is DashboardFilter {
65
+ if (
66
+ !isRecord(value) ||
67
+ typeof value.id !== "string" ||
68
+ !value.id ||
69
+ typeof value.label !== "string" ||
70
+ !FILTER_TYPES.includes(value.type as DashboardFilter["type"]) ||
71
+ (value.default !== undefined && typeof value.default !== "string")
72
+ ) {
73
+ return false;
74
+ }
75
+ return (
76
+ value.options === undefined ||
77
+ (Array.isArray(value.options) &&
78
+ value.options.length <= 100 &&
79
+ value.options.every(
80
+ (option) =>
81
+ isRecord(option) &&
82
+ typeof option.value === "string" &&
83
+ typeof option.label === "string",
84
+ ))
85
+ );
86
+ }
87
+
88
+ export function reviewDashboardFilters(
89
+ value: unknown,
90
+ ): DashboardFilter[] | undefined {
91
+ if (!isRecord(value) || value.filters === undefined) return [];
92
+ return Array.isArray(value.filters) &&
93
+ value.filters.length <= 100 &&
94
+ value.filters.every(isDashboardFilter)
95
+ ? value.filters
96
+ : undefined;
97
+ }
98
+
99
+ export function reviewDashboardVariables(
100
+ value: unknown,
101
+ ): Record<string, string> | undefined {
102
+ if (!isRecord(value) || value.variables === undefined) return {};
103
+ if (!isRecord(value.variables)) return undefined;
104
+ const entries = Object.entries(value.variables);
105
+ if (
106
+ entries.length > 100 ||
107
+ entries.some(([, variable]) => typeof variable !== "string")
108
+ ) {
109
+ return undefined;
110
+ }
111
+ return Object.fromEntries(entries) as Record<string, string>;
112
+ }
113
+
114
+ export function firstReviewDashboardPanel(
115
+ value: unknown,
116
+ ): SqlPanel | undefined {
117
+ if (!isRecord(value) || !Array.isArray(value.panels)) return undefined;
118
+ const panels = value.panels.filter(isSqlPanel);
119
+ const byId = new Map(panels.map((panel) => [panel.id, panel]));
120
+ const preferredIds =
121
+ isRecord(value.layout) && Array.isArray(value.layout.firstPanelIds)
122
+ ? value.layout.firstPanelIds.filter(
123
+ (id): id is string => typeof id === "string",
124
+ )
125
+ : [];
126
+ const preferred = preferredIds.flatMap((id) => {
127
+ const panel = byId.get(id);
128
+ return panel ? [panel] : [];
129
+ });
130
+ const ordered = [
131
+ ...preferred,
132
+ ...panels.filter((panel) => !preferredIds.includes(panel.id)),
133
+ ];
134
+ return ordered.find(
135
+ (panel) => panel.chartType !== "section" && panel.chartType !== "extension",
136
+ );
137
+ }
138
+
139
+ export function AnalyticsReviewArtifactPreview({
140
+ artifactId,
141
+ compact,
142
+ }: {
143
+ artifactId: string;
144
+ compact: boolean;
145
+ }) {
146
+ const t = useT();
147
+ const { data, isLoading, isError } = useActionQuery<Record<string, unknown>>(
148
+ "get-sql-dashboard",
149
+ { id: artifactId, includeConfig: true },
150
+ { staleTime: 5 * 60_000 },
151
+ );
152
+ const panel = firstReviewDashboardPanel(data);
153
+ const filters = reviewDashboardFilters(data);
154
+ const variables = reviewDashboardVariables(data);
155
+ if (isLoading) {
156
+ return (
157
+ <div
158
+ aria-hidden="true"
159
+ className={
160
+ compact
161
+ ? "size-full animate-pulse bg-muted"
162
+ : "h-full min-h-64 w-full animate-pulse bg-muted"
163
+ }
164
+ />
165
+ );
166
+ }
167
+ if (isError || !panel || !filters || !variables) {
168
+ return (
169
+ <div
170
+ className="flex size-full items-center justify-center bg-muted px-2 text-center text-xs text-muted-foreground"
171
+ data-preview-state="unavailable"
172
+ role="status"
173
+ >
174
+ {t("settings.reviewPreviewUnavailable")}
175
+ </div>
176
+ );
177
+ }
178
+
179
+ const vars = { ...variables, ...resolveFilterVars(filters, () => "") };
180
+ const resolvedSql = interpolate(serializePanelSql(panel.sql), vars, {
181
+ failClosedTimeVariables: true,
182
+ });
183
+
184
+ return (
185
+ <div
186
+ className={
187
+ compact
188
+ ? "pointer-events-none h-[600%] w-[600%] origin-top-left scale-[0.166667] overflow-hidden"
189
+ : "h-full min-h-64 w-full overflow-hidden"
190
+ }
191
+ data-preview-kind="analytics-sql-chart"
192
+ >
193
+ <SqlChart
194
+ panel={panel}
195
+ resolvedSql={resolvedSql}
196
+ timeRange={timeRangeDays(vars.timeRange)}
197
+ dashboardId={artifactId}
198
+ />
199
+ </div>
200
+ );
201
+ }
@@ -337,6 +337,8 @@ export default {
337
337
  untitledDashboard: "Untitled dashboard",
338
338
  },
339
339
  settings: {
340
+ agentObservability: "Agent Observability",
341
+ reviewPreviewUnavailable: "Preview unavailable",
340
342
  agentTitle: "Manage agent",
341
343
  agentDescription:
342
344
  "Manage the agent's model, API keys, automations, voice, and other controls.",
@@ -4,7 +4,9 @@ import {
4
4
  useActionQuery,
5
5
  } from "@agent-native/core/client/hooks";
6
6
  import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
7
- import { TeamPage } from "@agent-native/core/client/org";
7
+ import { buildSettingsRoute } from "@agent-native/core/client/navigation";
8
+ import { ObservabilityDashboard } from "@agent-native/core/client/observability";
9
+ import { TeamPage, useOrg } from "@agent-native/core/client/org";
8
10
  import {
9
11
  AccountSettingsCard,
10
12
  SettingsGroup,
@@ -18,7 +20,7 @@ import {
18
20
  createCreativeContextAgentTab,
19
21
  useCreativeContextLab,
20
22
  } from "@agent-native/creative-context/client";
21
- import { IconBell } from "@tabler/icons-react";
23
+ import { IconActivity, IconBell } from "@tabler/icons-react";
22
24
  import { useEffect, useMemo, useState } from "react";
23
25
  import { Link } from "react-router";
24
26
  import { toast } from "sonner";
@@ -31,6 +33,7 @@ import {
31
33
  ANALYTICS_USER_PREFS_KEY,
32
34
  type AnalyticsUserPrefs,
33
35
  } from "../../shared/analytics-user-prefs";
36
+ import { AnalyticsReviewArtifactPreview } from "../components/AnalyticsReviewArtifactPreview";
34
37
  import { useReplayStorageStatus } from "../hooks/use-replay-storage-status";
35
38
  import { ReplayStorageHint } from "./sessions/SessionsPage";
36
39
  import { AlertRulesSettingsCard } from "./settings/AlertRulesSettingsCard";
@@ -40,6 +43,11 @@ export default function Settings() {
40
43
  const t = useT();
41
44
  const creativeContextEnabled = useCreativeContextLab();
42
45
  const replayStorageStatus = useReplayStorageStatus();
46
+ const {
47
+ data: activeOrg,
48
+ isLoading: orgLoading,
49
+ isError: orgError,
50
+ } = useOrg();
43
51
  const { data: analyticsPrefs, isLoading: analyticsPrefsLoading } =
44
52
  useActionQuery<AnalyticsUserPrefs>("get-user-pref", {
45
53
  key: ANALYTICS_USER_PREFS_KEY,
@@ -142,6 +150,44 @@ export default function Settings() {
142
150
  agentAdditionalContent,
143
151
  agentAdditionalTabFactories,
144
152
  });
153
+ const observabilityBasePath = buildSettingsRoute("observability");
154
+ const observabilityTabs = useMemo<SettingsTabItem[]>(
155
+ () =>
156
+ !orgLoading &&
157
+ !orgError &&
158
+ activeOrg?.orgId &&
159
+ (activeOrg.role === "owner" || activeOrg.role === "admin")
160
+ ? [
161
+ {
162
+ id: "observability",
163
+ label: t("settings.agentObservability"),
164
+ icon: IconActivity,
165
+ group: "agent",
166
+ href: `${observabilityBasePath}/overview`,
167
+ content: (
168
+ <ObservabilityDashboard
169
+ routeBasePath={observabilityBasePath}
170
+ showHumanReview
171
+ renderArtifactPreview={(artifact, compact) => (
172
+ <AnalyticsReviewArtifactPreview
173
+ artifactId={artifact.artifactId}
174
+ compact={compact}
175
+ />
176
+ )}
177
+ />
178
+ ),
179
+ },
180
+ ]
181
+ : [],
182
+ [
183
+ activeOrg?.orgId,
184
+ activeOrg?.role,
185
+ observabilityBasePath,
186
+ orgError,
187
+ orgLoading,
188
+ t,
189
+ ],
190
+ );
145
191
  const labs = useMemo(
146
192
  () => [
147
193
  {
@@ -167,8 +213,9 @@ export default function Settings() {
167
213
  ),
168
214
  },
169
215
  ...agentSettingsTabs,
216
+ ...observabilityTabs,
170
217
  ],
171
- [agentSettingsTabs, t],
218
+ [agentSettingsTabs, observabilityTabs, t],
172
219
  );
173
220
 
174
221
  const generalSearchEntries = useMemo(
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-09-25
4
+ ---
5
+
6
+ First-run onboarding records setup choices and Builder connection outcomes
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-09-25
4
+ ---
5
+
6
+ Human review previews Analytics dashboards as real charts
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-09-25
4
+ ---
5
+
6
+ Org admins can review agent runs from Settings
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-09-25
4
+ ---
5
+
6
+ Relevant metric definitions and saved dashboard examples are available with the first response so Analytics queries can reuse proven definitions and query shapes.