diff --git a/apps/desktop/src/main/managers/service-manager.ts b/apps/desktop/src/main/managers/service-manager.ts index fd4b16a..5a7fd2f 100644 --- a/apps/desktop/src/main/managers/service-manager.ts +++ b/apps/desktop/src/main/managers/service-manager.ts @@ -64,8 +64,8 @@ export class ServiceManager { this.initializeSettingsService(); this.initializeAuthService(); await this.initializeTelemetryService(); - await this.initializeOnboardingService(); await this.initializeModelServices(); + await this.initializeOnboardingService(); this.initializePlatformServices(); await this.initializeVADService(); await this.initializeAIServices(); @@ -99,9 +99,9 @@ export class ServiceManager { } private async initializeOnboardingService(): Promise { - if (!this.settingsService || !this.telemetryService) { + if (!this.settingsService || !this.telemetryService || !this.modelService) { logger.main.warn( - "Settings or telemetry service not available for onboarding", + "Settings, telemetry, or model service not available for onboarding", ); return; } @@ -109,6 +109,7 @@ export class ServiceManager { this.onboardingService = OnboardingService.getInstance( this.settingsService, this.telemetryService, + this.modelService, ); logger.main.info("Onboarding service initialized"); } diff --git a/apps/desktop/src/services/auth-service.ts b/apps/desktop/src/services/auth-service.ts index dd4456f..b996cd4 100644 --- a/apps/desktop/src/services/auth-service.ts +++ b/apps/desktop/src/services/auth-service.ts @@ -4,6 +4,7 @@ import { logger } from "../main/logger"; import { EventEmitter } from "events"; import { getSettingsSection, updateSettingsSection } from "../db/app-settings"; import { getUserAgent } from "../utils/http-client"; +import { ServiceManager } from "../main/managers/service-manager"; interface AuthConfig { clientId: string; @@ -201,6 +202,17 @@ export class AuthService extends EventEmitter { // Save to database await updateSettingsSection("auth", authState); + // Identify user in telemetry + if (authState.userInfo?.sub) { + const telemetryService = + ServiceManager.getInstance().getService("telemetryService"); + telemetryService.identifyUser( + authState.userInfo.sub, + authState.userInfo.email, + authState.userInfo.name, + ); + } + // Clear pending auth this.pendingAuth = null; diff --git a/apps/desktop/src/services/onboarding-service.ts b/apps/desktop/src/services/onboarding-service.ts index 0ac6fc3..3986fe6 100644 --- a/apps/desktop/src/services/onboarding-service.ts +++ b/apps/desktop/src/services/onboarding-service.ts @@ -3,6 +3,7 @@ import { systemPreferences } from "electron"; import { logger } from "../main/logger"; import type { SettingsService } from "./settings-service"; import type { TelemetryService } from "./telemetry-service"; +import type { ModelService } from "./model-service"; import type { AppSettingsData } from "../db/schema"; import { OnboardingScreen, @@ -40,26 +41,31 @@ export class OnboardingService extends EventEmitter { private static instance: OnboardingService | null = null; private settingsService: SettingsService; private telemetryService: TelemetryService; + private modelService: ModelService; private currentState: Partial = {}; private isOnboardingInProgress = false; constructor( settingsService: SettingsService, telemetryService: TelemetryService, + modelService: ModelService, ) { super(); this.settingsService = settingsService; this.telemetryService = telemetryService; + this.modelService = modelService; } static getInstance( settingsService: SettingsService, telemetryService: TelemetryService, + modelService: ModelService, ): OnboardingService { if (!OnboardingService.instance) { OnboardingService.instance = new OnboardingService( settingsService, telemetryService, + modelService, ); } return OnboardingService.instance; @@ -211,7 +217,7 @@ export class OnboardingService extends EventEmitter { }); } - // Track model selection + // Track model selection and set the actual model if (preferences.selectedModelType !== undefined) { updates.selectedModelType = preferences.selectedModelType; this.telemetryService.trackOnboardingModelSelected({ @@ -219,6 +225,26 @@ export class OnboardingService extends EventEmitter { recommendation_followed: preferences.modelRecommendation?.followed ?? false, }); + + // Set the actual model in ModelService + if (preferences.selectedModelType === "cloud") { + await this.modelService.setSelectedModel("amical-cloud"); + logger.main.info("Set default speech model to amical-cloud"); + } else if (preferences.selectedModelType === "local") { + // Keep existing selection if any, otherwise use first downloaded model + const currentModel = await this.modelService.getSelectedModel(); + if (!currentModel) { + const downloadedModels = + await this.modelService.getDownloadedModels(); + const downloadedIds = Object.keys(downloadedModels); + if (downloadedIds.length > 0) { + await this.modelService.setSelectedModel(downloadedIds[0]); + logger.main.info( + `Set default speech model to ${downloadedIds[0]}`, + ); + } + } + } } if (preferences.modelRecommendation !== undefined) { diff --git a/apps/desktop/src/services/telemetry-service.ts b/apps/desktop/src/services/telemetry-service.ts index e549905..405ca3f 100644 --- a/apps/desktop/src/services/telemetry-service.ts +++ b/apps/desktop/src/services/telemetry-service.ts @@ -126,13 +126,6 @@ export class TelemetryService { }, }; - // Identify the machine with system properties - this.posthog.identify({ - distinctId: this.machineId, - properties: { - ...this.persistedProperties, - }, - }); this.enabled = true; this.initialized = true; logger.main.info("Telemetry service initialized successfully"); @@ -261,6 +254,34 @@ export class TelemetryService { } } + // ============================================================================ + // User Identification + // ============================================================================ + + /** + * Identify user in telemetry after login. + * Also creates an alias to link machine ID with user ID. + */ + identifyUser(userId: string, email?: string, name?: string): void { + if (!this.posthog || !this.enabled) return; + + // Identify with user ID + this.posthog.identify({ + distinctId: userId, + properties: { + ...this.persistedProperties, + email, + name, + }, + }); + + // Alias machine ID to user ID so previous anonymous events are linked + this.posthog.alias({ + distinctId: userId, + alias: this.machineId, + }); + } + // ============================================================================ // Onboarding Events // ============================================================================