@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,519 @@
1
+ import {
2
+ AlertDialog,
3
+ AlertDialogAction,
4
+ AlertDialogCancel,
5
+ AlertDialogContent,
6
+ AlertDialogDescription,
7
+ AlertDialogFooter,
8
+ AlertDialogHeader,
9
+ AlertDialogTitle,
10
+ } from "@agent-native/toolkit/ui/alert-dialog";
11
+ import { Badge } from "@agent-native/toolkit/ui/badge";
12
+ import { Button } from "@agent-native/toolkit/ui/button";
13
+ import {
14
+ DropdownMenu,
15
+ DropdownMenuContent,
16
+ DropdownMenuGroup,
17
+ DropdownMenuItem,
18
+ DropdownMenuTrigger,
19
+ } from "@agent-native/toolkit/ui/dropdown-menu";
20
+ import { Input } from "@agent-native/toolkit/ui/input";
21
+ import { Label } from "@agent-native/toolkit/ui/label";
22
+ import {
23
+ Select,
24
+ SelectContent,
25
+ SelectGroup,
26
+ SelectItem,
27
+ SelectTrigger,
28
+ SelectValue,
29
+ } from "@agent-native/toolkit/ui/select";
30
+ import { Textarea } from "@agent-native/toolkit/ui/textarea";
31
+ import {
32
+ IconCheck,
33
+ IconDots,
34
+ IconSettings,
35
+ IconLoader2,
36
+ IconUserCheck,
37
+ } from "@tabler/icons-react";
38
+ import { useMemo, useState } from "react";
39
+
40
+ import {
41
+ Dialog,
42
+ DialogContent,
43
+ DialogDescription,
44
+ DialogFooter,
45
+ DialogHeader,
46
+ DialogTitle,
47
+ } from "../components/ui/dialog.js";
48
+ import { useT } from "../i18n.js";
49
+ import {
50
+ normalizeFeatureFlagPercentage,
51
+ normalizeFeatureFlagRules,
52
+ } from "./helpers.js";
53
+ import type {
54
+ FeatureFlagMetadata,
55
+ FeatureFlagRules,
56
+ SetFeatureFlagInput,
57
+ } from "./types.js";
58
+
59
+ function formatActor(actor: FeatureFlagRules["updatedBy"]): string | null {
60
+ if (!actor) return null;
61
+ if (typeof actor === "string") return actor;
62
+ return actor.name ?? actor.email ?? null;
63
+ }
64
+
65
+ function formatWhen(value: number | null | undefined): string | null {
66
+ if (!value) return null;
67
+ const date = new Date(value);
68
+ if (Number.isNaN(date.valueOf())) return null;
69
+ return new Intl.DateTimeFormat(undefined, {
70
+ dateStyle: "medium",
71
+ timeStyle: "short",
72
+ }).format(date);
73
+ }
74
+
75
+ function rolloutLabel(
76
+ rules: FeatureFlagRules,
77
+ t: ReturnType<typeof useT>,
78
+ ): string {
79
+ if (rules.mode === "off") return t("featureFlags.off");
80
+ if (rules.mode === "on") return t("featureFlags.everyone");
81
+ const parts = [
82
+ rules.emails.length
83
+ ? t("featureFlags.emailCount", { count: rules.emails.length })
84
+ : null,
85
+ rules.orgIds.length
86
+ ? t("featureFlags.organizationCount", { count: rules.orgIds.length })
87
+ : null,
88
+ rules.percentage
89
+ ? t("featureFlags.percentageRollout", { count: rules.percentage })
90
+ : null,
91
+ ].filter(Boolean);
92
+ return parts.join(" · ") || t("featureFlags.inherited");
93
+ }
94
+
95
+ function audienceLabel(
96
+ rules: FeatureFlagRules,
97
+ t: ReturnType<typeof useT>,
98
+ ): string {
99
+ if (rules.mode === "off") return t("featureFlags.off");
100
+ if (rules.mode === "on") return t("featureFlags.everyoneAudience");
101
+ return rolloutLabel(rules, t);
102
+ }
103
+
104
+ function modeLabel(rules: FeatureFlagRules, t: ReturnType<typeof useT>) {
105
+ if (rules.mode === "off") return t("featureFlags.off");
106
+ if (rules.mode === "on") return t("featureFlags.everyone");
107
+ return t("featureFlags.targeted");
108
+ }
109
+
110
+ function listText(values: string[]): string {
111
+ return values.join("\n");
112
+ }
113
+
114
+ function parseList(value: string): string[] {
115
+ return [
116
+ ...new Set(
117
+ value
118
+ .split(/[\n,]/)
119
+ .map((entry) => entry.trim())
120
+ .filter(Boolean),
121
+ ),
122
+ ];
123
+ }
124
+
125
+ function TargetingDialog({
126
+ flag,
127
+ open,
128
+ onOpenChange,
129
+ onMutate,
130
+ isPending,
131
+ }: {
132
+ flag: FeatureFlagMetadata;
133
+ open: boolean;
134
+ onOpenChange: (open: boolean) => void;
135
+ onMutate: (input: SetFeatureFlagInput) => void;
136
+ isPending?: boolean;
137
+ }) {
138
+ const t = useT();
139
+ const modeId = `feature-flag-${flag.key}-mode`;
140
+ const emailsId = `feature-flag-${flag.key}-emails`;
141
+ const orgIdsId = `feature-flag-${flag.key}-org-ids`;
142
+ const percentageId = `feature-flag-${flag.key}-percentage`;
143
+ const [mode, setMode] = useState(flag.rules.mode);
144
+ const [emails, setEmails] = useState(() => listText(flag.rules.emails));
145
+ const [orgIds, setOrgIds] = useState(() => listText(flag.rules.orgIds));
146
+ const [percentage, setPercentage] = useState(String(flag.rules.percentage));
147
+
148
+ const save = () => {
149
+ const nextPercentage = normalizeFeatureFlagPercentage(percentage);
150
+ onMutate({
151
+ key: flag.key,
152
+ operation: "replace-rules",
153
+ rules: {
154
+ version: 1,
155
+ mode,
156
+ emails: parseList(emails),
157
+ orgIds: parseList(orgIds),
158
+ percentage: nextPercentage,
159
+ },
160
+ });
161
+ };
162
+
163
+ return (
164
+ <Dialog open={open} onOpenChange={onOpenChange}>
165
+ <DialogContent className="max-w-xl">
166
+ <DialogHeader>
167
+ <DialogTitle>
168
+ {t("featureFlags.targetingTitle", {
169
+ name: flag.displayName ?? flag.key,
170
+ })}
171
+ </DialogTitle>
172
+ <DialogDescription>
173
+ {t("featureFlags.targetingDescription")}
174
+ </DialogDescription>
175
+ </DialogHeader>
176
+ <div className="grid gap-2">
177
+ <Label htmlFor={modeId}>{t("featureFlags.modeLabel")}</Label>
178
+ <Select
179
+ value={mode}
180
+ onValueChange={(value) =>
181
+ setMode(value as FeatureFlagRules["mode"])
182
+ }
183
+ >
184
+ <SelectTrigger id={modeId}>
185
+ <SelectValue />
186
+ </SelectTrigger>
187
+ <SelectContent>
188
+ <SelectGroup>
189
+ <SelectItem value="off">{t("featureFlags.off")}</SelectItem>
190
+ <SelectItem value="rules">
191
+ {t("featureFlags.targeted")}
192
+ </SelectItem>
193
+ <SelectItem value="on">{t("featureFlags.everyone")}</SelectItem>
194
+ </SelectGroup>
195
+ </SelectContent>
196
+ </Select>
197
+ </div>
198
+ {mode === "rules" ? (
199
+ <div className="grid gap-4">
200
+ <div className="grid gap-2">
201
+ <Label htmlFor={emailsId}>{t("featureFlags.emailsLabel")}</Label>
202
+ <Textarea
203
+ id={emailsId}
204
+ className="min-h-20"
205
+ value={emails}
206
+ onChange={(event) => setEmails(event.target.value)}
207
+ placeholder="one@example.com"
208
+ />
209
+ </div>
210
+ <div className="grid gap-2">
211
+ <Label htmlFor={orgIdsId}>{t("featureFlags.orgIdsLabel")}</Label>
212
+ <Textarea
213
+ id={orgIdsId}
214
+ className="min-h-20"
215
+ value={orgIds}
216
+ onChange={(event) => setOrgIds(event.target.value)}
217
+ placeholder="org_123"
218
+ />
219
+ </div>
220
+ <div className="grid gap-2">
221
+ <Label htmlFor={percentageId}>
222
+ {t("featureFlags.percentageLabel")}
223
+ </Label>
224
+ <Input
225
+ id={percentageId}
226
+ type="number"
227
+ min="0"
228
+ max="100"
229
+ step="1"
230
+ value={percentage}
231
+ onChange={(event) => setPercentage(event.target.value)}
232
+ />
233
+ </div>
234
+ <p className="text-xs text-muted-foreground">
235
+ {t("featureFlags.targetingRuleHelp")}
236
+ </p>
237
+ </div>
238
+ ) : null}
239
+ <div className="rounded-md bg-muted/50 px-3 py-2 text-sm">
240
+ {t("featureFlags.targetingSummary", {
241
+ audience: audienceLabel(
242
+ normalizeFeatureFlagRules({
243
+ mode,
244
+ emails: parseList(emails),
245
+ orgIds: parseList(orgIds),
246
+ percentage: normalizeFeatureFlagPercentage(percentage),
247
+ }),
248
+ t,
249
+ ),
250
+ })}
251
+ <span className="ms-2 text-xs text-muted-foreground">
252
+ ·{" "}
253
+ {flag.defaultValue
254
+ ? t("featureFlags.defaultOn")
255
+ : t("featureFlags.defaultOff")}
256
+ </span>
257
+ </div>
258
+ <DialogFooter>
259
+ <Button
260
+ type="button"
261
+ variant="ghost"
262
+ onClick={() => onOpenChange(false)}
263
+ >
264
+ {t("featureFlags.cancel")}
265
+ </Button>
266
+ <Button type="button" disabled={isPending} onClick={save}>
267
+ {isPending ? <IconLoader2 className="animate-spin" /> : null}
268
+ {t("featureFlags.saveRules")}
269
+ </Button>
270
+ </DialogFooter>
271
+ </DialogContent>
272
+ </Dialog>
273
+ );
274
+ }
275
+
276
+ function FeatureFlagRow({
277
+ flag,
278
+ onMutate,
279
+ isPending,
280
+ error,
281
+ }: {
282
+ flag: FeatureFlagMetadata;
283
+ onMutate: (input: SetFeatureFlagInput) => void;
284
+ isPending?: boolean;
285
+ error?: Error | null;
286
+ }) {
287
+ const t = useT();
288
+ const [targetingOpen, setTargetingOpen] = useState(false);
289
+ const [disableOpen, setDisableOpen] = useState(false);
290
+ const actor = formatActor(flag.rules.updatedBy);
291
+ const when = formatWhen(flag.rules.updatedAt);
292
+ const metadata = [actor, when].filter(Boolean).join(" · ");
293
+
294
+ return (
295
+ <article
296
+ id={`feature-flag-${flag.key}`}
297
+ className="grid gap-4 scroll-mt-24 border-b border-border py-5 last:border-b-0 md:grid-cols-[minmax(0,1fr)_auto] md:items-center"
298
+ >
299
+ <div className="min-w-0">
300
+ <div className="flex min-w-0 items-center gap-2">
301
+ <h3 className="truncate text-sm font-medium text-foreground">
302
+ {flag.displayName ?? flag.key}
303
+ </h3>
304
+ {flag.displayName && flag.displayName !== flag.key ? (
305
+ <code className="truncate text-xs text-muted-foreground">
306
+ {flag.key}
307
+ </code>
308
+ ) : null}
309
+ <Badge
310
+ variant={flag.rules.mode === "on" ? "secondary" : "outline"}
311
+ className="ms-auto shrink-0"
312
+ >
313
+ {modeLabel(flag.rules, t)}
314
+ </Badge>
315
+ </div>
316
+ {flag.description ? (
317
+ <p className="mt-1 text-sm text-muted-foreground">
318
+ {flag.description}
319
+ </p>
320
+ ) : null}
321
+ <div className="mt-3 flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground">
322
+ <span>
323
+ {t("featureFlags.enabledFor")}: {audienceLabel(flag.rules, t)}
324
+ </span>
325
+ {metadata ? (
326
+ <span>{t("featureFlags.lastChanged", { metadata })}</span>
327
+ ) : null}
328
+ </div>
329
+ <div className="mt-2 flex items-center gap-1.5 text-xs font-medium text-foreground">
330
+ {flag.enabledForCurrentUser === true ? (
331
+ <>
332
+ <IconCheck className="size-4 text-emerald-500" />
333
+ {t("featureFlags.youHaveAccess")}
334
+ </>
335
+ ) : flag.enabledForCurrentUser === false ? (
336
+ <>{t("featureFlags.youDoNotHaveAccess")}</>
337
+ ) : (
338
+ <>{t("featureFlags.currentUserUnknown")}</>
339
+ )}
340
+ </div>
341
+ {error ? (
342
+ <p className="mt-3 text-sm text-destructive">
343
+ {t("featureFlags.mutationUnverified", {
344
+ name: flag.displayName ?? flag.key,
345
+ })}
346
+ </p>
347
+ ) : null}
348
+ </div>
349
+ <div className="flex flex-wrap items-center gap-2 md:justify-end">
350
+ <Button
351
+ type="button"
352
+ variant="outline"
353
+ size="sm"
354
+ className="text-xs"
355
+ disabled={isPending || flag.enabledForCurrentUser === true}
356
+ onClick={() =>
357
+ onMutate({
358
+ key: flag.key,
359
+ operation: "enable-for-current-user",
360
+ })
361
+ }
362
+ >
363
+ {flag.enabledForCurrentUser === true ? (
364
+ <IconCheck />
365
+ ) : (
366
+ <IconUserCheck />
367
+ )}
368
+ {flag.enabledForCurrentUser === true
369
+ ? t("featureFlags.enabledForMe")
370
+ : t("featureFlags.enableForMe")}
371
+ </Button>
372
+ <Button
373
+ type="button"
374
+ variant="outline"
375
+ size="sm"
376
+ className="text-xs"
377
+ disabled={isPending}
378
+ onClick={() => setTargetingOpen(true)}
379
+ >
380
+ <IconSettings />
381
+ {t("featureFlags.editTargeting")}
382
+ </Button>
383
+ <DropdownMenu>
384
+ <DropdownMenuTrigger asChild>
385
+ <Button
386
+ type="button"
387
+ variant="ghost"
388
+ size="icon"
389
+ className="size-8 text-muted-foreground"
390
+ disabled={isPending}
391
+ aria-label={t("featureFlags.moreActions", {
392
+ name: flag.displayName ?? flag.key,
393
+ })}
394
+ >
395
+ <IconDots />
396
+ </Button>
397
+ </DropdownMenuTrigger>
398
+ <DropdownMenuContent align="end">
399
+ <DropdownMenuGroup>
400
+ <DropdownMenuItem
401
+ className="text-destructive focus:text-destructive"
402
+ disabled={flag.rules.mode === "off"}
403
+ onSelect={() => setDisableOpen(true)}
404
+ >
405
+ {t("featureFlags.disableForEveryone")}
406
+ </DropdownMenuItem>
407
+ </DropdownMenuGroup>
408
+ </DropdownMenuContent>
409
+ </DropdownMenu>
410
+ </div>
411
+ {targetingOpen ? (
412
+ <TargetingDialog
413
+ flag={flag}
414
+ open
415
+ onOpenChange={setTargetingOpen}
416
+ onMutate={onMutate}
417
+ isPending={isPending}
418
+ />
419
+ ) : null}
420
+ <AlertDialog open={disableOpen} onOpenChange={setDisableOpen}>
421
+ <AlertDialogContent>
422
+ <AlertDialogHeader>
423
+ <AlertDialogTitle>
424
+ {t("featureFlags.disableForEveryoneTitle", {
425
+ name: flag.displayName ?? flag.key,
426
+ })}
427
+ </AlertDialogTitle>
428
+ <AlertDialogDescription>
429
+ {t("featureFlags.disableForEveryoneDescription")}
430
+ </AlertDialogDescription>
431
+ </AlertDialogHeader>
432
+ <AlertDialogFooter>
433
+ <AlertDialogCancel>{t("featureFlags.cancel")}</AlertDialogCancel>
434
+ <AlertDialogAction
435
+ className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
436
+ onClick={() => onMutate({ key: flag.key, operation: "off" })}
437
+ >
438
+ {t("featureFlags.disableForEveryone")}
439
+ </AlertDialogAction>
440
+ </AlertDialogFooter>
441
+ </AlertDialogContent>
442
+ </AlertDialog>
443
+ </article>
444
+ );
445
+ }
446
+
447
+ export function FeatureFlagsEditor({
448
+ flags,
449
+ onMutate,
450
+ isPending,
451
+ error,
452
+ errorFlagKey,
453
+ showHeader = true,
454
+ }: {
455
+ flags: FeatureFlagMetadata[];
456
+ onMutate: (input: SetFeatureFlagInput) => void;
457
+ isPending?: boolean;
458
+ error?: Error | null;
459
+ errorFlagKey?: string | null;
460
+ showHeader?: boolean;
461
+ }) {
462
+ const t = useT();
463
+ const sortedFlags = useMemo(
464
+ () =>
465
+ flags
466
+ .map((flag) => ({
467
+ ...flag,
468
+ rules: normalizeFeatureFlagRules(flag.rules),
469
+ }))
470
+ .sort((left, right) => left.key.localeCompare(right.key)),
471
+ [flags],
472
+ );
473
+
474
+ return (
475
+ <section
476
+ className={
477
+ showHeader ? "mx-auto w-full max-w-2xl" : "mx-auto w-full max-w-4xl"
478
+ }
479
+ aria-labelledby={showHeader ? "feature-flags-title" : undefined}
480
+ aria-label={showHeader ? undefined : t("featureFlags.title")}
481
+ >
482
+ {showHeader ? (
483
+ <header className="border-b border-border pb-5">
484
+ <h2
485
+ id="feature-flags-title"
486
+ className="text-base font-semibold text-foreground"
487
+ >
488
+ {t("featureFlags.title")}
489
+ </h2>
490
+ <p className="mt-1 text-sm text-muted-foreground">
491
+ {t("featureFlags.description")}
492
+ </p>
493
+ </header>
494
+ ) : null}
495
+ {sortedFlags.length ? (
496
+ <div>
497
+ {sortedFlags.map((flag) => (
498
+ <FeatureFlagRow
499
+ key={flag.key}
500
+ flag={flag}
501
+ onMutate={onMutate}
502
+ isPending={isPending}
503
+ error={errorFlagKey === flag.key ? error : null}
504
+ />
505
+ ))}
506
+ </div>
507
+ ) : (
508
+ <p className="py-8 text-sm text-muted-foreground">
509
+ {t("featureFlags.noFlags")}
510
+ </p>
511
+ )}
512
+ {error && !errorFlagKey ? (
513
+ <p className="pt-3 text-sm text-destructive">
514
+ {t("featureFlags.mutationUnverifiedGeneric")}
515
+ </p>
516
+ ) : null}
517
+ </section>
518
+ );
519
+ }
@@ -0,0 +1,77 @@
1
+ import type { FeatureFlagRules } from "./types.js";
2
+
3
+ export type EvaluatedFeatureFlags =
4
+ | Record<string, boolean>
5
+ | { flags?: Record<string, boolean>; values?: Record<string, boolean> };
6
+
7
+ export function evaluatedFeatureFlagValues(
8
+ result: EvaluatedFeatureFlags | undefined,
9
+ ): Record<string, boolean> {
10
+ if (!result) return {};
11
+ const envelope = result as {
12
+ flags?: unknown;
13
+ values?: unknown;
14
+ };
15
+ if (
16
+ envelope.flags &&
17
+ typeof envelope.flags === "object" &&
18
+ !Array.isArray(envelope.flags)
19
+ ) {
20
+ return envelope.flags as Record<string, boolean>;
21
+ }
22
+ if (
23
+ envelope.values &&
24
+ typeof envelope.values === "object" &&
25
+ !Array.isArray(envelope.values)
26
+ ) {
27
+ return envelope.values as Record<string, boolean>;
28
+ }
29
+ return result as Record<string, boolean>;
30
+ }
31
+
32
+ export function featureFlagValue(
33
+ values: Record<string, boolean>,
34
+ key: string,
35
+ ): boolean {
36
+ return values[key] === true;
37
+ }
38
+
39
+ export function normalizeFeatureFlagPercentage(value: unknown): number {
40
+ const percentage = Number(value);
41
+ return Number.isFinite(percentage)
42
+ ? Math.floor(Math.max(0, Math.min(100, percentage)))
43
+ : 0;
44
+ }
45
+
46
+ /**
47
+ * Keep the shared editor safe while a remote app is upgrading or returning an
48
+ * optimistic/transient rule envelope. The fleet contract still validates the
49
+ * authoritative response; this only prevents absent collection fields from
50
+ * crashing the operator UI between refreshes.
51
+ */
52
+ export function normalizeFeatureFlagRules(
53
+ rules: Partial<FeatureFlagRules> | null | undefined,
54
+ ): FeatureFlagRules {
55
+ const mode =
56
+ rules?.mode === "off" || rules?.mode === "on" || rules?.mode === "rules"
57
+ ? rules.mode
58
+ : "rules";
59
+ const percentage = normalizeFeatureFlagPercentage(rules?.percentage);
60
+
61
+ return {
62
+ ...rules,
63
+ version: 1,
64
+ mode,
65
+ emails: Array.isArray(rules?.emails)
66
+ ? rules.emails.filter(
67
+ (value): value is string => typeof value === "string",
68
+ )
69
+ : [],
70
+ orgIds: Array.isArray(rules?.orgIds)
71
+ ? rules.orgIds.filter(
72
+ (value): value is string => typeof value === "string",
73
+ )
74
+ : [],
75
+ percentage,
76
+ };
77
+ }
@@ -0,0 +1,13 @@
1
+ export { FeatureFlagsEditor } from "./FeatureFlagsPanel.js";
2
+ export {
3
+ evaluatedFeatureFlagValues,
4
+ featureFlagValue,
5
+ type EvaluatedFeatureFlags,
6
+ } from "./helpers.js";
7
+ export { useFeatureFlag, useFeatureFlags } from "./use-feature-flag.js";
8
+ export type {
9
+ FeatureFlagActor,
10
+ FeatureFlagMetadata,
11
+ FeatureFlagRules,
12
+ SetFeatureFlagInput,
13
+ } from "./types.js";
@@ -0,0 +1,29 @@
1
+ export interface FeatureFlagActor {
2
+ name?: string | null;
3
+ email?: string | null;
4
+ }
5
+
6
+ export interface FeatureFlagMetadata {
7
+ key: string;
8
+ displayName?: string | null;
9
+ description?: string | null;
10
+ defaultValue: boolean;
11
+ rules: FeatureFlagRules;
12
+ enabledForCurrentUser?: boolean;
13
+ }
14
+
15
+ export interface FeatureFlagRules {
16
+ version?: 1;
17
+ mode: "off" | "on" | "rules";
18
+ emails: string[];
19
+ orgIds: string[];
20
+ percentage: number;
21
+ updatedAt?: number | null;
22
+ updatedBy?: FeatureFlagActor | string | null;
23
+ }
24
+
25
+ export interface SetFeatureFlagInput {
26
+ key: string;
27
+ operation: "off" | "enable-for-current-user" | "replace-rules";
28
+ rules?: FeatureFlagRules;
29
+ }
@@ -0,0 +1,26 @@
1
+ import { useActionQuery } from "../use-action.js";
2
+ import {
3
+ evaluatedFeatureFlagValues,
4
+ featureFlagValue,
5
+ type EvaluatedFeatureFlags,
6
+ } from "./helpers.js";
7
+
8
+ export type { EvaluatedFeatureFlags } from "./helpers.js";
9
+
10
+ /**
11
+ * Returns the current user's evaluated value for a registered feature flag.
12
+ * Flags that have not been registered evaluate to false.
13
+ */
14
+ export function useFeatureFlag(key: string): boolean {
15
+ const query = useActionQuery<EvaluatedFeatureFlags>(
16
+ "get-feature-flags" as never,
17
+ );
18
+ return featureFlagValue(evaluatedFeatureFlagValues(query.data), key);
19
+ }
20
+
21
+ export function useFeatureFlags(): Record<string, boolean> {
22
+ const query = useActionQuery<EvaluatedFeatureFlags>(
23
+ "get-feature-flags" as never,
24
+ );
25
+ return evaluatedFeatureFlagValues(query.data);
26
+ }
@@ -698,6 +698,17 @@ export {
698
698
  type DataWidgetResultMetadata,
699
699
  } from "./chat/widgets/data-widget-types.js";
700
700
  export { AgentNativeIcon } from "./components/icons/AgentNativeIcon.js";
701
+ export {
702
+ FeatureFlagsEditor,
703
+ evaluatedFeatureFlagValues,
704
+ featureFlagValue,
705
+ useFeatureFlag,
706
+ useFeatureFlags,
707
+ type FeatureFlagActor,
708
+ type FeatureFlagMetadata,
709
+ type FeatureFlagRules,
710
+ type SetFeatureFlagInput,
711
+ } from "./feature-flags/index.js";
701
712
  export {
702
713
  SettingsPanel,
703
714
  SettingsTabsPage,
@@ -776,6 +787,7 @@ export {
776
787
  export { AgentTerminal, type AgentTerminalProps } from "./terminal/index.js";
777
788
  export {
778
789
  trackEvent,
790
+ trackAgentChatLifecycle,
779
791
  trackSessionStatus,
780
792
  configureTracking,
781
793
  setTrackingContentCaptureEnabled,
@@ -800,6 +812,7 @@ export {
800
812
  type CaptureExceptionContext,
801
813
  type CapturedExceptionEvent,
802
814
  type ClientCaptureContext,
815
+ type AgentChatLifecycleEvent,
803
816
  type ConfigureTrackingOptions,
804
817
  type ErrorCaptureConfigOptions,
805
818
  type ExceptionBreadcrumb,