@agent-native/core 0.107.2 → 0.109.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (502) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +24 -0
  3. package/corpus/core/docs/content/actions.mdx +48 -0
  4. package/corpus/core/docs/content/locales/ar-SA/actions.mdx +38 -0
  5. package/corpus/core/docs/content/locales/de-DE/actions.mdx +38 -0
  6. package/corpus/core/docs/content/locales/es-ES/actions.mdx +38 -0
  7. package/corpus/core/docs/content/locales/fr-FR/actions.mdx +38 -0
  8. package/corpus/core/docs/content/locales/hi-IN/actions.mdx +38 -0
  9. package/corpus/core/docs/content/locales/ja-JP/actions.mdx +38 -0
  10. package/corpus/core/docs/content/locales/ko-KR/actions.mdx +38 -0
  11. package/corpus/core/docs/content/locales/pt-BR/actions.mdx +38 -0
  12. package/corpus/core/docs/content/locales/zh-CN/actions.mdx +38 -0
  13. package/corpus/core/docs/content/locales/zh-TW/actions.mdx +38 -0
  14. package/corpus/core/package.json +5 -1
  15. package/corpus/core/src/a2a/client.ts +140 -17
  16. package/corpus/core/src/a2a/handlers.ts +60 -0
  17. package/corpus/core/src/a2a/index.ts +6 -1
  18. package/corpus/core/src/a2a/invoke.ts +68 -1
  19. package/corpus/core/src/a2a/server.ts +13 -1
  20. package/corpus/core/src/a2a/types.ts +16 -0
  21. package/corpus/core/src/a2a-claims.ts +52 -0
  22. package/corpus/core/src/action.ts +7 -2
  23. package/corpus/core/src/agent/production-agent.ts +10 -4
  24. package/corpus/core/src/audit/record.ts +6 -0
  25. package/corpus/core/src/client/AssistantChat.tsx +648 -603
  26. package/corpus/core/src/client/MultiTabAssistantChat.tsx +31 -4
  27. package/corpus/core/src/client/agent-chat-adapter.ts +23 -37
  28. package/corpus/core/src/client/agent-sidebar-state.ts +4 -0
  29. package/corpus/core/src/client/analytics.ts +84 -0
  30. package/corpus/core/src/client/chat/message-components.tsx +94 -22
  31. package/corpus/core/src/client/chat/tool-call-display.tsx +170 -47
  32. package/corpus/core/src/client/chat/use-agent-chat-lifecycle-tracking.ts +74 -0
  33. package/corpus/core/src/client/chat-thread-url.ts +11 -0
  34. package/corpus/core/src/client/error-capture.ts +12 -0
  35. package/corpus/core/src/client/extensions/ExtensionSlot.tsx +37 -1
  36. package/corpus/core/src/client/feature-flags/FeatureFlagsPanel.tsx +519 -0
  37. package/corpus/core/src/client/feature-flags/helpers.ts +77 -0
  38. package/corpus/core/src/client/feature-flags/index.ts +13 -0
  39. package/corpus/core/src/client/feature-flags/types.ts +29 -0
  40. package/corpus/core/src/client/feature-flags/use-feature-flag.ts +26 -0
  41. package/corpus/core/src/client/index.ts +13 -0
  42. package/corpus/core/src/client/route-chunk-recovery.ts +20 -8
  43. package/corpus/core/src/client/session-replay.ts +31 -0
  44. package/corpus/core/src/extensions/actions.ts +2 -14
  45. package/corpus/core/src/extensions/routes.ts +1 -1
  46. package/corpus/core/src/extensions/store.ts +1 -1
  47. package/corpus/core/src/feature-flags/a2a-action-route.ts +56 -0
  48. package/corpus/core/src/feature-flags/actions/get-feature-flags.ts +24 -0
  49. package/corpus/core/src/feature-flags/actions/list-feature-flags.ts +69 -0
  50. package/corpus/core/src/feature-flags/actions/set-feature-flag.ts +89 -0
  51. package/corpus/core/src/feature-flags/index.ts +21 -0
  52. package/corpus/core/src/feature-flags/permissions.ts +53 -0
  53. package/corpus/core/src/feature-flags/plugin.ts +44 -0
  54. package/corpus/core/src/feature-flags/registry.ts +96 -0
  55. package/corpus/core/src/feature-flags/store.ts +176 -0
  56. package/corpus/core/src/index.ts +15 -0
  57. package/corpus/core/src/localization/default-messages.ts +50 -0
  58. package/corpus/core/src/mcp/build-server.ts +2 -2
  59. package/corpus/core/src/progress/actions.ts +4 -2
  60. package/corpus/core/src/provider-api/index.ts +205 -105
  61. package/corpus/core/src/scripts/call-agent.ts +137 -17
  62. package/corpus/core/src/server/action-discovery.ts +12 -0
  63. package/corpus/core/src/server/action-routes.ts +47 -5
  64. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +40 -0
  65. package/corpus/core/src/server/agent-chat-plugin.ts +31 -0
  66. package/corpus/core/src/server/index.ts +1 -0
  67. package/corpus/core/src/settings/org-settings.ts +13 -0
  68. package/corpus/core/src/settings/store.ts +57 -0
  69. package/corpus/core/src/styles/agent-conversation.css +7 -0
  70. package/corpus/core/src/templates/default/.agents/skills/feature-flags/SKILL.md +169 -0
  71. package/corpus/core/src/templates/default/AGENTS.md +1 -0
  72. package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +20 -0
  73. package/corpus/core/src/templates/default/app/i18n/de-DE.ts +20 -0
  74. package/corpus/core/src/templates/default/app/i18n/en-US.ts +20 -0
  75. package/corpus/core/src/templates/default/app/i18n/es-ES.ts +20 -0
  76. package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +21 -0
  77. package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +19 -0
  78. package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +20 -0
  79. package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +19 -0
  80. package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +20 -0
  81. package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +19 -0
  82. package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +19 -0
  83. package/corpus/core/src/templates/headless/.agents/skills/feature-flags/SKILL.md +169 -0
  84. package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +28 -0
  85. package/corpus/core/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
  86. package/corpus/core/src/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +169 -0
  87. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
  88. package/corpus/core/src/templates/workspace-core/AGENTS.md +1 -1
  89. package/corpus/core/src/templates/workspace-root/AGENTS.md +1 -1
  90. package/corpus/core/src/vite/action-types-plugin.ts +12 -0
  91. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +29 -10
  92. package/corpus/templates/analytics/.agents/skills/feature-flags/SKILL.md +169 -0
  93. package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +54 -23
  94. package/corpus/templates/analytics/.builder/skills/apollo/SKILL.md +19 -41
  95. package/corpus/templates/analytics/.builder/skills/commonroom/SKILL.md +20 -35
  96. package/corpus/templates/analytics/.builder/skills/github/SKILL.md +23 -67
  97. package/corpus/templates/analytics/.builder/skills/pylon/SKILL.md +25 -43
  98. package/corpus/templates/analytics/AGENTS.md +37 -16
  99. package/corpus/templates/analytics/actions/account-deep-dive.ts +1 -0
  100. package/corpus/templates/analytics/actions/configure-gong-native-insights.ts +29 -0
  101. package/corpus/templates/analytics/actions/content-calendar-schema.ts +8 -4
  102. package/corpus/templates/analytics/actions/content-calendar.ts +12 -4
  103. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -1
  104. package/corpus/templates/analytics/actions/gong-calls.ts +113 -22
  105. package/corpus/templates/analytics/actions/gong-native-insights.ts +166 -0
  106. package/corpus/templates/analytics/actions/hubspot-deals.ts +190 -46
  107. package/corpus/templates/analytics/actions/list-workspace-feature-flags.ts +15 -0
  108. package/corpus/templates/analytics/actions/navigate.ts +2 -2
  109. package/corpus/templates/analytics/actions/pylon-issues.ts +123 -0
  110. package/corpus/templates/analytics/actions/set-workspace-feature-flag.ts +45 -0
  111. package/corpus/templates/analytics/actions/slack-messages.ts +179 -27
  112. package/corpus/templates/analytics/actions/view-screen.ts +13 -0
  113. package/corpus/templates/analytics/app/components/agents/FeatureFlagsFleetPanel.tsx +243 -0
  114. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +48 -152
  115. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +11 -3
  116. package/corpus/templates/analytics/app/components/ui/chart.tsx +1 -1
  117. package/corpus/templates/analytics/app/hooks/use-chart-tooltip-flip.ts +21 -6
  118. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +3 -1
  119. package/corpus/templates/analytics/app/i18n/zh-TW.ts +30 -0
  120. package/corpus/templates/analytics/app/i18n-data.ts +385 -0
  121. package/corpus/templates/analytics/app/pages/Agents.tsx +22 -2
  122. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +181 -30
  123. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +6 -0
  124. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +4 -3
  125. package/corpus/templates/analytics/changelog/2026-07-17-dashboard-editors-can-add-shared-extensions-or-opt-into-per-.md +6 -0
  126. package/corpus/templates/analytics/changelog/2026-07-17-dashboard-extensions-show-a-loading-skeleton.md +6 -0
  127. package/corpus/templates/analytics/changelog/2026-07-17-errors-now-group-repeat-failures-consistently-and-keep-priva.md +6 -0
  128. package/corpus/templates/analytics/changelog/2026-07-17-gong-transcript-reviews-now-batch-bounded-call-windows-for-f.md +6 -0
  129. package/corpus/templates/analytics/changelog/2026-07-17-hubspot-deal-filters-now-run-in-hubspot-before-paging-result.md +6 -0
  130. package/corpus/templates/analytics/changelog/2026-07-17-manage-feature-flag-rollouts-across-your-organization-s-apps.md +6 -0
  131. package/corpus/templates/analytics/changelog/2026-07-17-notion-content-calendars-now-discover-the-matching-database-.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-17-pylon-dashboard-reads-now-use-the-paginated-issue-search-api.md +6 -0
  133. package/corpus/templates/analytics/changelog/2026-07-17-slack-reads-no-longer-join-channels-and-report-pagination-coverage.md +6 -0
  134. package/corpus/templates/analytics/server/handlers/notion.ts +14 -3
  135. package/corpus/templates/analytics/server/handlers/slack.ts +182 -29
  136. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +2 -6
  137. package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +6 -2
  138. package/corpus/templates/analytics/server/lib/db-admin-connections.ts +13 -5
  139. package/corpus/templates/analytics/server/lib/error-capture.ts +75 -8
  140. package/corpus/templates/analytics/server/lib/gong-native-policy.ts +72 -0
  141. package/corpus/templates/analytics/server/lib/gong.ts +54 -66
  142. package/corpus/templates/analytics/server/lib/hubspot.ts +40 -3
  143. package/corpus/templates/analytics/server/lib/notion.ts +83 -8
  144. package/corpus/templates/analytics/server/lib/real-data-actions.ts +4 -0
  145. package/corpus/templates/analytics/server/lib/slack.ts +242 -90
  146. package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +347 -0
  147. package/corpus/templates/analytics/server/plugins/agent-chat.ts +3 -3
  148. package/corpus/templates/analytics/server/routes/api/pylon/accounts.get.ts +42 -1
  149. package/corpus/templates/analytics/server/routes/api/pylon/issues.get.ts +71 -1
  150. package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +44 -4
  151. package/corpus/templates/assets/.agents/skills/feature-flags/SKILL.md +169 -0
  152. package/corpus/templates/brain/.agents/skills/feature-flags/SKILL.md +169 -0
  153. package/corpus/templates/calendar/.agents/skills/feature-flags/SKILL.md +169 -0
  154. package/corpus/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
  155. package/corpus/templates/clips/.agents/skills/feature-flags/SKILL.md +169 -0
  156. package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +19 -1
  157. package/corpus/templates/clips/app/components/library/create-folder-dialog.tsx +123 -0
  158. package/corpus/templates/clips/app/components/library/library-grid.tsx +42 -4
  159. package/corpus/templates/clips/app/components/library/recording-card.tsx +30 -0
  160. package/corpus/templates/clips/app/entry.client.tsx +6 -1
  161. package/corpus/templates/clips/app/i18n/ar-SA.ts +12 -1
  162. package/corpus/templates/clips/app/i18n/de-DE.ts +12 -1
  163. package/corpus/templates/clips/app/i18n/en-US.ts +12 -1
  164. package/corpus/templates/clips/app/i18n/es-ES.ts +11 -1
  165. package/corpus/templates/clips/app/i18n/fr-FR.ts +11 -1
  166. package/corpus/templates/clips/app/i18n/hi-IN.ts +10 -1
  167. package/corpus/templates/clips/app/i18n/ja-JP.ts +12 -1
  168. package/corpus/templates/clips/app/i18n/ko-KR.ts +11 -1
  169. package/corpus/templates/clips/app/i18n/pt-BR.ts +11 -1
  170. package/corpus/templates/clips/app/i18n/zh-CN.ts +11 -1
  171. package/corpus/templates/clips/app/i18n/zh-TW.ts +11 -1
  172. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +72 -1
  173. package/corpus/templates/clips/changelog/2026-07-17-choose-which-workspace-receives-new-clips-recordings-and-des.md +6 -0
  174. package/corpus/templates/clips/changelog/2026-07-17-create-folders-directly-from-the-move-menu.md +6 -0
  175. package/corpus/templates/clips/changelog/2026-07-17-failed-desktop-uploads-now-offer-a-direct-way-to-reopen-clip.md +6 -0
  176. package/corpus/templates/clips/desktop/src/app.tsx +1 -1
  177. package/corpus/templates/clips/server/plugins/feature-flags.ts +11 -0
  178. package/corpus/templates/clips/shared/feature-flags.ts +30 -37
  179. package/corpus/templates/content/.agents/skills/feature-flags/SKILL.md +169 -0
  180. package/corpus/templates/content/app/entry.client.tsx +6 -1
  181. package/corpus/templates/design/.agents/skills/feature-flags/SKILL.md +169 -0
  182. package/corpus/templates/design/AGENTS.md +5 -3
  183. package/corpus/templates/design/actions/add-fusion-screens.ts +4 -6
  184. package/corpus/templates/design/actions/apply-fusion-edits.ts +4 -6
  185. package/corpus/templates/design/actions/create-fusion-app.ts +5 -4
  186. package/corpus/templates/design/actions/deploy-fusion-app.ts +4 -3
  187. package/corpus/templates/design/actions/get-fusion-deploy-status.ts +4 -6
  188. package/corpus/templates/design/actions/list-fusion-edits.ts +4 -3
  189. package/corpus/templates/design/actions/push-fusion-app.ts +4 -6
  190. package/corpus/templates/design/actions/queue-fusion-edit.ts +4 -3
  191. package/corpus/templates/design/actions/send-fusion-message.ts +4 -6
  192. package/corpus/templates/design/actions/sync-fusion-app.ts +4 -3
  193. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +1 -1
  194. package/corpus/templates/design/app/pages/Index.tsx +8 -6
  195. package/corpus/templates/design/server/plugins/feature-flags.ts +5 -0
  196. package/corpus/templates/design/shared/full-app.ts +10 -7
  197. package/corpus/templates/dispatch/.agents/skills/feature-flags/SKILL.md +169 -0
  198. package/corpus/templates/dispatch/AGENTS.md +5 -0
  199. package/corpus/templates/dispatch/changelog/2026-07-17-apps-page-links-to-other-available-apps.md +6 -0
  200. package/corpus/templates/dispatch/changelog/2026-07-17-curated-template-remixes.md +6 -0
  201. package/corpus/templates/forms/.agents/skills/feature-flags/SKILL.md +169 -0
  202. package/corpus/templates/macros/.agents/skills/feature-flags/SKILL.md +169 -0
  203. package/corpus/templates/mail/.agents/skills/feature-flags/SKILL.md +169 -0
  204. package/corpus/templates/mail/app/entry.client.tsx +6 -1
  205. package/corpus/templates/plan/.agents/skills/feature-flags/SKILL.md +169 -0
  206. package/corpus/templates/slides/.agents/skills/feature-flags/SKILL.md +169 -0
  207. package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +11 -7
  208. package/corpus/templates/slides/.env.example +0 -1
  209. package/corpus/templates/slides/AGENTS.md +4 -0
  210. package/corpus/templates/slides/DEVELOPING.md +2 -2
  211. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +1 -1
  212. package/corpus/templates/slides/actions/logo-config.ts +6 -7
  213. package/corpus/templates/slides/actions/search-images.ts +11 -39
  214. package/corpus/templates/slides/actions/search-logos.ts +5 -52
  215. package/corpus/templates/slides/app/components/editor/ImageSearchPanel.tsx +1 -1
  216. package/corpus/templates/slides/app/components/editor/LogoSearchPanel.tsx +16 -26
  217. package/corpus/templates/slides/app/entry.client.tsx +6 -1
  218. package/corpus/templates/slides/server/lib/media-search-providers.ts +216 -0
  219. package/corpus/templates/slides/server/register-secrets.ts +30 -0
  220. package/corpus/templates/tasks/.agents/skills/feature-flags/SKILL.md +169 -0
  221. package/dist/a2a/client.d.ts +38 -1
  222. package/dist/a2a/client.d.ts.map +1 -1
  223. package/dist/a2a/client.js +81 -12
  224. package/dist/a2a/client.js.map +1 -1
  225. package/dist/a2a/handlers.d.ts.map +1 -1
  226. package/dist/a2a/handlers.js +47 -0
  227. package/dist/a2a/handlers.js.map +1 -1
  228. package/dist/a2a/index.d.ts +4 -4
  229. package/dist/a2a/index.d.ts.map +1 -1
  230. package/dist/a2a/index.js +2 -2
  231. package/dist/a2a/index.js.map +1 -1
  232. package/dist/a2a/invoke.d.ts +26 -2
  233. package/dist/a2a/invoke.d.ts.map +1 -1
  234. package/dist/a2a/invoke.js +30 -1
  235. package/dist/a2a/invoke.js.map +1 -1
  236. package/dist/a2a/server.d.ts.map +1 -1
  237. package/dist/a2a/server.js +14 -1
  238. package/dist/a2a/server.js.map +1 -1
  239. package/dist/a2a/types.d.ts +12 -0
  240. package/dist/a2a/types.d.ts.map +1 -1
  241. package/dist/a2a/types.js.map +1 -1
  242. package/dist/a2a-claims.d.ts +10 -0
  243. package/dist/a2a-claims.d.ts.map +1 -0
  244. package/dist/a2a-claims.js +41 -0
  245. package/dist/a2a-claims.js.map +1 -0
  246. package/dist/action.d.ts +7 -2
  247. package/dist/action.d.ts.map +1 -1
  248. package/dist/action.js.map +1 -1
  249. package/dist/agent/production-agent.d.ts +5 -0
  250. package/dist/agent/production-agent.d.ts.map +1 -1
  251. package/dist/agent/production-agent.js +5 -3
  252. package/dist/agent/production-agent.js.map +1 -1
  253. package/dist/audit/record.d.ts +3 -0
  254. package/dist/audit/record.d.ts.map +1 -1
  255. package/dist/audit/record.js +3 -0
  256. package/dist/audit/record.js.map +1 -1
  257. package/dist/client/AssistantChat.d.ts +14 -1
  258. package/dist/client/AssistantChat.d.ts.map +1 -1
  259. package/dist/client/AssistantChat.js +158 -136
  260. package/dist/client/AssistantChat.js.map +1 -1
  261. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  262. package/dist/client/MultiTabAssistantChat.js +27 -4
  263. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  264. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  265. package/dist/client/agent-chat-adapter.js +21 -39
  266. package/dist/client/agent-chat-adapter.js.map +1 -1
  267. package/dist/client/agent-sidebar-state.d.ts +1 -0
  268. package/dist/client/agent-sidebar-state.d.ts.map +1 -1
  269. package/dist/client/agent-sidebar-state.js +4 -0
  270. package/dist/client/agent-sidebar-state.js.map +1 -1
  271. package/dist/client/analytics.d.ts +14 -0
  272. package/dist/client/analytics.d.ts.map +1 -1
  273. package/dist/client/analytics.js +67 -0
  274. package/dist/client/analytics.js.map +1 -1
  275. package/dist/client/chat/message-components.d.ts +8 -0
  276. package/dist/client/chat/message-components.d.ts.map +1 -1
  277. package/dist/client/chat/message-components.js +62 -19
  278. package/dist/client/chat/message-components.js.map +1 -1
  279. package/dist/client/chat/tool-call-display.d.ts +6 -0
  280. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  281. package/dist/client/chat/tool-call-display.js +83 -14
  282. package/dist/client/chat/tool-call-display.js.map +1 -1
  283. package/dist/client/chat/use-agent-chat-lifecycle-tracking.d.ts +8 -0
  284. package/dist/client/chat/use-agent-chat-lifecycle-tracking.d.ts.map +1 -0
  285. package/dist/client/chat/use-agent-chat-lifecycle-tracking.js +51 -0
  286. package/dist/client/chat/use-agent-chat-lifecycle-tracking.js.map +1 -0
  287. package/dist/client/chat-thread-url.d.ts +2 -0
  288. package/dist/client/chat-thread-url.d.ts.map +1 -0
  289. package/dist/client/chat-thread-url.js +12 -0
  290. package/dist/client/chat-thread-url.js.map +1 -0
  291. package/dist/client/error-capture.d.ts.map +1 -1
  292. package/dist/client/error-capture.js +7 -0
  293. package/dist/client/error-capture.js.map +1 -1
  294. package/dist/client/extensions/ExtensionSlot.d.ts +3 -1
  295. package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -1
  296. package/dist/client/extensions/ExtensionSlot.js +28 -3
  297. package/dist/client/extensions/ExtensionSlot.js.map +1 -1
  298. package/dist/client/feature-flags/FeatureFlagsPanel.d.ts +10 -0
  299. package/dist/client/feature-flags/FeatureFlagsPanel.d.ts.map +1 -0
  300. package/dist/client/feature-flags/FeatureFlagsPanel.js +143 -0
  301. package/dist/client/feature-flags/FeatureFlagsPanel.js.map +1 -0
  302. package/dist/client/feature-flags/helpers.d.ts +16 -0
  303. package/dist/client/feature-flags/helpers.d.ts.map +1 -0
  304. package/dist/client/feature-flags/helpers.js +50 -0
  305. package/dist/client/feature-flags/helpers.js.map +1 -0
  306. package/dist/client/feature-flags/index.d.ts +5 -0
  307. package/dist/client/feature-flags/index.d.ts.map +1 -0
  308. package/dist/client/feature-flags/index.js +4 -0
  309. package/dist/client/feature-flags/index.js.map +1 -0
  310. package/dist/client/feature-flags/types.d.ts +27 -0
  311. package/dist/client/feature-flags/types.d.ts.map +1 -0
  312. package/dist/client/feature-flags/types.js +2 -0
  313. package/dist/client/feature-flags/types.js.map +1 -0
  314. package/dist/client/feature-flags/use-feature-flag.d.ts +8 -0
  315. package/dist/client/feature-flags/use-feature-flag.d.ts.map +1 -0
  316. package/dist/client/feature-flags/use-feature-flag.js +15 -0
  317. package/dist/client/feature-flags/use-feature-flag.js.map +1 -0
  318. package/dist/client/index.d.ts +2 -1
  319. package/dist/client/index.d.ts.map +1 -1
  320. package/dist/client/index.js +2 -1
  321. package/dist/client/index.js.map +1 -1
  322. package/dist/client/route-chunk-recovery.d.ts.map +1 -1
  323. package/dist/client/route-chunk-recovery.js +14 -9
  324. package/dist/client/route-chunk-recovery.js.map +1 -1
  325. package/dist/client/session-replay.d.ts +15 -0
  326. package/dist/client/session-replay.d.ts.map +1 -1
  327. package/dist/client/session-replay.js +20 -0
  328. package/dist/client/session-replay.js.map +1 -1
  329. package/dist/collab/struct-routes.d.ts +1 -1
  330. package/dist/extensions/actions.d.ts.map +1 -1
  331. package/dist/extensions/actions.js +2 -10
  332. package/dist/extensions/actions.js.map +1 -1
  333. package/dist/extensions/routes.d.ts.map +1 -1
  334. package/dist/extensions/routes.js +1 -1
  335. package/dist/extensions/routes.js.map +1 -1
  336. package/dist/extensions/store.js +1 -1
  337. package/dist/extensions/store.js.map +1 -1
  338. package/dist/feature-flags/a2a-action-route.d.ts +14 -0
  339. package/dist/feature-flags/a2a-action-route.d.ts.map +1 -0
  340. package/dist/feature-flags/a2a-action-route.js +50 -0
  341. package/dist/feature-flags/a2a-action-route.js.map +1 -0
  342. package/dist/feature-flags/actions/get-feature-flags.d.ts +3 -0
  343. package/dist/feature-flags/actions/get-feature-flags.d.ts.map +1 -0
  344. package/dist/feature-flags/actions/get-feature-flags.js +18 -0
  345. package/dist/feature-flags/actions/get-feature-flags.js.map +1 -0
  346. package/dist/feature-flags/actions/list-feature-flags.d.ts +28 -0
  347. package/dist/feature-flags/actions/list-feature-flags.d.ts.map +1 -0
  348. package/dist/feature-flags/actions/list-feature-flags.js +60 -0
  349. package/dist/feature-flags/actions/list-feature-flags.js.map +1 -0
  350. package/dist/feature-flags/actions/set-feature-flag.d.ts +26 -0
  351. package/dist/feature-flags/actions/set-feature-flag.d.ts.map +1 -0
  352. package/dist/feature-flags/actions/set-feature-flag.js +78 -0
  353. package/dist/feature-flags/actions/set-feature-flag.js.map +1 -0
  354. package/dist/feature-flags/index.d.ts +5 -0
  355. package/dist/feature-flags/index.d.ts.map +1 -0
  356. package/dist/feature-flags/index.js +5 -0
  357. package/dist/feature-flags/index.js.map +1 -0
  358. package/dist/feature-flags/permissions.d.ts +13 -0
  359. package/dist/feature-flags/permissions.d.ts.map +1 -0
  360. package/dist/feature-flags/permissions.js +37 -0
  361. package/dist/feature-flags/permissions.js.map +1 -0
  362. package/dist/feature-flags/plugin.d.ts +17 -0
  363. package/dist/feature-flags/plugin.d.ts.map +1 -0
  364. package/dist/feature-flags/plugin.js +29 -0
  365. package/dist/feature-flags/plugin.js.map +1 -0
  366. package/dist/feature-flags/registry.d.ts +23 -0
  367. package/dist/feature-flags/registry.d.ts.map +1 -0
  368. package/dist/feature-flags/registry.js +59 -0
  369. package/dist/feature-flags/registry.js.map +1 -0
  370. package/dist/feature-flags/store.d.ts +31 -0
  371. package/dist/feature-flags/store.d.ts.map +1 -0
  372. package/dist/feature-flags/store.js +124 -0
  373. package/dist/feature-flags/store.js.map +1 -0
  374. package/dist/index.d.ts +1 -0
  375. package/dist/index.d.ts.map +1 -1
  376. package/dist/index.js +1 -0
  377. package/dist/index.js.map +1 -1
  378. package/dist/localization/default-messages.d.ts +45 -0
  379. package/dist/localization/default-messages.d.ts.map +1 -1
  380. package/dist/localization/default-messages.js +45 -0
  381. package/dist/localization/default-messages.js.map +1 -1
  382. package/dist/mcp/build-server.d.ts +2 -0
  383. package/dist/mcp/build-server.d.ts.map +1 -1
  384. package/dist/mcp/build-server.js +2 -2
  385. package/dist/mcp/build-server.js.map +1 -1
  386. package/dist/notifications/routes.d.ts +2 -2
  387. package/dist/progress/actions.d.ts.map +1 -1
  388. package/dist/progress/actions.js +3 -2
  389. package/dist/progress/actions.js.map +1 -1
  390. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  391. package/dist/provider-api/index.d.ts.map +1 -1
  392. package/dist/provider-api/index.js +91 -8
  393. package/dist/provider-api/index.js.map +1 -1
  394. package/dist/resources/handlers.d.ts +3 -3
  395. package/dist/scripts/call-agent.d.ts.map +1 -1
  396. package/dist/scripts/call-agent.js +107 -16
  397. package/dist/scripts/call-agent.js.map +1 -1
  398. package/dist/server/action-discovery.d.ts.map +1 -1
  399. package/dist/server/action-discovery.js +12 -0
  400. package/dist/server/action-discovery.js.map +1 -1
  401. package/dist/server/action-routes.d.ts +3 -0
  402. package/dist/server/action-routes.d.ts.map +1 -1
  403. package/dist/server/action-routes.js +45 -5
  404. package/dist/server/action-routes.js.map +1 -1
  405. package/dist/server/agent-chat/action-filters-a2a.d.ts +6 -0
  406. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  407. package/dist/server/agent-chat/action-filters-a2a.js +27 -0
  408. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  409. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  410. package/dist/server/agent-chat-plugin.js +27 -1
  411. package/dist/server/agent-chat-plugin.js.map +1 -1
  412. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  413. package/dist/server/index.d.ts +1 -0
  414. package/dist/server/index.d.ts.map +1 -1
  415. package/dist/server/index.js +1 -0
  416. package/dist/server/index.js.map +1 -1
  417. package/dist/server/transcribe-voice.d.ts +1 -1
  418. package/dist/settings/org-settings.d.ts +2 -0
  419. package/dist/settings/org-settings.d.ts.map +1 -1
  420. package/dist/settings/org-settings.js +5 -1
  421. package/dist/settings/org-settings.js.map +1 -1
  422. package/dist/settings/store.d.ts +8 -0
  423. package/dist/settings/store.d.ts.map +1 -1
  424. package/dist/settings/store.js +48 -0
  425. package/dist/settings/store.js.map +1 -1
  426. package/dist/styles/agent-conversation.css +7 -0
  427. package/dist/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
  428. package/dist/templates/default/.agents/skills/feature-flags/SKILL.md +169 -0
  429. package/dist/templates/default/AGENTS.md +1 -0
  430. package/dist/templates/default/app/i18n/ar-SA.ts +20 -0
  431. package/dist/templates/default/app/i18n/de-DE.ts +20 -0
  432. package/dist/templates/default/app/i18n/en-US.ts +20 -0
  433. package/dist/templates/default/app/i18n/es-ES.ts +20 -0
  434. package/dist/templates/default/app/i18n/fr-FR.ts +21 -0
  435. package/dist/templates/default/app/i18n/hi-IN.ts +19 -0
  436. package/dist/templates/default/app/i18n/ja-JP.ts +20 -0
  437. package/dist/templates/default/app/i18n/ko-KR.ts +19 -0
  438. package/dist/templates/default/app/i18n/pt-BR.ts +20 -0
  439. package/dist/templates/default/app/i18n/zh-CN.ts +19 -0
  440. package/dist/templates/default/app/i18n/zh-TW.ts +19 -0
  441. package/dist/templates/headless/.agents/skills/feature-flags/SKILL.md +169 -0
  442. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +28 -0
  443. package/dist/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
  444. package/dist/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +169 -0
  445. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
  446. package/dist/templates/workspace-core/AGENTS.md +1 -1
  447. package/dist/templates/workspace-root/AGENTS.md +1 -1
  448. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  449. package/dist/vite/action-types-plugin.js +12 -0
  450. package/dist/vite/action-types-plugin.js.map +1 -1
  451. package/docs/content/actions.mdx +48 -0
  452. package/docs/content/locales/ar-SA/actions.mdx +38 -0
  453. package/docs/content/locales/de-DE/actions.mdx +38 -0
  454. package/docs/content/locales/es-ES/actions.mdx +38 -0
  455. package/docs/content/locales/fr-FR/actions.mdx +38 -0
  456. package/docs/content/locales/hi-IN/actions.mdx +38 -0
  457. package/docs/content/locales/ja-JP/actions.mdx +38 -0
  458. package/docs/content/locales/ko-KR/actions.mdx +38 -0
  459. package/docs/content/locales/pt-BR/actions.mdx +38 -0
  460. package/docs/content/locales/zh-CN/actions.mdx +38 -0
  461. package/docs/content/locales/zh-TW/actions.mdx +38 -0
  462. package/package.json +5 -1
  463. package/src/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
  464. package/src/templates/default/.agents/skills/feature-flags/SKILL.md +169 -0
  465. package/src/templates/default/AGENTS.md +1 -0
  466. package/src/templates/default/app/i18n/ar-SA.ts +20 -0
  467. package/src/templates/default/app/i18n/de-DE.ts +20 -0
  468. package/src/templates/default/app/i18n/en-US.ts +20 -0
  469. package/src/templates/default/app/i18n/es-ES.ts +20 -0
  470. package/src/templates/default/app/i18n/fr-FR.ts +21 -0
  471. package/src/templates/default/app/i18n/hi-IN.ts +19 -0
  472. package/src/templates/default/app/i18n/ja-JP.ts +20 -0
  473. package/src/templates/default/app/i18n/ko-KR.ts +19 -0
  474. package/src/templates/default/app/i18n/pt-BR.ts +20 -0
  475. package/src/templates/default/app/i18n/zh-CN.ts +19 -0
  476. package/src/templates/default/app/i18n/zh-TW.ts +19 -0
  477. package/src/templates/headless/.agents/skills/feature-flags/SKILL.md +169 -0
  478. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +28 -0
  479. package/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
  480. package/src/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +169 -0
  481. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
  482. package/src/templates/workspace-core/AGENTS.md +1 -1
  483. package/src/templates/workspace-root/AGENTS.md +1 -1
  484. package/corpus/templates/analytics/server/handlers/github.ts +0 -200
  485. package/corpus/templates/analytics/server/handlers/pylon.ts +0 -43
  486. package/corpus/templates/analytics/server/lib/apollo.ts +0 -167
  487. package/corpus/templates/analytics/server/lib/commonroom.ts +0 -149
  488. package/corpus/templates/analytics/server/lib/github.ts +0 -660
  489. package/corpus/templates/analytics/server/lib/mixpanel.ts +0 -156
  490. package/corpus/templates/analytics/server/lib/posthog.ts +0 -194
  491. package/corpus/templates/analytics/server/lib/pylon.ts +0 -109
  492. package/corpus/templates/analytics/server/routes/api/github/graphql.post.ts +0 -1
  493. package/corpus/templates/analytics/server/routes/api/github/issue.get.ts +0 -1
  494. package/corpus/templates/analytics/server/routes/api/github/org-prs.get.ts +0 -1
  495. package/corpus/templates/analytics/server/routes/api/github/pr.get.ts +0 -1
  496. package/corpus/templates/analytics/server/routes/api/github/prs.get.ts +0 -1
  497. package/corpus/templates/analytics/server/routes/api/github/search.get.ts +0 -1
  498. package/corpus/templates/clips/actions/get-feature-flags.ts +0 -30
  499. package/corpus/templates/slides/actions/fetch-logos.ts +0 -90
  500. package/corpus/templates/slides/actions/image-search.ts +0 -64
  501. package/corpus/templates/slides/actions/import-github.ts +0 -182
  502. package/corpus/templates/slides/actions/logo-lookup.ts +0 -113
@@ -0,0 +1,347 @@
1
+ import { randomUUID } from "node:crypto";
2
+
3
+ import { signA2AToken } from "@agent-native/core/a2a";
4
+ import { fetchOrgApps, type OrgApp } from "@agent-native/core/mcp";
5
+
6
+ import type { AnalyticsAdminContext } from "./db-admin-connections.js";
7
+
8
+ const TARGET_TIMEOUT_MS = 3_000;
9
+ const CONCURRENCY = 4;
10
+
11
+ export type FleetFlagState =
12
+ | "ready"
13
+ | "no-definitions"
14
+ | "unsupported"
15
+ | "unreachable"
16
+ | "forbidden"
17
+ | "unknown-legacy";
18
+
19
+ export interface FleetFlagApp {
20
+ appId: string;
21
+ appName: string;
22
+ appOrigin: string;
23
+ state: FleetFlagState;
24
+ flags: Array<Record<string, unknown>>;
25
+ reason?: string;
26
+ }
27
+
28
+ export interface WorkspaceFeatureFlagsResult {
29
+ directoryStatus: "available" | "unavailable";
30
+ apps: FleetFlagApp[];
31
+ }
32
+
33
+ export interface WorkspaceFeatureFlagMutationResult {
34
+ contractVersion: 1;
35
+ status: "ready";
36
+ key: string;
37
+ rules: Record<string, unknown>;
38
+ scope: { orgId: string | null };
39
+ }
40
+
41
+ export interface WorkspaceFeatureFlagMutationInput {
42
+ appId: string;
43
+ key: string;
44
+ operation: "enable-for-current-user" | "off" | "replace-rules";
45
+ rules?: Record<string, unknown>;
46
+ }
47
+
48
+ export function workspaceFeatureFlagTargetInput(
49
+ input: WorkspaceFeatureFlagMutationInput,
50
+ ): Omit<WorkspaceFeatureFlagMutationInput, "appId"> {
51
+ const { appId: _appId, ...rawTargetInput } = input;
52
+ return input.operation === "replace-rules" && input.rules
53
+ ? {
54
+ ...rawTargetInput,
55
+ rules: {
56
+ ...input.rules,
57
+ emails: input.rules.emails ?? [],
58
+ orgIds: input.rules.orgIds ?? [],
59
+ percentage: input.rules.percentage ?? 0,
60
+ },
61
+ }
62
+ : rawTargetInput;
63
+ }
64
+
65
+ export function validateWorkspaceFeatureFlagMutation(
66
+ body: unknown,
67
+ expected: {
68
+ key: string;
69
+ orgId: string;
70
+ rules?: Record<string, unknown>;
71
+ enabledForEmail?: string;
72
+ },
73
+ ): WorkspaceFeatureFlagMutationResult {
74
+ const payload = body as Partial<WorkspaceFeatureFlagMutationResult> | null;
75
+ const valid =
76
+ payload?.contractVersion === 1 &&
77
+ payload.status === "ready" &&
78
+ payload.key === expected.key &&
79
+ !!payload.rules &&
80
+ typeof payload.rules === "object" &&
81
+ !Array.isArray(payload.rules) &&
82
+ !!payload.scope &&
83
+ typeof payload.scope === "object" &&
84
+ payload.scope.orgId === expected.orgId;
85
+ if (!valid)
86
+ throw new Error(
87
+ "The target app returned an unsupported or unverified feature flag mutation response.",
88
+ );
89
+ const persistedRules = payload.rules as Record<string, unknown>;
90
+ if (expected.rules) {
91
+ for (const field of ["mode", "percentage"] as const) {
92
+ if (
93
+ expected.rules[field] !== undefined &&
94
+ persistedRules[field] !== expected.rules[field]
95
+ )
96
+ throw new Error(
97
+ "The target app did not persist the requested feature flag rules.",
98
+ );
99
+ }
100
+ for (const field of ["emails", "orgIds"] as const) {
101
+ const isValidTargetArray = (value: unknown): value is string[] =>
102
+ Array.isArray(value) &&
103
+ value.every(
104
+ (item) => typeof item === "string" && item.trim().length > 0,
105
+ );
106
+ const normalize = (value: unknown) =>
107
+ Array.isArray(value)
108
+ ? [
109
+ ...new Set(
110
+ value
111
+ .filter((item): item is string => typeof item === "string")
112
+ .map((item) =>
113
+ field === "emails"
114
+ ? item.trim().toLowerCase()
115
+ : item.trim(),
116
+ )
117
+ .filter(Boolean),
118
+ ),
119
+ ].sort()
120
+ : [];
121
+ if (
122
+ expected.rules[field] !== undefined &&
123
+ (!isValidTargetArray(persistedRules[field]) ||
124
+ JSON.stringify(normalize(persistedRules[field])) !==
125
+ JSON.stringify(normalize(expected.rules[field])))
126
+ )
127
+ throw new Error(
128
+ "The target app did not persist the requested feature flag rules.",
129
+ );
130
+ }
131
+ }
132
+ if (expected.enabledForEmail) {
133
+ const email = expected.enabledForEmail.trim().toLowerCase();
134
+ const emails = Array.isArray(persistedRules.emails)
135
+ ? persistedRules.emails
136
+ .filter((value): value is string => typeof value === "string")
137
+ .map((value) => value.trim().toLowerCase())
138
+ : [];
139
+ if (persistedRules.mode !== "on" && !emails.includes(email))
140
+ throw new Error(
141
+ "The target app did not enable the feature flag for the delegated operator.",
142
+ );
143
+ }
144
+ return payload as WorkspaceFeatureFlagMutationResult;
145
+ }
146
+
147
+ function targetOrigin(app: OrgApp): string {
148
+ return new URL(app.url).origin;
149
+ }
150
+
151
+ async function delegatedToken(
152
+ admin: AnalyticsAdminContext,
153
+ origin: string,
154
+ scope: "flags:read" | "flags:write",
155
+ ): Promise<string> {
156
+ return signA2AToken(admin.userEmail, undefined, undefined, {
157
+ expiresIn: "120s",
158
+ preferGlobalSecret: true,
159
+ audience: origin,
160
+ extraClaims: { org_id: admin.orgId, scope, jti: randomUUID() },
161
+ });
162
+ }
163
+
164
+ async function callTarget(
165
+ app: OrgApp,
166
+ admin: AnalyticsAdminContext,
167
+ action: "list-feature-flags" | "set-feature-flag",
168
+ body: Record<string, unknown>,
169
+ ): Promise<{ status: number; body: unknown }> {
170
+ const origin = targetOrigin(app);
171
+ const token = await delegatedToken(
172
+ admin,
173
+ origin,
174
+ action === "list-feature-flags" ? "flags:read" : "flags:write",
175
+ );
176
+ const response = await fetch(`${origin}/_agent-native/actions/${action}`, {
177
+ method: action === "list-feature-flags" ? "GET" : "POST",
178
+ headers: {
179
+ Authorization: `Bearer ${token}`,
180
+ Accept: "application/json",
181
+ ...(action === "set-feature-flag"
182
+ ? { "Content-Type": "application/json" }
183
+ : {}),
184
+ },
185
+ ...(action === "set-feature-flag" ? { body: JSON.stringify(body) } : {}),
186
+ signal: AbortSignal.timeout(TARGET_TIMEOUT_MS),
187
+ });
188
+ let parsed: unknown = null;
189
+ try {
190
+ parsed = await response.json();
191
+ } catch {
192
+ // A legacy/non-action endpoint is classified below without reflecting body.
193
+ }
194
+ return { status: response.status, body: parsed };
195
+ }
196
+
197
+ export function classifyWorkspaceFeatureFlagList(
198
+ app: OrgApp,
199
+ result: { status: number; body: unknown },
200
+ ): FleetFlagApp {
201
+ const base = {
202
+ appId: app.id,
203
+ appName: app.name,
204
+ appOrigin: targetOrigin(app),
205
+ flags: [] as Array<Record<string, unknown>>,
206
+ };
207
+ if (result.status === 401 || result.status === 403)
208
+ return { ...base, state: "forbidden" };
209
+ if (result.status === 404 || result.status === 405)
210
+ return { ...base, state: "unsupported" };
211
+ if (result.status < 200 || result.status >= 300)
212
+ return { ...base, state: "unknown-legacy" };
213
+ const payload = result.body as {
214
+ flags?: unknown;
215
+ canManage?: unknown;
216
+ status?: unknown;
217
+ contractVersion?: unknown;
218
+ } | null;
219
+ if (!payload || !Array.isArray(payload.flags))
220
+ return { ...base, state: "unknown-legacy" };
221
+ if (payload.contractVersion !== 1)
222
+ return { ...base, state: "unknown-legacy" };
223
+ if (payload.status === "no-definitions")
224
+ return { ...base, state: "no-definitions" };
225
+ if (payload.status === "forbidden" || payload.canManage === false)
226
+ return { ...base, state: "forbidden" };
227
+ if (payload.flags.length === 0) return { ...base, state: "no-definitions" };
228
+ return {
229
+ ...base,
230
+ state: "ready",
231
+ flags: payload.flags.filter(
232
+ (f): f is Record<string, unknown> => !!f && typeof f === "object",
233
+ ),
234
+ };
235
+ }
236
+
237
+ async function mapBounded<T, R>(
238
+ items: T[],
239
+ fn: (item: T) => Promise<R>,
240
+ ): Promise<R[]> {
241
+ const results: R[] = [];
242
+ let cursor = 0;
243
+ await Promise.all(
244
+ Array.from({ length: Math.min(CONCURRENCY, items.length) }, async () => {
245
+ while (cursor < items.length) {
246
+ const index = cursor++;
247
+ results[index] = await fn(items[index]!);
248
+ }
249
+ }),
250
+ );
251
+ return results;
252
+ }
253
+
254
+ export async function listWorkspaceFeatureFlags(
255
+ admin: AnalyticsAdminContext,
256
+ ): Promise<WorkspaceFeatureFlagsResult> {
257
+ const apps = await fetchOrgApps({ serviceOrgId: admin.orgId });
258
+ if (apps.length === 0) return { directoryStatus: "unavailable", apps: [] };
259
+ const entries = await mapBounded(apps, async (app) => {
260
+ try {
261
+ return classifyWorkspaceFeatureFlagList(
262
+ app,
263
+ await callTarget(app, admin, "list-feature-flags", {}),
264
+ );
265
+ } catch {
266
+ return {
267
+ appId: app.id,
268
+ appName: app.name,
269
+ appOrigin: targetOrigin(app),
270
+ state: "unreachable" as const,
271
+ flags: [],
272
+ };
273
+ }
274
+ });
275
+ return { directoryStatus: "available", apps: entries };
276
+ }
277
+
278
+ export async function setWorkspaceFeatureFlag(
279
+ admin: AnalyticsAdminContext,
280
+ input: WorkspaceFeatureFlagMutationInput,
281
+ ): Promise<WorkspaceFeatureFlagMutationResult> {
282
+ const apps = await fetchOrgApps({ serviceOrgId: admin.orgId });
283
+ const app = apps.find((candidate) => candidate.id === input.appId);
284
+ if (!app)
285
+ throw new Error(
286
+ "The requested app is not available in this organization directory.",
287
+ );
288
+ const targetInput = workspaceFeatureFlagTargetInput(input);
289
+ const result = await callTarget(app, admin, "set-feature-flag", targetInput);
290
+ if (result.status === 401 || result.status === 403)
291
+ throw new Error("The target app denied this delegated flag operation.");
292
+ if (result.status === 404 || result.status === 405)
293
+ throw new Error("The target app does not support feature flag management.");
294
+ if (result.status < 200 || result.status >= 300)
295
+ throw new Error(
296
+ "The target app could not persist the feature flag change.",
297
+ );
298
+ return validateWorkspaceFeatureFlagMutation(result.body, {
299
+ key: input.key,
300
+ orgId: admin.orgId,
301
+ ...(input.operation === "replace-rules" && input.rules
302
+ ? {
303
+ rules: {
304
+ mode: input.rules.mode,
305
+ emails: input.rules.emails ?? [],
306
+ orgIds: input.rules.orgIds ?? [],
307
+ percentage: input.rules.percentage ?? 0,
308
+ },
309
+ }
310
+ : input.operation === "off"
311
+ ? {
312
+ rules: {
313
+ mode: "off",
314
+ emails: [],
315
+ orgIds: [],
316
+ percentage: 0,
317
+ },
318
+ }
319
+ : { enabledForEmail: admin.userEmail }),
320
+ });
321
+ }
322
+
323
+ export async function getWorkspaceFlagTarget(
324
+ admin: AnalyticsAdminContext,
325
+ appId: string,
326
+ ): Promise<FleetFlagApp> {
327
+ const apps = await fetchOrgApps({ serviceOrgId: admin.orgId });
328
+ const app = apps.find((candidate) => candidate.id === appId);
329
+ if (!app)
330
+ throw new Error(
331
+ "The requested app is not available in this organization directory.",
332
+ );
333
+ try {
334
+ return classifyWorkspaceFeatureFlagList(
335
+ app,
336
+ await callTarget(app, admin, "list-feature-flags", {}),
337
+ );
338
+ } catch {
339
+ return {
340
+ appId: app.id,
341
+ appName: app.name,
342
+ appOrigin: targetOrigin(app),
343
+ state: "unreachable",
344
+ flags: [],
345
+ };
346
+ }
347
+ }
@@ -687,7 +687,7 @@ export default createAgentChatPlugin({
687
687
  connectorCatalog: [...ANALYTICS_CONNECTOR_CATALOG],
688
688
  externalAgents: {
689
689
  // Keep the direct MCP surface deliberately curated. External agents
690
- // should use ask_app for multi-step investigation; these six actions are
690
+ // should use ask_app for multi-step investigation; cataloged actions are
691
691
  // bounded fallback reads for callers that already know what they need.
692
692
  authenticatedReads: "off",
693
693
  writes: "ask_app_only",
@@ -704,8 +704,8 @@ export default createAgentChatPlugin({
704
704
  analyticsSourceGuidanceOpening() +
705
705
  "DASHBOARD CREATION RULE — You may create dashboards, analyses, SQL panels, or other resources only when the user explicitly asks you to (e.g. 'build me a dashboard for...', 'create a new analysis', 'add a chart for...'). Never create any resource proactively during research, trend analysis, or answering questions. If you think a dashboard would be useful, suggest it and wait for explicit confirmation before creating anything. Never add new items to the sidebar or modify existing dashboards without an explicit user directive. " +
706
706
  "DASHBOARD MUTATION RULE — For dashboard edits, default to `mutate-dashboard` with the typed `dashboard.*` script API so the main payload is a string and avoids native-array serialization traps. It can move panels by id, edit titles/SQL/config, insert, duplicate, remove, and patch dashboard fields in one atomic save. The script API is constrained: no variables/imports/loops/functions, only JSON-compatible arguments on documented dashboard methods. Do not count shifting `/panels/<index>` positions for ordinary dashboard edits unless the user specifically asks for low-level JSON-pointer operations. " +
707
- 'DASHBOARD EXTENSION BOX RULE — Analytics dashboards support extension boxes. Insert `chartType: "extension"` panels with `config.extensionSlotId` set to `analytics.dashboard.<dashboard-id>.panel.<panel-id>`, then call `add-extension-slot-target` and `install-extension` with that same id. The install is per-user; the extension box stays on the shared dashboard and receives dashboard/panel/current-filter context. Use `get-sql-dashboard` panel summaries to inspect an existing box; `config.extensionId` is only the legacy direct-embed format. ' +
708
- "EXTENSION DATA-REPAIR RULE — When fixing data in an existing extension-backed dashboard or migrated surface such as Risk Meeting, inspect the current dashboard and extension first, then use `update-extension` `patches`/`edits` that change only the data-loading seam. Preserve the existing layout, CSS, copy, and interactions; never reconstruct the full HTML body for a data-only fix. Full-body replacement is blocked unless `allowFullReplacement=true`, which is reserved for an explicit visual rewrite or a complete replacement body supplied by the user. If a focused edit fails, change the target instead of retrying identical arguments. " +
707
+ 'DASHBOARD EXTENSION BOX RULE — Analytics dashboards support extension boxes. For ordinary requests such as "put X in this dashboard," insert a `chartType: "extension"` panel with `config.extensionId`; this author-selected embed is shared with the dashboard, appears in scheduled reports, and receives dashboard/panel/current-filter context. Use `config.extensionSlotId` only when the user explicitly asks for a personal/per-viewer slot. Slot ids use `analytics.dashboard.<dashboard-id>.panel.<panel-id>` and require `add-extension-slot-target` plus `install-extension`; installs are per-user, so viewers can see different content and report identities may see an empty slot. Use `get-sql-dashboard` panel summaries to inspect an existing box. ' +
708
+ "EXTENSION DATA-REPAIR RULE — When fixing data in an existing extension-backed dashboard or migrated surface such as Risk Meeting, inspect the current dashboard and extension first, then use `update-extension` `patches`/`edits` that change only the data-loading seam. Preserve the existing layout, CSS, copy, and interactions; never reconstruct the full HTML body for a data-only fix. Full-body replacement is blocked unless `allowFullReplacement=true`. A request that combines a visual rewrite such as compacting, removing sections, renaming, or changing padding with a data repair is a broad rewrite; after inspecting the current extension, use `allowFullReplacement=true` for the complete replacement. If a focused edit fails, change the target instead of retrying identical arguments. " +
709
709
  'FIRST-PARTY DASHBOARD TIME RULE — AI-generated `source: "first-party"` panels are dashboard-time-bound by default: set `config.timeScope` to `dashboard` and include a matching dashboard time predicate. `{{timeRange}}` requires a matching `filters` entry with `id: "timeRange"` and `type: "select"`; `{{<id>Start}}`/`{{<id>End}}` require a matching `type: "date-range"` filter with that id. Allowed `timeScope` values are `dashboard`, `fixed-window`, `cohort-history`, and `all-time`; use `all-time` only when the user requests full available history and put all-time, lifetime, or historical in the title or description. Server validation rejects unbound first-party SQL. ' +
710
710
  "DASHBOARD READ RULE — `get-sql-dashboard` is compact by default: use its `panels` summaries plus `layout.panelOrder`, `layout.firstPanelIds`, and `layout.groups[].rows[].rowNumber/panelIds` for orientation and verification. Pass `includeConfig: true` only when you truly need full panel SQL/config. " +
711
711
  'DASHBOARD REORDER RULE — For simple chart/section moves, use `mutate-dashboard` code such as `dashboard.panels(["panel-a","panel-b"]).moveToTop();`. For visible placement requests like "second row" or "next to return rates", use row-aware placement such as `dashboard.insertPanel({...}).nextTo("retention-over-time")`, `.atRow(2)`, or `dashboard.panel("panel-a").moveNextTo("panel-b")`; these keep panels in the intended rendered row and expand/rebalance that row when needed. Never count shifting `/panels/<index>` positions for ordinary \'move this chart\' requests. Use `get-sql-dashboard.layout.groups[].rows` as proof of visible row placement, not only flat `panelOrder`. ' +
@@ -1 +1,42 @@
1
- export { handlePylonAccounts as default } from "../../../handlers/pylon";
1
+ import { defineEventHandler, getQuery, setResponseStatus } from "h3";
2
+
3
+ import {
4
+ requireCredential,
5
+ runApiHandlerWithContext,
6
+ } from "../../../lib/credentials";
7
+ import { executeProviderApiRequest } from "../../../lib/provider-api";
8
+
9
+ export default defineEventHandler((event) =>
10
+ runApiHandlerWithContext(event, async () => {
11
+ const missing = await requireCredential(event, "PYLON_API_KEY", "Pylon");
12
+ if (missing) return missing;
13
+ try {
14
+ const query = getQuery(event);
15
+ const search =
16
+ typeof query.query === "string" && query.query.trim()
17
+ ? query.query
18
+ : undefined;
19
+ const result = (await executeProviderApiRequest({
20
+ provider: "pylon",
21
+ method: "GET",
22
+ path: "/accounts",
23
+ ...(search ? { query: { query: search } } : {}),
24
+ })) as { response?: { json?: unknown } };
25
+ const body = result.response?.json;
26
+ const accounts =
27
+ Array.isArray(body) || !body || typeof body !== "object"
28
+ ? Array.isArray(body)
29
+ ? body
30
+ : []
31
+ : Array.isArray((body as { data?: unknown }).data)
32
+ ? (body as { data: unknown[] }).data
33
+ : [];
34
+ return { accounts, total: accounts.length };
35
+ } catch (error) {
36
+ setResponseStatus(event, 500);
37
+ return {
38
+ error: error instanceof Error ? error.message : String(error),
39
+ };
40
+ }
41
+ }),
42
+ );
@@ -1 +1,71 @@
1
- export { handlePylonIssues as default } from "../../../handlers/pylon";
1
+ import { defineEventHandler, getQuery, setResponseStatus } from "h3";
2
+
3
+ import pylonIssues from "../../../../actions/pylon-issues";
4
+ import {
5
+ requireCredential,
6
+ runApiHandlerWithContext,
7
+ } from "../../../lib/credentials";
8
+ import { executeProviderApiRequest } from "../../../lib/provider-api";
9
+
10
+ function queryString(value: unknown): string | undefined {
11
+ return typeof value === "string" && value.trim() ? value : undefined;
12
+ }
13
+
14
+ function responseItems(value: unknown): unknown[] {
15
+ if (Array.isArray(value)) return value;
16
+ if (value && typeof value === "object" && "data" in value) {
17
+ const data = (value as { data?: unknown }).data;
18
+ return Array.isArray(data) ? data : [];
19
+ }
20
+ return [];
21
+ }
22
+
23
+ export default defineEventHandler((event) =>
24
+ runApiHandlerWithContext(event, async () => {
25
+ const missing = await requireCredential(event, "PYLON_API_KEY", "Pylon");
26
+ if (missing) return missing;
27
+ try {
28
+ const query = getQuery(event);
29
+ const accountId = queryString(query.account_id);
30
+ const state = queryString(query.state);
31
+ const search = queryString(query.query);
32
+
33
+ if (accountId || state || search) {
34
+ const now = new Date();
35
+ const start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1_000);
36
+ const response = (await executeProviderApiRequest({
37
+ provider: "pylon",
38
+ method: "GET",
39
+ path: "/issues",
40
+ query: {
41
+ ...(accountId ? { account_id: accountId } : {}),
42
+ ...(state ? { state } : {}),
43
+ ...(search ? { query: search } : {}),
44
+ start_time: start.toISOString(),
45
+ end_time: now.toISOString(),
46
+ },
47
+ })) as { response?: { json?: unknown } };
48
+ const issues = responseItems(response.response?.json);
49
+ return { issues, total: issues.length };
50
+ }
51
+
52
+ const days = queryString(query.days);
53
+ const parsedDays = days == null ? 371 : Number(days);
54
+ if (!Number.isInteger(parsedDays) || parsedDays < 1 || parsedDays > 730) {
55
+ setResponseStatus(event, 400);
56
+ return { error: "days must be an integer between 1 and 730" };
57
+ }
58
+ const result = await pylonIssues.run({
59
+ days: parsedDays,
60
+ pageSize: 500,
61
+ maxPages: 20,
62
+ });
63
+ return result;
64
+ } catch (error) {
65
+ setResponseStatus(event, 500);
66
+ return {
67
+ error: error instanceof Error ? error.message : String(error),
68
+ };
69
+ }
70
+ }),
71
+ );
@@ -6,6 +6,7 @@ import {
6
6
  resolveCredential,
7
7
  withRequestContextFromEvent,
8
8
  } from "../../lib/credentials";
9
+ import { executeProviderApiRequest } from "../../lib/provider-api";
9
10
  import {
10
11
  CLAY_ANALYTICS_CREDENTIAL_KEYS,
11
12
  HUBSPOT_ANALYTICS_CREDENTIAL_KEYS,
@@ -13,6 +14,32 @@ import {
13
14
  resolveAnalyticsProviderCredential,
14
15
  } from "../../lib/provider-credentials";
15
16
 
17
+ type ProviderApiConnectionResponse = {
18
+ response?: {
19
+ ok?: boolean;
20
+ status?: number;
21
+ text?: string;
22
+ json?: unknown;
23
+ };
24
+ };
25
+
26
+ function providerApiConnectionResult(
27
+ provider: string,
28
+ result: unknown,
29
+ ): { ok: boolean; error?: string } {
30
+ const response = (result as ProviderApiConnectionResponse).response;
31
+ if (response?.ok) return { ok: true };
32
+
33
+ const detail =
34
+ response?.text?.trim() ||
35
+ (response?.json === undefined ? "" : JSON.stringify(response.json));
36
+ const status = response?.status ?? "unknown";
37
+ return {
38
+ ok: false,
39
+ error: `${provider} API error ${status}${detail ? `: ${detail}` : ""}`,
40
+ };
41
+ }
42
+
16
43
  export default defineEventHandler(async (event) => {
17
44
  const body = await readBody(event);
18
45
  const { source } = body as { source?: string };
@@ -66,8 +93,17 @@ export default defineEventHandler(async (event) => {
66
93
  const sa = await resolveCredential("MIXPANEL_SERVICE_ACCOUNT", ctx);
67
94
  if (!projectId || !sa)
68
95
  return { ok: false, error: "Missing credentials" };
69
- const { testConnection } = await import("../../lib/mixpanel");
70
- return await testConnection();
96
+ const result = await executeProviderApiRequest({
97
+ provider: "mixpanel",
98
+ method: "GET",
99
+ path: "/events/top",
100
+ query: {
101
+ type: "general",
102
+ limit: 1,
103
+ project_id: "{projectId}",
104
+ },
105
+ });
106
+ return providerApiConnectionResult("Mixpanel", result);
71
107
  }
72
108
 
73
109
  case "posthog": {
@@ -75,8 +111,12 @@ export default defineEventHandler(async (event) => {
75
111
  const projectId = await resolveCredential("POSTHOG_PROJECT_ID", ctx);
76
112
  if (!apiKey || !projectId)
77
113
  return { ok: false, error: "Missing credentials" };
78
- const { testConnection } = await import("../../lib/posthog");
79
- return await testConnection();
114
+ const result = await executeProviderApiRequest({
115
+ provider: "posthog",
116
+ method: "GET",
117
+ path: "/api/projects/{projectId}/",
118
+ });
119
+ return providerApiConnectionResult("PostHog", result);
80
120
  }
81
121
 
82
122
  case "postgresql": {