33 REPORT_MODEL_RESOLVER ,
44 type ReportModelResolver ,
55} from "@posthog/core/inbox/identifiers" ;
6+ import { classifyIntegrations } from "@posthog/core/integrations/selectors" ;
67import {
78 TASK_SERVICE ,
89 type TaskCreationInput ,
@@ -21,6 +22,10 @@ import {
2122 ResponderAgentRoster ,
2223 ResponderAgentRosterSkeleton ,
2324} from "@posthog/ui/features/inbox/components/ResponderAgentRoster" ;
25+ import {
26+ RESPONDER_AGENT_GROUPS ,
27+ type ResponderAgentSource ,
28+ } from "@posthog/ui/features/inbox/components/responderAgentMeta" ;
2429import { resolveDefaultModel } from "@posthog/ui/features/inbox/hooks/resolveDefaultModel" ;
2530import { useSignalSourceManager } from "@posthog/ui/features/inbox/hooks/useSignalSourceManager" ;
2631import {
@@ -72,6 +77,18 @@ Inspect the connected PostHog project and repository, figure out which Self-driv
7277
7378const log = logger . scope ( "agents-setup-task" ) ;
7479
80+ /**
81+ * Source products that count as Responders on this page. `displayValues` also
82+ * carries the legacy `signals_scout` toggle, but scouts render separately in
83+ * `ScoutsFleetSection` and are excluded from the responder roster — so they must
84+ * not inflate the responder counts in `AGENTS_VIEWED`.
85+ */
86+ const RESPONDER_SOURCE_PRODUCTS = new Set < ResponderAgentSource > (
87+ RESPONDER_AGENT_GROUPS . flatMap ( ( group ) =>
88+ group . agents . map ( ( agent ) => agent . source ) ,
89+ ) ,
90+ ) ;
91+
7592export function ConfigureAgentsSection ( ) {
7693 const {
7794 displayValues,
@@ -92,18 +109,33 @@ export function ConfigureAgentsSection() {
92109 const {
93110 isLoading : isLoadingSlackIntegrations ,
94111 isError : isIntegrationsError ,
112+ data : integrationsData ,
95113 } = useIntegrations ( ) ;
96114 const isLoadingSlack = isLoadingIntegrations || isLoadingSlackIntegrations ;
97115 const showSetupTask = useFeatureFlag ( SELF_DRIVING_SETUP_TASK_FLAG ) ;
98116 const userAutostartPriority =
99117 userAutonomyConfig ?. autostart_priority ?? NEVER_AUTOSTART_VALUE ;
100118
119+ // Derive from the query data, not the store-backed `hasGithubIntegration`: the
120+ // store is hydrated by a passive effect that lags the query by a render, so the
121+ // store value can still read `false` on the render where the query settles —
122+ // exactly when the view event fires. Classifying the query data avoids the lag.
123+ const trackedHasGithubIntegration = classifyIntegrations (
124+ integrationsData ?? [ ] ,
125+ ) . hasGithubIntegration ;
126+ // Count only Responder sources; `displayValues` also includes `signals_scout`,
127+ // which renders separately and would otherwise inflate the responder counts.
128+ const responderEntries = Object . entries ( displayValues ) . filter ( ( [ source ] ) =>
129+ RESPONDER_SOURCE_PRODUCTS . has ( source as ResponderAgentSource ) ,
130+ ) ;
131+
101132 useTrackAgentsViewed ( {
102133 isLoading : isLoading || isLoadingIntegrations || userAutonomyConfigLoading ,
103134 isError : isIntegrationsError ,
104- hasGithubIntegration,
105- responderTotalCount : Object . keys ( displayValues ) . length ,
106- responderEnabledCount : Object . values ( displayValues ) . filter ( Boolean ) . length ,
135+ hasGithubIntegration : trackedHasGithubIntegration ,
136+ responderTotalCount : responderEntries . length ,
137+ responderEnabledCount : responderEntries . filter ( ( [ , enabled ] ) => enabled )
138+ . length ,
107139 autostartPriority : userAutonomyConfig ?. autostart_priority ?? null ,
108140 setupTaskAvailable : showSetupTask ,
109141 } ) ;
@@ -292,23 +324,36 @@ function SetupTaskSection() {
292324 ) ;
293325
294326 const handleStartSetup = useCallback ( async ( ) => {
327+ // A click that fails a precondition is still a failed setup attempt; emit
328+ // `run_setup_agent` with success:false so these don't drop out of the funnel
329+ // and bias the success rate upward. (The re-entrancy and still-loading guards
330+ // below are not attempts, so they don't fire.)
331+ const trackSetupFailure = ( ) =>
332+ track ( ANALYTICS_EVENTS . AGENTS_ACTION , {
333+ action_type : "run_setup_agent" ,
334+ success : false ,
335+ } ) ;
336+
295337 if ( isStartingSetupTask ) return ;
296338 if ( isLoadingRepos ) {
297339 toast . error ( "Still loading GitHub repositories" ) ;
298340 return ;
299341 }
300342 if ( ! hasGithubIntegration || ! setupRepository ) {
343+ trackSetupFailure ( ) ;
301344 toast . error ( "Connect GitHub before starting Self-driving setup" ) ;
302345 return ;
303346 }
304347 if ( ! cloudRegion ) {
348+ trackSetupFailure ( ) ;
305349 toast . error ( "Sign in to start Self-driving setup" ) ;
306350 return ;
307351 }
308352
309353 const githubUserIntegrationId =
310354 getUserIntegrationIdForRepo ( setupRepository ) ;
311355 if ( ! githubUserIntegrationId ) {
356+ trackSetupFailure ( ) ;
312357 toast . error ( "Connect a GitHub integration with repository access" ) ;
313358 return ;
314359 }
@@ -334,6 +379,7 @@ function SetupTaskSection() {
334379
335380 if ( ! model ) {
336381 sonnerToast . dismiss ( toastId ) ;
382+ trackSetupFailure ( ) ;
337383 toast . error ( "Failed to start Self-driving setup" , {
338384 description :
339385 "Couldn't resolve a default model. Open the task page once and pick a model, then try again." ,
0 commit comments