@agent-native/core 0.119.2 → 0.119.4

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 (228) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +19 -0
  3. package/corpus/core/package.json +3 -3
  4. package/corpus/core/src/agent/production-agent.ts +107 -125
  5. package/corpus/core/src/agent/run-manager.ts +45 -2
  6. package/corpus/core/src/agent/thread-data-builder.ts +85 -8
  7. package/corpus/core/src/cli/create.ts +44 -5
  8. package/corpus/core/src/client/AssistantChat.tsx +37 -9
  9. package/corpus/core/src/client/chat/message-components.tsx +9 -1
  10. package/corpus/core/src/client/chat/repo-helpers.ts +77 -0
  11. package/corpus/core/src/client/chat/tool-call-display.tsx +51 -15
  12. package/corpus/core/src/server/agent-chat/framework-prompts.ts +3 -1
  13. package/corpus/core/src/server/agent-chat/plugin-options.ts +9 -0
  14. package/corpus/core/src/server/agent-chat-plugin.ts +12 -3
  15. package/corpus/core/src/templates/chat/.agents/skills/actions/SKILL.md +512 -0
  16. package/corpus/core/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +189 -0
  17. package/corpus/core/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +115 -0
  18. package/corpus/core/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +177 -0
  19. package/corpus/core/src/templates/chat/.agents/skills/capture-learnings/SKILL.md +89 -0
  20. package/corpus/core/src/templates/chat/.agents/skills/create-skill/SKILL.md +221 -0
  21. package/corpus/core/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +220 -0
  22. package/corpus/core/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +263 -0
  23. package/corpus/core/src/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
  24. package/corpus/core/src/templates/chat/.agents/skills/frontend-design/SKILL.md +160 -0
  25. package/corpus/core/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +232 -0
  26. package/corpus/core/src/templates/chat/.agents/skills/security/SKILL.md +280 -0
  27. package/corpus/core/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +118 -0
  28. package/corpus/core/src/templates/chat/.agents/skills/shadcn-ui/SKILL.md +119 -0
  29. package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +100 -0
  30. package/corpus/core/src/templates/chat/.env.example +5 -0
  31. package/corpus/core/src/templates/chat/.ignore +0 -0
  32. package/corpus/core/src/templates/chat/.oxfmtrc.json +8 -0
  33. package/corpus/core/src/templates/chat/AGENTS.md +69 -0
  34. package/corpus/core/src/templates/chat/CHANGELOG.md +10 -0
  35. package/corpus/core/src/templates/chat/DEVELOPING.md +185 -0
  36. package/corpus/core/src/templates/chat/README.md +32 -0
  37. package/corpus/core/src/templates/chat/_gitignore +43 -0
  38. package/corpus/core/src/templates/chat/actions/hello.ts +13 -0
  39. package/corpus/core/src/templates/chat/actions/navigate.ts +41 -0
  40. package/corpus/core/src/templates/chat/actions/run.ts +2 -0
  41. package/corpus/core/src/templates/chat/actions/view-screen.ts +31 -0
  42. package/corpus/core/src/templates/chat/app/components/layout/Header.tsx +60 -0
  43. package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +185 -0
  44. package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +450 -0
  45. package/corpus/core/src/templates/chat/app/components/ui/button.tsx +1 -0
  46. package/corpus/core/src/templates/chat/app/components/ui/card.tsx +1 -0
  47. package/corpus/core/src/templates/chat/app/components/ui/dropdown-menu.tsx +1 -0
  48. package/corpus/core/src/templates/chat/app/components/ui/input.tsx +1 -0
  49. package/corpus/core/src/templates/chat/app/components/ui/label.tsx +1 -0
  50. package/corpus/core/src/templates/chat/app/components/ui/sheet.tsx +1 -0
  51. package/corpus/core/src/templates/chat/app/components/ui/toolkit-provider.tsx +17 -0
  52. package/corpus/core/src/templates/chat/app/components/ui/tooltip.tsx +1 -0
  53. package/corpus/core/src/templates/chat/app/design-system.ts +3 -0
  54. package/corpus/core/src/templates/chat/app/entry.client.tsx +19 -0
  55. package/corpus/core/src/templates/chat/app/entry.server.tsx +10 -0
  56. package/corpus/core/src/templates/chat/app/global.css +93 -0
  57. package/corpus/core/src/templates/chat/app/hooks/use-navigation-state.ts +93 -0
  58. package/corpus/core/src/templates/chat/app/i18n/ar-SA.ts +68 -0
  59. package/corpus/core/src/templates/chat/app/i18n/de-DE.ts +71 -0
  60. package/corpus/core/src/templates/chat/app/i18n/en-US.ts +70 -0
  61. package/corpus/core/src/templates/chat/app/i18n/es-ES.ts +71 -0
  62. package/corpus/core/src/templates/chat/app/i18n/fr-FR.ts +71 -0
  63. package/corpus/core/src/templates/chat/app/i18n/hi-IN.ts +69 -0
  64. package/corpus/core/src/templates/chat/app/i18n/index.ts +34 -0
  65. package/corpus/core/src/templates/chat/app/i18n/ja-JP.ts +70 -0
  66. package/corpus/core/src/templates/chat/app/i18n/ko-KR.ts +70 -0
  67. package/corpus/core/src/templates/chat/app/i18n/pt-BR.ts +71 -0
  68. package/corpus/core/src/templates/chat/app/i18n/zh-CN.ts +66 -0
  69. package/corpus/core/src/templates/chat/app/i18n/zh-TW.ts +66 -0
  70. package/corpus/core/src/templates/chat/app/i18n-data.ts +556 -0
  71. package/corpus/core/src/templates/chat/app/lib/agent-page.tsx +49 -0
  72. package/corpus/core/src/templates/chat/app/lib/app-config.ts +11 -0
  73. package/corpus/core/src/templates/chat/app/lib/tab-id.ts +1 -0
  74. package/corpus/core/src/templates/chat/app/lib/utils.ts +1 -0
  75. package/corpus/core/src/templates/chat/app/root.tsx +173 -0
  76. package/corpus/core/src/templates/chat/app/routes/_index.tsx +94 -0
  77. package/corpus/core/src/templates/chat/app/routes/agent.tsx +24 -0
  78. package/corpus/core/src/templates/chat/app/routes/chat.$threadId.tsx +1 -0
  79. package/corpus/core/src/templates/chat/app/routes/database.tsx +17 -0
  80. package/corpus/core/src/templates/chat/app/routes/extensions.$id.$slug.tsx +2 -0
  81. package/corpus/core/src/templates/chat/app/routes/extensions.$id.tsx +11 -0
  82. package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +11 -0
  83. package/corpus/core/src/templates/chat/app/routes/extensions.tsx +5 -0
  84. package/corpus/core/src/templates/chat/app/routes/observability.tsx +19 -0
  85. package/corpus/core/src/templates/chat/app/routes/settings.tsx +89 -0
  86. package/corpus/core/src/templates/chat/app/routes/team.tsx +11 -0
  87. package/corpus/core/src/templates/chat/app/routes.ts +4 -0
  88. package/corpus/core/src/templates/chat/app/vite-env.d.ts +6 -0
  89. package/corpus/core/src/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  90. package/corpus/core/src/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  91. package/corpus/core/src/templates/chat/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
  92. package/corpus/core/src/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  93. package/corpus/core/src/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  94. package/corpus/core/src/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  95. package/corpus/core/src/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
  96. package/corpus/core/src/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  97. package/corpus/core/src/templates/chat/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +6 -0
  98. package/corpus/core/src/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
  99. package/corpus/core/src/templates/chat/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +6 -0
  100. package/corpus/core/src/templates/chat/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +6 -0
  101. package/corpus/core/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  102. package/corpus/core/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  103. package/corpus/core/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  104. package/corpus/core/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  105. package/corpus/core/src/templates/chat/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +6 -0
  106. package/corpus/core/src/templates/chat/components.json +20 -0
  107. package/corpus/core/src/templates/chat/learnings.defaults.md +5 -0
  108. package/corpus/core/src/templates/chat/netlify.toml +10 -0
  109. package/corpus/core/src/templates/chat/package.json +92 -0
  110. package/corpus/core/src/templates/chat/public/agent-native-icon-dark.svg +10 -0
  111. package/corpus/core/src/templates/chat/public/agent-native-icon-light.svg +10 -0
  112. package/corpus/core/src/templates/chat/public/agent-native-logo-dark.svg +21 -0
  113. package/corpus/core/src/templates/chat/public/agent-native-logo-light.svg +21 -0
  114. package/corpus/core/src/templates/chat/public/favicon.svg +1 -0
  115. package/corpus/core/src/templates/chat/public/icon-180.svg +1 -0
  116. package/corpus/core/src/templates/chat/public/icon-192.svg +1 -0
  117. package/corpus/core/src/templates/chat/public/icon-512.svg +1 -0
  118. package/corpus/core/src/templates/chat/public/manifest.json +21 -0
  119. package/corpus/core/src/templates/chat/react-router.config.ts +7 -0
  120. package/corpus/core/src/templates/chat/server/middleware/auth.ts +15 -0
  121. package/corpus/core/src/templates/chat/server/plugins/agent-chat.ts +21 -0
  122. package/corpus/core/src/templates/chat/server/plugins/auth.ts +17 -0
  123. package/corpus/core/src/templates/chat/server/routes/[...page].get.ts +5 -0
  124. package/corpus/core/src/templates/chat/ssr-entry.ts +15 -0
  125. package/corpus/core/src/templates/chat/tsconfig.json +21 -0
  126. package/corpus/core/src/templates/chat/vite.config.ts +19 -0
  127. package/corpus/templates/analytics/AGENTS.md +19 -11
  128. package/corpus/templates/analytics/actions/list-data-dictionary.ts +3 -1
  129. package/corpus/templates/analytics/actions/save-data-dictionary-entry.ts +14 -0
  130. package/corpus/templates/analytics/actions/search-analytics-query-catalog.ts +41 -0
  131. package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +13 -0
  132. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +12 -11
  133. package/corpus/templates/analytics/app/pages/adhoc/DashboardSkeleton.tsx +3 -3
  134. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +7 -1
  135. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +8 -1
  136. package/corpus/templates/analytics/changelog/2026-07-22-fixed-dashboards-and-analyses-missing-a-copyable-share-link.md +6 -0
  137. package/corpus/templates/analytics/changelog/2026-07-23-dashboard-chart-loading-placeholders-are-easier-to-see-in-da.md +6 -0
  138. package/corpus/templates/analytics/changelog/2026-07-23-routine-analytics-lookups-reuse-existing-query-definitions.md +6 -0
  139. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +1 -12
  140. package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +405 -0
  141. package/corpus/templates/analytics/server/plugins/agent-chat.ts +11 -16
  142. package/corpus/templates/content/changelog/2026-07-23-database-toolbar-sort-and-filter-controls-open-reliably.md +6 -0
  143. package/corpus/templates/forms/app/lib/public-form-link.ts +14 -0
  144. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +6 -14
  145. package/corpus/templates/forms/changelog/2026-07-23-published-form-links-can-be-copied-without-being-asked-to-re.md +6 -0
  146. package/corpus/templates/mail/changelog/2026-07-23-scheduled-emails-now-send-only-once-when-multiple-requests-r.md +6 -0
  147. package/corpus/templates/mail/server/lib/jobs.ts +13 -4
  148. package/corpus/templates/mail/server/plugins/mail-jobs.ts +1 -1
  149. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +7 -18
  150. package/corpus/templates/slides/app/lib/agent-visible-message.ts +28 -0
  151. package/corpus/templates/slides/app/pages/Index.tsx +6 -34
  152. package/corpus/templates/slides/changelog/2026-07-23-full-prompts-stay-visible-in-chat-when-creating-decks-or-add.md +6 -0
  153. package/corpus/toolkit/CHANGELOG.md +13 -0
  154. package/corpus/toolkit/package.json +1 -1
  155. package/corpus/toolkit/src/editor/SharedRichEditor.tsx +23 -2
  156. package/corpus/toolkit/src/editor/SlashCommandMenu.tsx +68 -2
  157. package/corpus/toolkit/src/editor/index.ts +1 -0
  158. package/corpus/toolkit/src/editor.css +75 -0
  159. package/corpus/toolkit/src/ui/button.tsx +3 -2
  160. package/dist/agent/production-agent.d.ts.map +1 -1
  161. package/dist/agent/production-agent.js +96 -115
  162. package/dist/agent/production-agent.js.map +1 -1
  163. package/dist/agent/run-manager.d.ts +9 -1
  164. package/dist/agent/run-manager.d.ts.map +1 -1
  165. package/dist/agent/run-manager.js +26 -0
  166. package/dist/agent/run-manager.js.map +1 -1
  167. package/dist/agent/thread-data-builder.d.ts +2 -0
  168. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  169. package/dist/agent/thread-data-builder.js +69 -9
  170. package/dist/agent/thread-data-builder.js.map +1 -1
  171. package/dist/cli/create.d.ts +2 -1
  172. package/dist/cli/create.d.ts.map +1 -1
  173. package/dist/cli/create.js +43 -6
  174. package/dist/cli/create.js.map +1 -1
  175. package/dist/client/AssistantChat.d.ts.map +1 -1
  176. package/dist/client/AssistantChat.js +32 -10
  177. package/dist/client/AssistantChat.js.map +1 -1
  178. package/dist/client/chat/message-components.d.ts +2 -1
  179. package/dist/client/chat/message-components.d.ts.map +1 -1
  180. package/dist/client/chat/message-components.js +9 -3
  181. package/dist/client/chat/message-components.js.map +1 -1
  182. package/dist/client/chat/repo-helpers.d.ts +4 -0
  183. package/dist/client/chat/repo-helpers.d.ts.map +1 -1
  184. package/dist/client/chat/repo-helpers.js +61 -0
  185. package/dist/client/chat/repo-helpers.js.map +1 -1
  186. package/dist/client/chat/tool-call-display.d.ts +2 -1
  187. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  188. package/dist/client/chat/tool-call-display.js +10 -9
  189. package/dist/client/chat/tool-call-display.js.map +1 -1
  190. package/dist/collab/awareness.d.ts +2 -2
  191. package/dist/collab/awareness.d.ts.map +1 -1
  192. package/dist/collab/routes.d.ts +1 -1
  193. package/dist/collab/struct-routes.d.ts +1 -1
  194. package/dist/notifications/routes.d.ts +2 -2
  195. package/dist/observability/routes.d.ts +3 -3
  196. package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
  197. package/dist/provider-api/actions/provider-api.d.ts +7 -7
  198. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  199. package/dist/resources/handlers.d.ts +1 -1
  200. package/dist/secrets/routes.d.ts +9 -9
  201. package/dist/server/agent-chat/framework-prompts.d.ts.map +1 -1
  202. package/dist/server/agent-chat/framework-prompts.js +3 -1
  203. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  204. package/dist/server/agent-chat/plugin-options.d.ts +9 -0
  205. package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
  206. package/dist/server/agent-chat/plugin-options.js.map +1 -1
  207. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  208. package/dist/server/agent-chat-plugin.js +11 -2
  209. package/dist/server/agent-chat-plugin.js.map +1 -1
  210. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  211. package/dist/server/realtime-token.d.ts +1 -1
  212. package/dist/server/transcribe-voice.d.ts +1 -1
  213. package/package.json +4 -4
  214. package/src/agent/production-agent.ts +107 -125
  215. package/src/agent/run-manager.ts +45 -2
  216. package/src/agent/thread-data-builder.ts +85 -8
  217. package/src/cli/create.ts +44 -5
  218. package/src/client/AssistantChat.tsx +37 -9
  219. package/src/client/chat/message-components.tsx +9 -1
  220. package/src/client/chat/repo-helpers.ts +77 -0
  221. package/src/client/chat/tool-call-display.tsx +51 -15
  222. package/src/server/agent-chat/framework-prompts.ts +3 -1
  223. package/src/server/agent-chat/plugin-options.ts +9 -0
  224. package/src/server/agent-chat-plugin.ts +12 -3
  225. package/src/templates/chat/actions/hello.spec.ts +0 -23
  226. package/src/templates/chat/actions/navigate.spec.ts +0 -68
  227. package/src/templates/chat/actions/view-screen.spec.ts +0 -40
  228. package/src/templates/chat/app/lib/agent-page.spec.tsx +0 -61
@@ -0,0 +1,7 @@
1
+ import type { Config } from "@react-router/dev/config";
2
+
3
+ export default {
4
+ appDirectory: "app",
5
+ ssr: true,
6
+ routeDiscovery: { mode: "initial" },
7
+ } satisfies Config;
@@ -0,0 +1,15 @@
1
+ import { runAuthGuard } from "@agent-native/core/server";
2
+ /**
3
+ * Global auth middleware — runs for ALL requests (page routes, API routes,
4
+ * framework routes). The auth plugin configures the guard; this middleware
5
+ * enforces it on every request.
6
+ *
7
+ * Without this, auth only runs for /_agent-native/* routes because the
8
+ * framework handler's middleware registry is scoped to that catch-all.
9
+ * Page routes (/, /settings) and API routes (/api/*) would bypass auth.
10
+ */
11
+ import { defineEventHandler } from "h3";
12
+
13
+ export default defineEventHandler(async (event) => {
14
+ return runAuthGuard(event);
15
+ });
@@ -0,0 +1,21 @@
1
+ import { getOrgContext } from "@agent-native/core/org";
2
+ import {
3
+ createAgentChatPlugin,
4
+ loadActionsFromStaticRegistry,
5
+ } from "@agent-native/core/server";
6
+
7
+ import actionsRegistry from "../../.generated/actions-registry.js";
8
+
9
+ const INITIAL_TOOL_NAMES = ["view-screen", "navigate", "hello"];
10
+
11
+ export default createAgentChatPlugin({
12
+ appId: "chat",
13
+ actions: loadActionsFromStaticRegistry(actionsRegistry),
14
+ initialToolNames: INITIAL_TOOL_NAMES,
15
+ resolveOrgId: async (event) => (await getOrgContext(event)).orgId,
16
+ systemPrompt: `You are the Chat app agent.
17
+
18
+ This is a minimal chat-first Agent-Native app. The chat is the product surface, and actions are the contract shared by chat, UI, HTTP, MCP, A2A, and CLI.
19
+
20
+ Use actions as the source of truth. Start by inspecting the current screen when context matters. When the user asks to extend this app, keep the change small and agent-native: add or update actions, expose useful UI, and keep application state/navigation visible to the agent.`,
21
+ });
@@ -0,0 +1,17 @@
1
+ import { createAuthPlugin } from "@agent-native/core/server";
2
+
3
+ const rawAppTitle = "{{APP_TITLE}}";
4
+ const appTitle = rawAppTitle === "{" + "{APP_TITLE}}" ? "Chat" : rawAppTitle;
5
+
6
+ export default createAuthPlugin({
7
+ marketing: {
8
+ appName: appTitle,
9
+ tagline:
10
+ "Start from a chat-first agent-native app and add actions, screens, and workflows as you grow.",
11
+ features: [
12
+ "Full-page chat with durable threads and tool call history",
13
+ "Add actions once and use them from chat, UI, HTTP, MCP, A2A, and CLI",
14
+ "Plug in your own agent runtime or build on the included app-agent loop",
15
+ ],
16
+ },
17
+ });
@@ -0,0 +1,5 @@
1
+ import { createH3SSRHandler } from "@agent-native/core/server/ssr-handler";
2
+
3
+ export default createH3SSRHandler(
4
+ () => import("virtual:react-router/server-build"),
5
+ );
@@ -0,0 +1,15 @@
1
+ /**
2
+ * SSR entry point for Nitro.
3
+ * Wraps React Router's request handler so Nitro can use it as a service.
4
+ */
5
+ import { createRequestHandler } from "react-router";
6
+
7
+ const handler = createRequestHandler(
8
+ () => import("virtual:react-router/server-build"),
9
+ );
10
+
11
+ export default {
12
+ async fetch(request: Request) {
13
+ return handler(request);
14
+ },
15
+ };
@@ -0,0 +1,21 @@
1
+ {
2
+ "extends": "@agent-native/core/tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "ignoreDeprecations": "6.0",
5
+ "rootDirs": [".", "./.react-router/types"],
6
+ "paths": {
7
+ "*": ["./*"],
8
+ "@/*": ["./app/*"],
9
+ "@shared/*": ["./shared/*"]
10
+ }
11
+ },
12
+ "include": [
13
+ "app/**/*",
14
+ "server/**/*",
15
+ "shared/**/*",
16
+ "vite.config.ts",
17
+ "react-router.config.ts",
18
+ ".react-router/types/**/*",
19
+ ".generated/**/*"
20
+ ]
21
+ }
@@ -0,0 +1,19 @@
1
+ import { agentNative } from "@agent-native/core/vite";
2
+ import { reactRouter } from "@react-router/dev/vite";
3
+ import { defineConfig } from "vite";
4
+
5
+ const reactRouterPlugins = reactRouter as unknown as () => any[];
6
+ const agentNativePlugins = agentNative as unknown as (
7
+ options?: Parameters<typeof agentNative>[0],
8
+ ) => any[];
9
+
10
+ export default defineConfig({
11
+ plugins: [
12
+ ...reactRouterPlugins(),
13
+ ...agentNativePlugins({
14
+ // shiki only runs in AssistantChat's useEffect — keep it out of the
15
+ // CF Pages Functions bundle (25 MiB limit).
16
+ ssrStubs: ["shiki"],
17
+ }),
18
+ ],
19
+ });
@@ -26,23 +26,31 @@ membership id when its native update status reports `update-available`.
26
26
  - Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
27
27
  - Data integrity comes first. Do not invent numbers, dimensions, filters, or
28
28
  source semantics. State uncertainty and inspect the source when needed.
29
- - Catalog-first: before querying, consult known data sources (data-source
30
- status) and call `list-data-dictionary` with a focused search to learn what
31
- exists and which table/columns/join paths to use. Don't fan out blind queries
32
- when the catalog already answers where a fact lives.
29
+ - Existing-work-first: treat analytics definitions like code. For a bounded
30
+ metric lookup, call `search-analytics-query-catalog` once with focused
31
+ metric/entity terms before writing a new query. It searches accessible
32
+ dashboard/chart SQL and data-dictionary definitions together. Prefer the
33
+ strongest approved definition or saved chart, preserve its source and
34
+ business logic, adapt only the requested filters/time window, then run one
35
+ bounded query and stop.
36
+ - Use `list-data-dictionary` separately only when the user asks to browse
37
+ definitions or filter them by department. Use `data-source-status`, schema
38
+ discovery, or provider catalogs only when the combined catalog search does
39
+ not establish a source/query shape.
33
40
  - `data-source-status` always includes the built-in first-party Analytics source
34
41
  and returns `hasConnectedExternalDataSources`,
35
42
  `dataSourcesSetupLink` (a real deep link to `/data-sources`). Chat stays
36
43
  available when no external provider is connected; for a request that needs
37
44
  one, explain the missing source in context and include that returned link so
38
45
  the user can connect it. Do not replace this with a generic canned response.
39
- - Simple time-bounded metric fast path: when the data dictionary or a known
40
- canonical source already identifies the metric, run one bounded aggregate.
41
- Once that query returns a valid result, answer immediately with the source,
42
- time window, row count, and only necessary caveats. Do not schema-discover,
43
- retry, enrich, or add breakdowns unless the query fails or its result
44
- conflicts with the known metric definition. This never waives the real-data
45
- requirement: do not answer from a guess, stale value, or unverified result.
46
+ - Bounded structured lookup fast path: after the one catalog search, run one
47
+ query against the matched authoritative source. That source may be first-party
48
+ Analytics, BigQuery, HubSpot, Gong, or another connected provider. Once it
49
+ succeeds, answer immediately. Do not schema-discover, cross-check, enrich,
50
+ retry, or add breakdowns unless the user requested them, the first query
51
+ failed, or its result conflicts with the known definition. `all`, `total`,
52
+ and `exact` in a structured aggregate do not by themselves require a corpus
53
+ workflow.
46
54
  - Clarify-first for ambiguous ad-hoc work: when the metric definition, date
47
55
  range, or grain is ambiguous and a wrong guess would change the numbers, use
48
56
  the `ask-question` clarifying tool (multiple-choice) before computing. Ask at
@@ -10,7 +10,7 @@ const KEY_PREFIX = "data-dict-";
10
10
 
11
11
  export default defineAction({
12
12
  description:
13
- "List entries in the data dictionary — the internal catalog of metrics, tables, columns, and business definitions the analytics agent should consult before writing SQL or proposing a dashboard. Call this FIRST when the user asks for a dashboard or metric so you know what's already defined, where the numbers come from, and how to query them correctly. Returns all entries sorted by metric name; filter with `search` or `department` when you only need a slice.",
13
+ "List or browse entries in the data dictionary — the internal catalog of metrics, tables, columns, and business definitions. For an ordinary metric lookup, use search-analytics-query-catalog instead because it searches dictionary entries and existing dashboard/chart SQL together in one bounded call. Use this action when the user specifically asks to browse dictionary definitions or filter them by department.",
14
14
  schema: z.object({
15
15
  search: z
16
16
  .string()
@@ -64,6 +64,8 @@ export default defineAction({
64
64
  e.metric,
65
65
  e.definition,
66
66
  e.department,
67
+ e.source,
68
+ e.action,
67
69
  e.table,
68
70
  e.columnsUsed,
69
71
  e.cuts,
@@ -42,6 +42,18 @@ export default defineAction({
42
42
  .string()
43
43
  .optional()
44
44
  .describe("Owning team (e.g. 'Sales', 'Marketing', 'Product', 'Data')"),
45
+ source: z
46
+ .string()
47
+ .optional()
48
+ .describe(
49
+ "Canonical source/provider id for this definition (for example first-party, bigquery, or hubspot)",
50
+ ),
51
+ action: z
52
+ .string()
53
+ .optional()
54
+ .describe(
55
+ "Preferred Analytics action name when this metric is not expressed as SQL",
56
+ ),
45
57
  table: z
46
58
  .string()
47
59
  .optional()
@@ -143,6 +155,8 @@ export default defineAction({
143
155
  metric: args.metric,
144
156
  definition: args.definition,
145
157
  department: args.department ?? (existing as any)?.department ?? "",
158
+ source: args.source ?? (existing as any)?.source ?? "",
159
+ action: args.action ?? (existing as any)?.action ?? "",
146
160
  table: args.table ?? (existing as any)?.table ?? "",
147
161
  columnsUsed: args.columnsUsed ?? (existing as any)?.columnsUsed ?? "",
148
162
  cuts: args.cuts ?? (existing as any)?.cuts ?? "",
@@ -0,0 +1,41 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import {
3
+ getRequestOrgId,
4
+ getRequestUserEmail,
5
+ } from "@agent-native/core/server";
6
+ import { z } from "zod";
7
+
8
+ import { searchAnalyticsQueryCatalog } from "../server/lib/analytics-query-catalog";
9
+
10
+ export default defineAction({
11
+ description:
12
+ "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
+ schema: z.object({
14
+ search: z
15
+ .string()
16
+ .trim()
17
+ .min(2)
18
+ .describe(
19
+ "Focused metric/entity terms from the user's question, for example 'agent native signups' or 'HubSpot closed won revenue'",
20
+ ),
21
+ limit: z
22
+ .number()
23
+ .int()
24
+ .min(1)
25
+ .max(12)
26
+ .optional()
27
+ .default(6)
28
+ .describe("Maximum ranked candidates to return"),
29
+ }),
30
+ readOnly: true,
31
+ run: async ({ search, limit }) => {
32
+ const email = getRequestUserEmail();
33
+ if (!email) throw new Error("no authenticated user");
34
+ return searchAnalyticsQueryCatalog({
35
+ search,
36
+ limit,
37
+ email,
38
+ orgId: getRequestOrgId() || null,
39
+ });
40
+ },
41
+ });
@@ -0,0 +1,13 @@
1
+ import type { ComponentProps } from "react";
2
+
3
+ import { Skeleton } from "@/components/ui/skeleton";
4
+ import { cn } from "@/lib/utils";
5
+
6
+ export function DashboardPanelSkeleton({
7
+ className,
8
+ ...props
9
+ }: ComponentProps<typeof Skeleton>) {
10
+ return (
11
+ <Skeleton {...props} className={cn("bg-muted-foreground/20", className)} />
12
+ );
13
+ }
@@ -60,7 +60,6 @@ import {
60
60
  SelectTrigger,
61
61
  SelectValue,
62
62
  } from "@/components/ui/select";
63
- import { Skeleton } from "@/components/ui/skeleton";
64
63
  import { useChartTooltipPortalPosition } from "@/hooks/use-chart-tooltip-portal";
65
64
 
66
65
  const PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
@@ -75,6 +74,8 @@ import type {
75
74
  ColumnFormat,
76
75
  } from "@/pages/adhoc/sql-dashboard/types";
77
76
 
77
+ import { DashboardPanelSkeleton } from "./DashboardPanelSkeleton";
78
+
78
79
  const DEFAULT_COLORS = [
79
80
  "var(--brand-blue)",
80
81
  "var(--brand-teal)",
@@ -820,7 +821,7 @@ function TableLoadingSkeleton() {
820
821
  <div className="min-w-[480px]">
821
822
  <div className="grid h-8 grid-cols-4 items-center border-b border-border px-2">
822
823
  {columnWidths.map((width, index) => (
823
- <Skeleton key={index} className={`h-3 ${width}`} />
824
+ <DashboardPanelSkeleton key={index} className={`h-3 ${width}`} />
824
825
  ))}
825
826
  </div>
826
827
  {Array.from({ length: TABLE_PANEL_SKELETON_ROWS }).map((_, row) => (
@@ -829,7 +830,7 @@ function TableLoadingSkeleton() {
829
830
  className="grid h-8 grid-cols-4 items-center border-b border-border/50 px-2"
830
831
  >
831
832
  {columnWidths.map((width, col) => (
832
- <Skeleton
833
+ <DashboardPanelSkeleton
833
834
  key={col}
834
835
  className={`h-3 ${
835
836
  col === 0 ? "w-36" : col === 2 ? "ml-auto w-16" : width
@@ -841,8 +842,8 @@ function TableLoadingSkeleton() {
841
842
  </div>
842
843
  </div>
843
844
  <div className="flex h-8 items-center justify-between border-t border-border px-1 text-xs">
844
- <Skeleton className="h-3 w-28" />
845
- <Skeleton className="h-3 w-24" />
845
+ <DashboardPanelSkeleton className="h-3 w-28" />
846
+ <DashboardPanelSkeleton className="h-3 w-24" />
846
847
  </div>
847
848
  </div>
848
849
  );
@@ -853,7 +854,7 @@ function SqlChartLoadingSkeleton({ panel }: { panel: SqlPanel }) {
853
854
 
854
855
  if (panel.chartType === "metric") {
855
856
  return (
856
- <Skeleton
857
+ <DashboardPanelSkeleton
857
858
  data-dashboard-report-loading="true"
858
859
  className="w-full flex-1 min-h-12"
859
860
  />
@@ -868,7 +869,7 @@ function SqlChartLoadingSkeleton({ panel }: { panel: SqlPanel }) {
868
869
 
869
870
  if (!reserveLegend) {
870
871
  return (
871
- <Skeleton
872
+ <DashboardPanelSkeleton
872
873
  data-dashboard-report-loading="true"
873
874
  className={`w-full flex-1 ${fill ? "h-full min-h-[250px]" : "min-h-[250px]"}`}
874
875
  />
@@ -880,14 +881,14 @@ function SqlChartLoadingSkeleton({ panel }: { panel: SqlPanel }) {
880
881
  data-dashboard-report-loading="true"
881
882
  className={`flex w-full flex-1 flex-col overflow-hidden ${fill ? "h-full" : ""}`}
882
883
  >
883
- <Skeleton
884
+ <DashboardPanelSkeleton
884
885
  className={`w-full ${fill ? "h-full min-h-[250px] flex-1" : "h-[250px]"}`}
885
886
  />
886
887
  <div className="mt-1 flex min-h-6 flex-wrap gap-x-3 gap-y-1 overflow-hidden pr-1">
887
888
  {Array.from({ length: 3 }).map((_, index) => (
888
889
  <div key={index} className="flex min-h-6 items-center gap-1.5">
889
- <Skeleton className="h-2.5 w-3 shrink-0 rounded-sm" />
890
- <Skeleton className="h-3 w-20 min-w-0" />
890
+ <DashboardPanelSkeleton className="h-2.5 w-3 shrink-0 rounded-sm" />
891
+ <DashboardPanelSkeleton className="h-3 w-20 min-w-0" />
891
892
  </div>
892
893
  ))}
893
894
  </div>
@@ -1329,7 +1330,7 @@ function DashboardExtensionPanel({
1329
1330
  const [ready, setReady] = useState(false);
1330
1331
  const [unavailable, setUnavailable] = useState(false);
1331
1332
  const loadingSkeleton = !ready ? (
1332
- <Skeleton
1333
+ <DashboardPanelSkeleton
1333
1334
  data-dashboard-extension-loading="true"
1334
1335
  className="absolute inset-0 z-10 h-full min-h-[180px] w-full rounded-md"
1335
1336
  aria-hidden="true"
@@ -1,7 +1,7 @@
1
1
  import type { CSSProperties } from "react";
2
2
 
3
+ import { DashboardPanelSkeleton } from "@/components/dashboard/DashboardPanelSkeleton";
3
4
  import { Card, CardContent, CardHeader } from "@/components/ui/card";
4
- import { Skeleton } from "@/components/ui/skeleton";
5
5
 
6
6
  interface DashboardSkeletonProps {
7
7
  columns?: number;
@@ -22,10 +22,10 @@ export function DashboardSkeleton({
22
22
  <div key={i} className="dashboard-grid-cell h-full">
23
23
  <Card className="flex h-full flex-col overflow-visible">
24
24
  <CardHeader className="pb-2 shrink-0">
25
- <Skeleton className="h-4 w-32" />
25
+ <DashboardPanelSkeleton className="h-4 w-32" />
26
26
  </CardHeader>
27
27
  <CardContent className="flex flex-1 flex-col pt-0">
28
- <Skeleton className="w-full flex-1 min-h-[250px]" />
28
+ <DashboardPanelSkeleton className="w-full flex-1 min-h-[250px]" />
29
29
  </CardContent>
30
30
  </Card>
31
31
  </div>
@@ -1,5 +1,5 @@
1
1
  import { generateTabId } from "@agent-native/core/client/agent-chat";
2
- import { agentNativePath } from "@agent-native/core/client/api-path";
2
+ import { agentNativePath, appPath } from "@agent-native/core/client/api-path";
3
3
  import {
4
4
  useCollaborativeDoc,
5
5
  emailToColor,
@@ -1387,6 +1387,11 @@ export default function SqlDashboardPage() {
1387
1387
  [saveView],
1388
1388
  );
1389
1389
 
1390
+ const dashboardShareUrl = useMemo(() => {
1391
+ if (!dashboardId || typeof window === "undefined") return undefined;
1392
+ return window.location.origin + appPath("/dashboards/" + dashboardId);
1393
+ }, [dashboardId]);
1394
+
1390
1395
  useSetPageTitle(
1391
1396
  reportScreenshot ? null : dashboard ? (
1392
1397
  <div className="flex min-w-0 items-center gap-2">
@@ -1439,6 +1444,7 @@ export default function SqlDashboardPage() {
1439
1444
  resourceId={dashboardId}
1440
1445
  resourceTitle={dashboard.name}
1441
1446
  variant="compact"
1447
+ shareUrl={dashboardShareUrl}
1442
1448
  shareTabs={{
1443
1449
  tabs: [
1444
1450
  {
@@ -1,4 +1,5 @@
1
1
  import { useSendToAgentChat } from "@agent-native/core/client/agent-chat";
2
+ import { appPath } from "@agent-native/core/client/api-path";
2
3
  import {
3
4
  callAction,
4
5
  useActionMutation,
@@ -18,7 +19,7 @@ import {
18
19
  IconWorld,
19
20
  } from "@tabler/icons-react";
20
21
  import { useQuery, useQueryClient } from "@tanstack/react-query";
21
- import { useEffect, useState } from "react";
22
+ import { useEffect, useMemo, useState } from "react";
22
23
  import { useParams } from "react-router";
23
24
  import { Link, useNavigate } from "react-router";
24
25
 
@@ -168,6 +169,11 @@ export default function AnalysisDetail() {
168
169
  navigate("/analyses");
169
170
  };
170
171
 
172
+ const analysisShareUrl = useMemo(() => {
173
+ if (!analysis?.id || typeof window === "undefined") return undefined;
174
+ return window.location.origin + appPath("/analyses/" + analysis.id);
175
+ }, [analysis?.id]);
176
+
171
177
  useSetPageTitle(
172
178
  analysis ? (
173
179
  <h1 className="text-lg font-semibold tracking-tight truncate">
@@ -184,6 +190,7 @@ export default function AnalysisDetail() {
184
190
  resourceId={analysis.id}
185
191
  resourceTitle={analysis.name}
186
192
  variant="compact"
193
+ shareUrl={analysisShareUrl}
187
194
  />
188
195
  <Button
189
196
  variant="outline"
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-22
4
+ ---
5
+
6
+ Fixed dashboards and analyses missing a copyable share link
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-23
4
+ ---
5
+
6
+ Dashboard chart loading placeholders are easier to see in dark mode.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-23
4
+ ---
5
+
6
+ Routine analytics lookups now search existing dashboard queries and dictionary definitions, then stop after one successful authoritative query.
@@ -31,21 +31,10 @@ export const INITIAL_TOOL_NAMES = [
31
31
  "list-extensions",
32
32
  "get-extension",
33
33
  "generate-chart",
34
+ "search-analytics-query-catalog",
34
35
  "query-agent-native-analytics",
35
36
  "bigquery",
36
37
  "search-bigquery-schema",
37
- "provider-api-catalog",
38
- "provider-api-docs",
39
- "provider-api-request",
40
- "run-code",
41
- "get-code-execution",
42
- "provider-corpus-job",
43
- "query-staged-dataset",
44
- "list-staged-datasets",
45
- "account-deep-dive",
46
- "gong-calls",
47
- "gong-native-insights",
48
- "github-repo-files",
49
38
  "list-data-dictionary",
50
39
  "navigate",
51
40
  ];