@@ -506,8 +506,11 @@ export function calculateTemplateMetrics(
506506/**
507507 * Calculate daily user engagement from workspace data
508508 * Returns array of daily unique users and active workspaces for the last 60 days
509+ *
510+ * A user is considered "engaged" if they initiate a connection to their workspace via apps, web terminal, or SSH.
511+ * This function processes all builds for each workspace and extracts all agent connection timestamps.
509512 */
510- export function calculateDailyEngagement ( workspaces : WorkspaceMetrics [ ] ) : DailyEngagement [ ] {
513+ export function calculateDailyEngagement ( workspaces : CoderWorkspace [ ] ) : DailyEngagement [ ] {
511514 const now = new Date ( ) ;
512515 const daysToShow = 60 ;
513516
@@ -524,22 +527,65 @@ export function calculateDailyEngagement(workspaces: WorkspaceMetrics[]): DailyE
524527 workspaceActivityMap . set ( dateStr , new Set ( ) ) ;
525528 }
526529
527- // Process each workspace
530+ // Process each workspace and all its builds
528531 workspaces . forEach ( ( workspace ) => {
529- const createdDate = new Date ( workspace . created_at ) . toISOString ( ) . split ( 'T' ) [ 0 ] ;
530- const lastActiveDate = workspace . last_active ? new Date ( workspace . last_active ) . toISOString ( ) . split ( 'T' ) [ 0 ] : createdDate ;
532+ const workspaceId = workspace . id ;
533+ const ownerHandle = workspace . owner_name . toLowerCase ( ) ;
534+ const allBuilds = workspace . all_builds || [ ] ;
535+
536+ // Track dates when this workspace had connections
537+ const workspaceConnectionDates = new Set < string > ( ) ;
538+
539+ // Process all builds to find all connection dates
540+ allBuilds . forEach ( ( build ) => {
541+ try {
542+ // Count workspace start actions as engagement (user initiating connection)
543+ if ( build . transition === 'start' && build . created_at ) {
544+ const dateStr = build . created_at . split ( 'T' ) [ 0 ] ;
545+ if ( engagementMap . has ( dateStr ) ) {
546+ engagementMap . get ( dateStr ) ! . add ( ownerHandle ) ;
547+ workspaceConnectionDates . add ( dateStr ) ;
548+ }
549+ }
531550
532- // Add user to created date
533- if ( engagementMap . has ( createdDate ) ) {
534- engagementMap . get ( createdDate ) ! . add ( workspace . owner_github_handle ) ;
535- workspaceActivityMap . get ( createdDate ) ! . add ( workspace . workspace_id ) ;
536- }
551+ const resources = build . resources || [ ] ;
552+
553+ for ( const resource of resources ) {
554+ const agents = resource . agents || [ ] ;
555+
556+ for ( const agent of agents ) {
557+ // Extract all connection timestamps from this agent
558+ const firstConnected = agent . first_connected_at ;
559+ const lastConnected = agent . last_connected_at ;
560+
561+ // Add engagement for first connection date
562+ if ( firstConnected ) {
563+ const dateStr = firstConnected . split ( 'T' ) [ 0 ] ;
564+ if ( engagementMap . has ( dateStr ) ) {
565+ engagementMap . get ( dateStr ) ! . add ( ownerHandle ) ;
566+ workspaceConnectionDates . add ( dateStr ) ;
567+ }
568+ }
569+
570+ // Add engagement for last connection date (if different from first)
571+ if ( lastConnected && lastConnected !== firstConnected ) {
572+ const dateStr = lastConnected . split ( 'T' ) [ 0 ] ;
573+ if ( engagementMap . has ( dateStr ) ) {
574+ engagementMap . get ( dateStr ) ! . add ( ownerHandle ) ;
575+ workspaceConnectionDates . add ( dateStr ) ;
576+ }
577+ }
578+ }
579+ }
580+ } catch ( error ) {
581+ console . warn ( `Error processing build for workspace ${ workspaceId } :` , error ) ;
582+ }
583+ } ) ;
537584
538- // Add user to last active date
539- if ( lastActiveDate !== createdDate && engagementMap . has ( lastActiveDate ) ) {
540- engagementMap . get ( lastActiveDate ) ! . add ( workspace . owner_github_handle ) ;
541- workspaceActivityMap . get ( lastActiveDate ) ! . add ( workspace . workspace_id ) ;
542- }
585+ // Add workspace to active workspaces for all dates it had connections
586+ workspaceConnectionDates . forEach ( ( dateStr ) => {
587+ workspaceActivityMap . get ( dateStr ) ?. add ( workspaceId ) ;
588+ } ) ;
543589 } ) ;
544590
545591 // Convert to array and sort by date
0 commit comments