@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.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +24 -0
- package/corpus/core/docs/content/actions.mdx +48 -0
- package/corpus/core/docs/content/locales/ar-SA/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/de-DE/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/es-ES/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/fr-FR/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/hi-IN/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/ja-JP/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/ko-KR/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/pt-BR/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/zh-CN/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/zh-TW/actions.mdx +38 -0
- package/corpus/core/package.json +5 -1
- package/corpus/core/src/a2a/client.ts +140 -17
- package/corpus/core/src/a2a/handlers.ts +60 -0
- package/corpus/core/src/a2a/index.ts +6 -1
- package/corpus/core/src/a2a/invoke.ts +68 -1
- package/corpus/core/src/a2a/server.ts +13 -1
- package/corpus/core/src/a2a/types.ts +16 -0
- package/corpus/core/src/a2a-claims.ts +52 -0
- package/corpus/core/src/action.ts +7 -2
- package/corpus/core/src/agent/production-agent.ts +10 -4
- package/corpus/core/src/audit/record.ts +6 -0
- package/corpus/core/src/client/AssistantChat.tsx +648 -603
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +31 -4
- package/corpus/core/src/client/agent-chat-adapter.ts +23 -37
- package/corpus/core/src/client/agent-sidebar-state.ts +4 -0
- package/corpus/core/src/client/analytics.ts +84 -0
- package/corpus/core/src/client/chat/message-components.tsx +94 -22
- package/corpus/core/src/client/chat/tool-call-display.tsx +170 -47
- package/corpus/core/src/client/chat/use-agent-chat-lifecycle-tracking.ts +74 -0
- package/corpus/core/src/client/chat-thread-url.ts +11 -0
- package/corpus/core/src/client/error-capture.ts +12 -0
- package/corpus/core/src/client/extensions/ExtensionSlot.tsx +37 -1
- package/corpus/core/src/client/feature-flags/FeatureFlagsPanel.tsx +519 -0
- package/corpus/core/src/client/feature-flags/helpers.ts +77 -0
- package/corpus/core/src/client/feature-flags/index.ts +13 -0
- package/corpus/core/src/client/feature-flags/types.ts +29 -0
- package/corpus/core/src/client/feature-flags/use-feature-flag.ts +26 -0
- package/corpus/core/src/client/index.ts +13 -0
- package/corpus/core/src/client/route-chunk-recovery.ts +20 -8
- package/corpus/core/src/client/session-replay.ts +31 -0
- package/corpus/core/src/extensions/actions.ts +2 -14
- package/corpus/core/src/extensions/routes.ts +1 -1
- package/corpus/core/src/extensions/store.ts +1 -1
- package/corpus/core/src/feature-flags/a2a-action-route.ts +56 -0
- package/corpus/core/src/feature-flags/actions/get-feature-flags.ts +24 -0
- package/corpus/core/src/feature-flags/actions/list-feature-flags.ts +69 -0
- package/corpus/core/src/feature-flags/actions/set-feature-flag.ts +89 -0
- package/corpus/core/src/feature-flags/index.ts +21 -0
- package/corpus/core/src/feature-flags/permissions.ts +53 -0
- package/corpus/core/src/feature-flags/plugin.ts +44 -0
- package/corpus/core/src/feature-flags/registry.ts +96 -0
- package/corpus/core/src/feature-flags/store.ts +176 -0
- package/corpus/core/src/index.ts +15 -0
- package/corpus/core/src/localization/default-messages.ts +50 -0
- package/corpus/core/src/mcp/build-server.ts +2 -2
- package/corpus/core/src/progress/actions.ts +4 -2
- package/corpus/core/src/provider-api/index.ts +205 -105
- package/corpus/core/src/scripts/call-agent.ts +137 -17
- package/corpus/core/src/server/action-discovery.ts +12 -0
- package/corpus/core/src/server/action-routes.ts +47 -5
- package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +40 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +31 -0
- package/corpus/core/src/server/index.ts +1 -0
- package/corpus/core/src/settings/org-settings.ts +13 -0
- package/corpus/core/src/settings/store.ts +57 -0
- package/corpus/core/src/styles/agent-conversation.css +7 -0
- package/corpus/core/src/templates/default/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/core/src/templates/default/AGENTS.md +1 -0
- package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/de-DE.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/es-ES.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +19 -0
- package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +19 -0
- package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +19 -0
- package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +19 -0
- package/corpus/core/src/templates/headless/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +28 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
- package/corpus/core/src/templates/workspace-core/AGENTS.md +1 -1
- package/corpus/core/src/templates/workspace-root/AGENTS.md +1 -1
- package/corpus/core/src/vite/action-types-plugin.ts +12 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +29 -10
- package/corpus/templates/analytics/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +54 -23
- package/corpus/templates/analytics/.builder/skills/apollo/SKILL.md +19 -41
- package/corpus/templates/analytics/.builder/skills/commonroom/SKILL.md +20 -35
- package/corpus/templates/analytics/.builder/skills/github/SKILL.md +23 -67
- package/corpus/templates/analytics/.builder/skills/pylon/SKILL.md +25 -43
- package/corpus/templates/analytics/AGENTS.md +37 -16
- package/corpus/templates/analytics/actions/account-deep-dive.ts +1 -0
- package/corpus/templates/analytics/actions/configure-gong-native-insights.ts +29 -0
- package/corpus/templates/analytics/actions/content-calendar-schema.ts +8 -4
- package/corpus/templates/analytics/actions/content-calendar.ts +12 -4
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -1
- package/corpus/templates/analytics/actions/gong-calls.ts +113 -22
- package/corpus/templates/analytics/actions/gong-native-insights.ts +166 -0
- package/corpus/templates/analytics/actions/hubspot-deals.ts +190 -46
- package/corpus/templates/analytics/actions/list-workspace-feature-flags.ts +15 -0
- package/corpus/templates/analytics/actions/navigate.ts +2 -2
- package/corpus/templates/analytics/actions/pylon-issues.ts +123 -0
- package/corpus/templates/analytics/actions/set-workspace-feature-flag.ts +45 -0
- package/corpus/templates/analytics/actions/slack-messages.ts +179 -27
- package/corpus/templates/analytics/actions/view-screen.ts +13 -0
- package/corpus/templates/analytics/app/components/agents/FeatureFlagsFleetPanel.tsx +243 -0
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +48 -152
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +11 -3
- package/corpus/templates/analytics/app/components/ui/chart.tsx +1 -1
- package/corpus/templates/analytics/app/hooks/use-chart-tooltip-flip.ts +21 -6
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +3 -1
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +30 -0
- package/corpus/templates/analytics/app/i18n-data.ts +385 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +22 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +181 -30
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +6 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +4 -3
- package/corpus/templates/analytics/changelog/2026-07-17-dashboard-editors-can-add-shared-extensions-or-opt-into-per-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-dashboard-extensions-show-a-loading-skeleton.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-errors-now-group-repeat-failures-consistently-and-keep-priva.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-gong-transcript-reviews-now-batch-bounded-call-windows-for-f.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-hubspot-deal-filters-now-run-in-hubspot-before-paging-result.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-manage-feature-flag-rollouts-across-your-organization-s-apps.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-notion-content-calendars-now-discover-the-matching-database-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-pylon-dashboard-reads-now-use-the-paginated-issue-search-api.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-slack-reads-no-longer-join-channels-and-report-pagination-coverage.md +6 -0
- package/corpus/templates/analytics/server/handlers/notion.ts +14 -3
- package/corpus/templates/analytics/server/handlers/slack.ts +182 -29
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +2 -6
- package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +6 -2
- package/corpus/templates/analytics/server/lib/db-admin-connections.ts +13 -5
- package/corpus/templates/analytics/server/lib/error-capture.ts +75 -8
- package/corpus/templates/analytics/server/lib/gong-native-policy.ts +72 -0
- package/corpus/templates/analytics/server/lib/gong.ts +54 -66
- package/corpus/templates/analytics/server/lib/hubspot.ts +40 -3
- package/corpus/templates/analytics/server/lib/notion.ts +83 -8
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +4 -0
- package/corpus/templates/analytics/server/lib/slack.ts +242 -90
- package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +347 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +3 -3
- package/corpus/templates/analytics/server/routes/api/pylon/accounts.get.ts +42 -1
- package/corpus/templates/analytics/server/routes/api/pylon/issues.get.ts +71 -1
- package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +44 -4
- package/corpus/templates/assets/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/brain/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/calendar/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/clips/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +19 -1
- package/corpus/templates/clips/app/components/library/create-folder-dialog.tsx +123 -0
- package/corpus/templates/clips/app/components/library/library-grid.tsx +42 -4
- package/corpus/templates/clips/app/components/library/recording-card.tsx +30 -0
- package/corpus/templates/clips/app/entry.client.tsx +6 -1
- package/corpus/templates/clips/app/i18n/ar-SA.ts +12 -1
- package/corpus/templates/clips/app/i18n/de-DE.ts +12 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +12 -1
- package/corpus/templates/clips/app/i18n/es-ES.ts +11 -1
- package/corpus/templates/clips/app/i18n/fr-FR.ts +11 -1
- package/corpus/templates/clips/app/i18n/hi-IN.ts +10 -1
- package/corpus/templates/clips/app/i18n/ja-JP.ts +12 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +11 -1
- package/corpus/templates/clips/app/i18n/pt-BR.ts +11 -1
- package/corpus/templates/clips/app/i18n/zh-CN.ts +11 -1
- package/corpus/templates/clips/app/i18n/zh-TW.ts +11 -1
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +72 -1
- package/corpus/templates/clips/changelog/2026-07-17-choose-which-workspace-receives-new-clips-recordings-and-des.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-create-folders-directly-from-the-move-menu.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-failed-desktop-uploads-now-offer-a-direct-way-to-reopen-clip.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +1 -1
- package/corpus/templates/clips/server/plugins/feature-flags.ts +11 -0
- package/corpus/templates/clips/shared/feature-flags.ts +30 -37
- package/corpus/templates/content/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/content/app/entry.client.tsx +6 -1
- package/corpus/templates/design/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/design/AGENTS.md +5 -3
- package/corpus/templates/design/actions/add-fusion-screens.ts +4 -6
- package/corpus/templates/design/actions/apply-fusion-edits.ts +4 -6
- package/corpus/templates/design/actions/create-fusion-app.ts +5 -4
- package/corpus/templates/design/actions/deploy-fusion-app.ts +4 -3
- package/corpus/templates/design/actions/get-fusion-deploy-status.ts +4 -6
- package/corpus/templates/design/actions/list-fusion-edits.ts +4 -3
- package/corpus/templates/design/actions/push-fusion-app.ts +4 -6
- package/corpus/templates/design/actions/queue-fusion-edit.ts +4 -3
- package/corpus/templates/design/actions/send-fusion-message.ts +4 -6
- package/corpus/templates/design/actions/sync-fusion-app.ts +4 -3
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +1 -1
- package/corpus/templates/design/app/pages/Index.tsx +8 -6
- package/corpus/templates/design/server/plugins/feature-flags.ts +5 -0
- package/corpus/templates/design/shared/full-app.ts +10 -7
- package/corpus/templates/dispatch/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/dispatch/AGENTS.md +5 -0
- package/corpus/templates/dispatch/changelog/2026-07-17-apps-page-links-to-other-available-apps.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-17-curated-template-remixes.md +6 -0
- package/corpus/templates/forms/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/macros/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/mail/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/mail/app/entry.client.tsx +6 -1
- package/corpus/templates/plan/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/slides/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +11 -7
- package/corpus/templates/slides/.env.example +0 -1
- package/corpus/templates/slides/AGENTS.md +4 -0
- package/corpus/templates/slides/DEVELOPING.md +2 -2
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +1 -1
- package/corpus/templates/slides/actions/logo-config.ts +6 -7
- package/corpus/templates/slides/actions/search-images.ts +11 -39
- package/corpus/templates/slides/actions/search-logos.ts +5 -52
- package/corpus/templates/slides/app/components/editor/ImageSearchPanel.tsx +1 -1
- package/corpus/templates/slides/app/components/editor/LogoSearchPanel.tsx +16 -26
- package/corpus/templates/slides/app/entry.client.tsx +6 -1
- package/corpus/templates/slides/server/lib/media-search-providers.ts +216 -0
- package/corpus/templates/slides/server/register-secrets.ts +30 -0
- package/corpus/templates/tasks/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/a2a/client.d.ts +38 -1
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +81 -12
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +47 -0
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/index.d.ts +4 -4
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +2 -2
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/invoke.d.ts +26 -2
- package/dist/a2a/invoke.d.ts.map +1 -1
- package/dist/a2a/invoke.js +30 -1
- package/dist/a2a/invoke.js.map +1 -1
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js +14 -1
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/types.d.ts +12 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/a2a-claims.d.ts +10 -0
- package/dist/a2a-claims.d.ts.map +1 -0
- package/dist/a2a-claims.js +41 -0
- package/dist/a2a-claims.js.map +1 -0
- package/dist/action.d.ts +7 -2
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts +5 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +5 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/audit/record.d.ts +3 -0
- package/dist/audit/record.d.ts.map +1 -1
- package/dist/audit/record.js +3 -0
- package/dist/audit/record.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +14 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +158 -136
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +27 -4
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +21 -39
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-sidebar-state.d.ts +1 -0
- package/dist/client/agent-sidebar-state.d.ts.map +1 -1
- package/dist/client/agent-sidebar-state.js +4 -0
- package/dist/client/agent-sidebar-state.js.map +1 -1
- package/dist/client/analytics.d.ts +14 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +67 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/chat/message-components.d.ts +8 -0
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +62 -19
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +6 -0
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +83 -14
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat/use-agent-chat-lifecycle-tracking.d.ts +8 -0
- package/dist/client/chat/use-agent-chat-lifecycle-tracking.d.ts.map +1 -0
- package/dist/client/chat/use-agent-chat-lifecycle-tracking.js +51 -0
- package/dist/client/chat/use-agent-chat-lifecycle-tracking.js.map +1 -0
- package/dist/client/chat-thread-url.d.ts +2 -0
- package/dist/client/chat-thread-url.d.ts.map +1 -0
- package/dist/client/chat-thread-url.js +12 -0
- package/dist/client/chat-thread-url.js.map +1 -0
- package/dist/client/error-capture.d.ts.map +1 -1
- package/dist/client/error-capture.js +7 -0
- package/dist/client/error-capture.js.map +1 -1
- package/dist/client/extensions/ExtensionSlot.d.ts +3 -1
- package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionSlot.js +28 -3
- package/dist/client/extensions/ExtensionSlot.js.map +1 -1
- package/dist/client/feature-flags/FeatureFlagsPanel.d.ts +10 -0
- package/dist/client/feature-flags/FeatureFlagsPanel.d.ts.map +1 -0
- package/dist/client/feature-flags/FeatureFlagsPanel.js +143 -0
- package/dist/client/feature-flags/FeatureFlagsPanel.js.map +1 -0
- package/dist/client/feature-flags/helpers.d.ts +16 -0
- package/dist/client/feature-flags/helpers.d.ts.map +1 -0
- package/dist/client/feature-flags/helpers.js +50 -0
- package/dist/client/feature-flags/helpers.js.map +1 -0
- package/dist/client/feature-flags/index.d.ts +5 -0
- package/dist/client/feature-flags/index.d.ts.map +1 -0
- package/dist/client/feature-flags/index.js +4 -0
- package/dist/client/feature-flags/index.js.map +1 -0
- package/dist/client/feature-flags/types.d.ts +27 -0
- package/dist/client/feature-flags/types.d.ts.map +1 -0
- package/dist/client/feature-flags/types.js +2 -0
- package/dist/client/feature-flags/types.js.map +1 -0
- package/dist/client/feature-flags/use-feature-flag.d.ts +8 -0
- package/dist/client/feature-flags/use-feature-flag.d.ts.map +1 -0
- package/dist/client/feature-flags/use-feature-flag.js +15 -0
- package/dist/client/feature-flags/use-feature-flag.js.map +1 -0
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/route-chunk-recovery.d.ts.map +1 -1
- package/dist/client/route-chunk-recovery.js +14 -9
- package/dist/client/route-chunk-recovery.js.map +1 -1
- package/dist/client/session-replay.d.ts +15 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +20 -0
- package/dist/client/session-replay.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +2 -10
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +1 -1
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/store.js +1 -1
- package/dist/extensions/store.js.map +1 -1
- package/dist/feature-flags/a2a-action-route.d.ts +14 -0
- package/dist/feature-flags/a2a-action-route.d.ts.map +1 -0
- package/dist/feature-flags/a2a-action-route.js +50 -0
- package/dist/feature-flags/a2a-action-route.js.map +1 -0
- package/dist/feature-flags/actions/get-feature-flags.d.ts +3 -0
- package/dist/feature-flags/actions/get-feature-flags.d.ts.map +1 -0
- package/dist/feature-flags/actions/get-feature-flags.js +18 -0
- package/dist/feature-flags/actions/get-feature-flags.js.map +1 -0
- package/dist/feature-flags/actions/list-feature-flags.d.ts +28 -0
- package/dist/feature-flags/actions/list-feature-flags.d.ts.map +1 -0
- package/dist/feature-flags/actions/list-feature-flags.js +60 -0
- package/dist/feature-flags/actions/list-feature-flags.js.map +1 -0
- package/dist/feature-flags/actions/set-feature-flag.d.ts +26 -0
- package/dist/feature-flags/actions/set-feature-flag.d.ts.map +1 -0
- package/dist/feature-flags/actions/set-feature-flag.js +78 -0
- package/dist/feature-flags/actions/set-feature-flag.js.map +1 -0
- package/dist/feature-flags/index.d.ts +5 -0
- package/dist/feature-flags/index.d.ts.map +1 -0
- package/dist/feature-flags/index.js +5 -0
- package/dist/feature-flags/index.js.map +1 -0
- package/dist/feature-flags/permissions.d.ts +13 -0
- package/dist/feature-flags/permissions.d.ts.map +1 -0
- package/dist/feature-flags/permissions.js +37 -0
- package/dist/feature-flags/permissions.js.map +1 -0
- package/dist/feature-flags/plugin.d.ts +17 -0
- package/dist/feature-flags/plugin.d.ts.map +1 -0
- package/dist/feature-flags/plugin.js +29 -0
- package/dist/feature-flags/plugin.js.map +1 -0
- package/dist/feature-flags/registry.d.ts +23 -0
- package/dist/feature-flags/registry.d.ts.map +1 -0
- package/dist/feature-flags/registry.js +59 -0
- package/dist/feature-flags/registry.js.map +1 -0
- package/dist/feature-flags/store.d.ts +31 -0
- package/dist/feature-flags/store.d.ts.map +1 -0
- package/dist/feature-flags/store.js +124 -0
- package/dist/feature-flags/store.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/localization/default-messages.d.ts +45 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +45 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/build-server.d.ts +2 -0
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +2 -2
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/progress/actions.d.ts.map +1 -1
- package/dist/progress/actions.js +3 -2
- package/dist/progress/actions.js.map +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +91 -8
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +107 -16
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +12 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/action-routes.d.ts +3 -0
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +45 -5
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.d.ts +6 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +27 -0
- package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +27 -1
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/settings/org-settings.d.ts +2 -0
- package/dist/settings/org-settings.d.ts.map +1 -1
- package/dist/settings/org-settings.js +5 -1
- package/dist/settings/org-settings.js.map +1 -1
- package/dist/settings/store.d.ts +8 -0
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +48 -0
- package/dist/settings/store.js.map +1 -1
- package/dist/styles/agent-conversation.css +7 -0
- package/dist/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/templates/default/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/templates/default/AGENTS.md +1 -0
- package/dist/templates/default/app/i18n/ar-SA.ts +20 -0
- package/dist/templates/default/app/i18n/de-DE.ts +20 -0
- package/dist/templates/default/app/i18n/en-US.ts +20 -0
- package/dist/templates/default/app/i18n/es-ES.ts +20 -0
- package/dist/templates/default/app/i18n/fr-FR.ts +21 -0
- package/dist/templates/default/app/i18n/hi-IN.ts +19 -0
- package/dist/templates/default/app/i18n/ja-JP.ts +20 -0
- package/dist/templates/default/app/i18n/ko-KR.ts +19 -0
- package/dist/templates/default/app/i18n/pt-BR.ts +20 -0
- package/dist/templates/default/app/i18n/zh-CN.ts +19 -0
- package/dist/templates/default/app/i18n/zh-TW.ts +19 -0
- package/dist/templates/headless/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +28 -0
- package/dist/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
- package/dist/templates/workspace-core/AGENTS.md +1 -1
- package/dist/templates/workspace-root/AGENTS.md +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +12 -0
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/docs/content/actions.mdx +48 -0
- package/docs/content/locales/ar-SA/actions.mdx +38 -0
- package/docs/content/locales/de-DE/actions.mdx +38 -0
- package/docs/content/locales/es-ES/actions.mdx +38 -0
- package/docs/content/locales/fr-FR/actions.mdx +38 -0
- package/docs/content/locales/hi-IN/actions.mdx +38 -0
- package/docs/content/locales/ja-JP/actions.mdx +38 -0
- package/docs/content/locales/ko-KR/actions.mdx +38 -0
- package/docs/content/locales/pt-BR/actions.mdx +38 -0
- package/docs/content/locales/zh-CN/actions.mdx +38 -0
- package/docs/content/locales/zh-TW/actions.mdx +38 -0
- package/package.json +5 -1
- package/src/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
- package/src/templates/default/.agents/skills/feature-flags/SKILL.md +169 -0
- package/src/templates/default/AGENTS.md +1 -0
- package/src/templates/default/app/i18n/ar-SA.ts +20 -0
- package/src/templates/default/app/i18n/de-DE.ts +20 -0
- package/src/templates/default/app/i18n/en-US.ts +20 -0
- package/src/templates/default/app/i18n/es-ES.ts +20 -0
- package/src/templates/default/app/i18n/fr-FR.ts +21 -0
- package/src/templates/default/app/i18n/hi-IN.ts +19 -0
- package/src/templates/default/app/i18n/ja-JP.ts +20 -0
- package/src/templates/default/app/i18n/ko-KR.ts +19 -0
- package/src/templates/default/app/i18n/pt-BR.ts +20 -0
- package/src/templates/default/app/i18n/zh-CN.ts +19 -0
- package/src/templates/default/app/i18n/zh-TW.ts +19 -0
- package/src/templates/headless/.agents/skills/feature-flags/SKILL.md +169 -0
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +28 -0
- package/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +169 -0
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +13 -0
- package/src/templates/workspace-core/AGENTS.md +1 -1
- package/src/templates/workspace-root/AGENTS.md +1 -1
- package/corpus/templates/analytics/server/handlers/github.ts +0 -200
- package/corpus/templates/analytics/server/handlers/pylon.ts +0 -43
- package/corpus/templates/analytics/server/lib/apollo.ts +0 -167
- package/corpus/templates/analytics/server/lib/commonroom.ts +0 -149
- package/corpus/templates/analytics/server/lib/github.ts +0 -660
- package/corpus/templates/analytics/server/lib/mixpanel.ts +0 -156
- package/corpus/templates/analytics/server/lib/posthog.ts +0 -194
- package/corpus/templates/analytics/server/lib/pylon.ts +0 -109
- package/corpus/templates/analytics/server/routes/api/github/graphql.post.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/issue.get.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/org-prs.get.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/pr.get.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/prs.get.ts +0 -1
- package/corpus/templates/analytics/server/routes/api/github/search.get.ts +0 -1
- package/corpus/templates/clips/actions/get-feature-flags.ts +0 -30
- package/corpus/templates/slides/actions/fetch-logos.ts +0 -90
- package/corpus/templates/slides/actions/image-search.ts +0 -64
- package/corpus/templates/slides/actions/import-github.ts +0 -182
- 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;
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
70
|
-
|
|
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
|
|
79
|
-
|
|
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": {
|