"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TelemetryService = void 0;
const posthog_node_1 = require("posthog-node");
const crypto_1 = require("crypto");
const logger_1 = require("../utils/logger");
const ConfigManager_1 = require("./ConfigManager");
const telemetry_1 = require("../config/telemetry");
const proxy_1 = require("../config/proxy");
const log = (0, logger_1.createLogger)('TelemetryService');
const KNOWN_MCP_EDITORS = new Set([
    'cursor',
    'codex',
    'claude',
    'claude-desktop',
]);
/** Normalizes CLI `--editor` values onto PostHog `mcp_editor` for dashboards. */
const mcpEditorEventValue = (editor) => {
    if (editor === undefined || editor === '') {
        return 'claude';
    }
    const key = editor.trim().toLowerCase();
    if (KNOWN_MCP_EDITORS.has(key)) {
        return key;
    }
    return 'other';
};
const POSTHOG_PUBLIC_API_KEY = 'phc_Ntj9tXHbS64XgYxlTfhglRmFivFsfm0AERph4ZlnNH';
const HASH_PREFIX_LENGTH = 12;
class TelemetryService {
    hashTelemetryValue(value) {
        return (0, crypto_1.createHash)('sha256')
            .update(value)
            .digest('hex')
            .slice(0, HASH_PREFIX_LENGTH);
    }
    posthog = null;
    isEnabled;
    /** Default `source` stamped on every event (overridable per-call). */
    defaultSource;
    /** MCP editor (`--editor`) stamped on events when present. */
    editor;
    constructor(options = true) {
        const opts = typeof options === 'boolean' ? { enabled: options } : options;
        this.isEnabled = opts.enabled ?? true;
        this.defaultSource = opts.source ?? 'core';
        this.editor = opts.editor;
        if (this.isEnabled) {
            try {
                this.posthog = new posthog_node_1.PostHog(POSTHOG_PUBLIC_API_KEY, {
                    host: proxy_1.POSTHOG_HOST,
                    flushAt: 1,
                    flushInterval: 0,
                    personProfiles: 'always',
                });
                this.identifyUser();
                // Forward every log.error() call to PostHog as a structured event.
                // Keeps error visibility in our analytics dashboard in sync with what
                // the logger sees, without needing a separate log aggregation pipeline.
                (0, logger_1.registerErrorCapture)((message, args, service) => {
                    const errorArg = args.find((a) => a instanceof Error);
                    const MAX_DETAIL_LENGTH = 512;
                    const errorDetail = args
                        .map((a) => (a instanceof Error ? a.message : String(a)))
                        .join(' ')
                        .slice(0, MAX_DETAIL_LENGTH);
                    const payload = {
                        error_message: message,
                        service: service ?? 'unknown',
                        error_type: 'logged_error',
                        ...(errorDetail ? { error_detail: errorDetail } : {}),
                        ...(errorArg?.stack ? { error_stack: errorArg.stack } : {}),
                    };
                    this.track('logger_error', payload);
                });
                log.info('Telemetry initialized');
            }
            catch (error) {
                // Use stderr directly so this is visible even if log is broken.
                process.stderr.write(`[TelemetryService] Init failed — error capture and PostHog events DISABLED: ${error}\n`);
                log.warn('Telemetry failed to initialize (MCP events will not be sent):', error);
                this.isEnabled = false;
            }
        }
        else {
            log.debug('Telemetry disabled');
        }
    }
    /**
     * Returns the canonical analytics identity: the Supabase user id when known,
     * else the email, else a stable anonymous ID. Keying on user id means the
     * same human is one PostHog person across surfaces and survives email changes.
     */
    get distinctId() {
        const cm = (0, ConfigManager_1.getConfigManager)();
        return cm.getUserId() ?? cm.getEmail() ?? cm.getAnonymousId();
    }
    /**
     * Identify the user in PostHog keyed on the canonical Supabase user id, and
     * merge their prior identities (email + anonymous ID) into it so history is
     * not split. `source` is intentionally NOT set as a person property — it is
     * an event property so the person stays merged across surfaces.
     *
     * No-op if the current user id has already been aliased+identified in a prior
     * run: posthog-node has no dedup, and this is called from the constructor on
     * every CLI/server process start. Without persistence we'd emit a
     * $create_alias event on every invocation.
     */
    identifyUser() {
        if (!this.isEnabled || !this.posthog)
            return;
        const cm = (0, ConfigManager_1.getConfigManager)();
        const userId = cm.getUserId();
        const email = cm.getEmail();
        // Without a user id we can't canonicalize; wait until login provides one.
        if (!userId)
            return;
        if (cm.getTelemetryIdentifiedUserId() === userId)
            return;
        try {
            const anonymousId = cm.getAnonymousId();
            // Merge pre-login anonymous events into the canonical person.
            this.posthog.alias({
                distinctId: userId,
                alias: anonymousId,
            });
            // Merge any historical email-keyed person into the canonical person.
            if (email) {
                this.posthog.alias({
                    distinctId: userId,
                    alias: email,
                });
            }
            this.posthog.identify({
                distinctId: userId,
                properties: {
                    ...(email ? { email } : {}),
                    rivet_version: telemetry_1.RIVET_VERSION,
                },
            });
            cm.setTelemetryIdentifiedUserId(userId);
            log.debug(`Identified user in PostHog: ${userId}`);
        }
        catch (error) {
            log.debug('Failed to identify user:', error);
        }
    }
    /**
     * Track an event with properties
     */
    track(event, properties = {}) {
        if (!this.isEnabled || !this.posthog)
            return;
        try {
            const source = properties.source ?? this.defaultSource;
            const enrichedProperties = {
                ...properties,
                source,
                ...(this.editor ? { mcp_editor: mcpEditorEventValue(this.editor) } : {}),
                rivet_version: telemetry_1.RIVET_VERSION,
                env: process.env.NODE_ENV || 'development',
                timestamp: new Date().toISOString(),
                platform: process.platform,
                node_version: process.version,
            };
            this.posthog.capture({
                distinctId: this.distinctId,
                event,
                properties: enrichedProperties,
            });
            const isMCP = source === 'mcp' ||
                event.startsWith('mcp_') ||
                event === 'changes_queued';
            if (isMCP) {
                log.info(`Telemetry: sent ${event}`);
            }
            else {
                log.debug(`Tracked event: ${event}`, enrichedProperties);
            }
        }
        catch (error) {
            log.warn(`Telemetry failed to send event "${event}":`, error);
        }
    }
    /**
     * Track CLI session start
     */
    trackSessionStart(options) {
        this.track('cli_session_start', {
            framework: options.framework,
            port: options.port,
            user_port: options.userPort,
            debug_mode: options.debugMode,
        });
    }
    /**
     * Track code modification request - NO CODE CONTENT, just metadata
     */
    trackCodeModification(data) {
        this.track('code_modification', {
            success: data.success,
            instruction: data.instruction, // User prompt is safe to capture
            instruction_length: data.instructionLength,
            element_count: data.elementCount,
            file_count: data.fileCount,
            error_type: data.errorType,
            modification_time_ms: data.modificationTimeMs,
        });
    }
    /**
     * Track agentic code modification request
     */
    trackAgentModification(data) {
        this.track('agent_modification', {
            success: data.success,
            instruction: data.instruction,
            instruction_length: data.instructionLength,
            element_count: data.elementCount,
            file_count: data.fileCount,
            error_type: data.errorType,
            modification_time_ms: data.modificationTimeMs,
            model: data.model,
            session_id: data.sessionId,
            time_to_first_message_ms: data.ttfmMs,
            trace_id: data.traceId,
            agent_run_id: data.agentRunId,
            posthog_session_id: data.posthogSessionId,
        });
    }
    /**
     * Track the start of a desktop agent run with correlation identifiers.
     */
    trackAgentRunStarted(data) {
        this.track('agent_run_started', {
            trace_id: data.traceId,
            agent_run_id: data.agentRunId,
            posthog_session_id: data.posthogSessionId,
            resume_session_id: data.resumeSessionId,
            instruction_length: data.instructionLength,
            element_count: data.elementCount,
            model: data.model,
            source: data.source,
        });
    }
    /**
     * Track successful completion of a desktop agent run.
     */
    trackAgentRunCompleted(data) {
        this.track('agent_run_completed', {
            trace_id: data.traceId,
            agent_run_id: data.agentRunId,
            session_id: data.sessionId,
            posthog_session_id: data.posthogSessionId,
            model: data.model,
            duration_ms: data.durationMs,
            time_to_first_message_ms: data.ttfmMs,
            time_to_first_write_ms: data.ttfwMs,
            ...(data.fileCount !== undefined ? { file_count: data.fileCount } : {}),
            tool_call_counts: data.toolSummary?.toolCallCounts,
            read_targets: data.toolSummary?.readTargets,
            edit_targets: data.toolSummary?.editTargets,
            write_targets: data.toolSummary?.writeTargets,
            source: data.source,
        });
    }
    /**
     * Track failed desktop agent runs for incident debugging.
     */
    trackAgentRunFailed(data) {
        this.track('agent_run_failed', {
            trace_id: data.traceId,
            agent_run_id: data.agentRunId,
            session_id: data.sessionId,
            posthog_session_id: data.posthogSessionId,
            model: data.model,
            duration_ms: data.durationMs,
            error_type: data.errorType,
            error_message: data.errorMessage,
            time_to_first_message_ms: data.ttfmMs,
            time_to_first_write_ms: data.ttfwMs,
            tool_call_counts: data.toolSummary?.toolCallCounts,
            read_targets: data.toolSummary?.readTargets,
            edit_targets: data.toolSummary?.editTargets,
            write_targets: data.toolSummary?.writeTargets,
            source: data.source,
        });
    }
    /**
     * Track agent abort events with enough context to distinguish inactivity timeouts,
     * explicit user cancels, and unexpected process exits.
     */
    trackAgentAborted(data) {
        this.track('agent_aborted', {
            trace_id: data.traceId,
            agent_run_id: data.agentRunId,
            session_id: data.sessionId,
            posthog_session_id: data.posthogSessionId,
            model: data.model,
            abort_reason: data.abortReason,
            last_tool_name: data.lastToolName,
            last_tool_ms: data.lastToolMs,
            elapsed_ms: data.elapsedMs,
            input_tokens: data.inputTokens,
            source: data.source,
        });
    }
    /**
     * Track component search
     */
    trackComponentSearch(data) {
        this.track('component_search', {
            success: data.success,
            result_count: data.resultCount,
            search_time_ms: data.searchTimeMs,
        });
    }
    /**
     * Track git operations
     */
    trackGitOperation(data) {
        this.track('git_operation', {
            operation: data.operation,
            success: data.success,
            error_type: data.errorType,
        });
    }
    /**
     * Track errors
     */
    trackError(data) {
        this.track('error', {
            error_type: data.errorType,
            context: data.context,
            framework: data.framework,
        });
    }
    /**
     * Capture an exception with full stack trace for PostHog Error Tracking
     */
    captureException(error, context) {
        if (!this.isEnabled || !this.posthog)
            return;
        try {
            this.posthog.captureException(error, this.distinctId, {
                context,
                source: this.defaultSource,
                rivet_version: telemetry_1.RIVET_VERSION,
                platform: process.platform,
                node_version: process.version,
            });
            log.debug(`Captured exception in context: ${context}`);
        }
        catch (captureError) {
            log.debug('Failed to capture exception:', captureError);
        }
    }
    /**
     * Track element selection patterns
     */
    trackElementSelection(data) {
        this.track('element_selection', {
            method: data.method,
            element_type: data.elementType,
            framework: data.framework,
        });
    }
    buildTryoutContextProperties(data) {
        const properties = {
            source: 'demo',
        };
        if (data.demoSessionId) {
            properties.demo_session_id = data.demoSessionId;
        }
        if (data.deploymentEnv) {
            properties.deployment_env = data.deploymentEnv;
        }
        if (data.templateProject) {
            properties.template_project = data.templateProject;
        }
        if (data.processRole) {
            properties.process_role = data.processRole;
        }
        if (data.posthogSessionId) {
            properties.posthog_session_id = data.posthogSessionId;
        }
        if (data.browserDistinctId) {
            properties.browser_distinct_id = data.browserDistinctId;
        }
        return properties;
    }
    trackTryoutSessionProvisionStarted(data) {
        this.track('demo_session_provision_started', {
            is_authenticated_request: data.isAuthenticatedRequest,
            require_signed_in_users: data.requireSignedInUsers,
            ...this.buildTryoutContextProperties({
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutSessionProvisionCompleted(data) {
        this.track('demo_session_provision_completed', {
            time_to_ready_ms: data.timeToReadyMs,
            active_sessions_after: data.activeSessionsAfter,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutSessionProvisionFailed(data) {
        this.track('demo_session_provision_failed', {
            error_type: data.errorType,
            status_code: data.statusCode,
            time_to_failure_ms: data.timeToFailureMs,
            ...this.buildTryoutContextProperties({
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutSessionCapacityRejected(data) {
        this.track('demo_session_capacity_rejected', {
            active_sessions: data.activeSessions,
            max_active_sessions: data.maxActiveSessions,
            ...this.buildTryoutContextProperties({
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutSessionMetadataRequested(data) {
        this.track('demo_session_metadata_requested', {
            found: data.found,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutSessionExpiredCleaned(data) {
        this.track('demo_session_expired_cleaned', {
            cleanup_duration_ms: data.cleanupDurationMs,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutSessionCleanupFailed(data) {
        this.track('demo_session_cleanup_failed', {
            error_type: data.errorType,
            stage: data.stage,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutRuntimeStarted(data) {
        this.track('demo_runtime_started', {
            rivet_port: data.rivetPort,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'session_runtime',
            }),
        });
    }
    trackTryoutRuntimeShutdown(data) {
        this.track('demo_runtime_shutdown', {
            signal: data.signal,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                processRole: 'session_runtime',
            }),
        });
    }
    trackTryoutRuntimeStoppedIdle(data) {
        this.track('demo_runtime_stopped_idle', {
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutRuntimeRehydrationStarted(data) {
        this.track('demo_runtime_rehydration_started', {
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutRuntimeRehydrationCompleted(data) {
        this.track('demo_runtime_rehydration_completed', {
            time_to_ready_ms: data.timeToReadyMs,
            rivet_port: data.rivetPort,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutRuntimeRehydrationFailed(data) {
        this.track('demo_runtime_rehydration_failed', {
            error_type: data.errorType,
            time_to_failure_ms: data.timeToFailureMs,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                templateProject: data.templateProject,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutAuthStoreCompleted(data) {
        this.track('demo_auth_store_completed', {
            has_refresh_token: data.hasRefreshToken,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutAuthStoreFailed(data) {
        this.track('demo_auth_store_failed', {
            reason: data.reason,
            status_code: data.statusCode,
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                processRole: 'orchestrator',
            }),
        });
    }
    trackTryoutProxySessionMissing(data) {
        this.track('demo_proxy_session_missing', {
            ...this.buildTryoutContextProperties({
                demoSessionId: data.demoSessionId,
                deploymentEnv: data.deploymentEnv,
                processRole: 'orchestrator',
            }),
        });
    }
    /**
     * Build shared MCP correlation properties for event capture.
     */
    buildMCPCorrelationProperties(data) {
        const correlation = {};
        if (data.sessionId) {
            correlation.session_id = data.sessionId;
        }
        if (data.traceId) {
            correlation.trace_id = data.traceId;
        }
        if (data.agentRunId) {
            correlation.agent_run_id = data.agentRunId;
        }
        if (data.browserSessionId) {
            correlation.$session_id = data.browserSessionId;
        }
        if (data.browserDistinctId) {
            correlation.browser_distinct_id = data.browserDistinctId;
        }
        return correlation;
    }
    /**
     * Track MCP session start (includes `mcp_editor` for PostHog breakdowns: cursor / codex / claude / other).
     */
    trackMCPSessionStart(data) {
        this.track('mcp_session_started', {
            framework: data.framework,
            dev_server_started: data.devServerStarted,
            mcp_editor: mcpEditorEventValue(data.mcpEditor),
            ...this.buildMCPCorrelationProperties(data),
            source: 'mcp',
        });
    }
    /**
     * Track changes queued (agent received pending changes)
     */
    trackChangesQueued(data) {
        this.track('changes_queued', {
            style_change_count: data.styleChangeCount,
            text_change_count: data.textChangeCount,
            comment_count: data.commentCount,
            chat_count: data.chatCount,
            round: data.round,
            ...this.buildMCPCorrelationProperties(data),
            source: 'mcp',
        });
    }
    /**
     * Track MCP session end
     */
    trackMCPSessionEnd(data) {
        this.track('mcp_session_ended', {
            rounds: data.rounds,
            duration_ms: data.durationMs,
            ...this.buildMCPCorrelationProperties(data),
            source: 'mcp',
        });
    }
    /**
     * Track when the user clicks "Send to Claude" and changes are queued (before the agent picks them up).
     * Compare with changes_queued (agent received) to detect "sent but not picked up".
     */
    trackMCPChangesSent(data) {
        this.track('mcp_changes_sent', {
            style_change_count: data.styleChangeCount,
            text_change_count: data.textChangeCount,
            comment_count: data.commentCount,
            chat_count: data.chatCount,
            round: data.round,
            ...this.buildMCPCorrelationProperties(data),
            source: 'mcp',
        });
    }
    /**
     * Track the start of background scaffold + npm install for an agent-
     * variants fresh-project session.
     */
    trackAgentVariantsScaffoldStarted(data) {
        this.track('agent_variants.scaffold_started', {
            session_id: data.sessionId,
            variant_count: data.variantCount,
            design_context: data.designContext ?? null,
            source: 'mcp',
        });
    }
    /**
     * Track successful completion of background scaffold + install.
     */
    trackAgentVariantsScaffoldCompleted(data) {
        this.track('agent_variants.scaffold_completed', {
            session_id: data.sessionId,
            duration_ms: data.durationMs,
            install_duration_ms: data.installDurationMs,
            variant_count: data.variantCount,
            source: 'mcp',
        });
    }
    /**
     * Track failure of background scaffold + install.
     */
    trackAgentVariantsScaffoldFailed(data) {
        this.track('agent_variants.scaffold_failed', {
            session_id: data.sessionId,
            error_code: data.errorCode,
            duration_ms: data.durationMs,
            source: 'mcp',
        });
    }
    /**
     * Track the ranked design-system list chosen for a fresh-project session.
     */
    trackAgentVariantsFreshDesignSystemsRanked(data) {
        this.track('agent_variants.fresh_design_systems_ranked', {
            session_id: data.sessionId,
            entries: data.entries,
            count: data.count,
            source: 'mcp',
        });
    }
    /**
     * Track the per-slot design-system pin chosen for a fresh-project session.
     */
    trackAgentVariantsFreshDesignSystemsPinned(data) {
        this.track('agent_variants.fresh_design_systems_pinned', {
            session_id: data.sessionId,
            slot: data.slot,
            kind: data.kind,
            slug: data.slug,
            markdown_label: data.markdownLabel,
            source_mode: data.sourceMode,
            source: 'mcp',
        });
    }
    /**
     * Track a fresh-variant dev server reaching ready state.
     */
    trackAgentVariantsFreshDevServerStarted(data) {
        this.track('agent_variants.fresh_dev_server_started', {
            session_id: data.sessionId,
            variant_id: data.variantId,
            port: data.port,
            source: 'mcp',
        });
    }
    /**
     * Track a fresh-variant dev server failing to come up.
     */
    trackAgentVariantsFreshDevServerFailed(data) {
        this.track('agent_variants.fresh_dev_server_failed', {
            session_id: data.sessionId,
            variant_id: data.variantId,
            error_code: data.errorCode,
            source: 'mcp',
        });
    }
    /**
     * Track materialize of a fresh-project pick into its user-facing
     * destination after commit_variant.
     */
    trackAgentVariantsNewProjectMaterialized(data) {
        this.track('agent_variants.new_project_materialized', {
            session_id: data.sessionId,
            variant_id: data.variantId,
            destination_path_hash: this.hashTelemetryValue(data.destinationPath),
            changed_files_count: data.changedFilesCount,
            duration_ms: data.durationMs,
            source: 'mcp',
        });
    }
    trackAgentVariantsSourceContextQuality(data) {
        this.track('agent_variants.source_context_quality', {
            session_id: data.sessionId,
            source_url_count: data.sourceUrlCount,
            source_artifact_count: data.artifactCount,
            has_screenshot_references: data.hasScreenshotReferences,
            preserve_brand: data.preserveBrand,
            source: 'mcp',
        });
    }
    trackAgentVariantsBriefQuality(data) {
        this.track('agent_variants.brief_quality', {
            session_id: data.sessionId,
            brief_count: data.briefCount,
            evidence_backed_count: data.evidenceBackedCount,
            short_brief_count: data.shortBriefCount,
            source: 'mcp',
        });
    }
    trackAgentVariantsRefinePass(data) {
        this.track('agent_variants.refine_pass', {
            session_id: data.sessionId,
            variant_id: data.variantId,
            refine_status: data.status,
            source: 'mcp',
        });
    }
    trackAgentVariantsActiveProjectTransition(data) {
        this.track('agent_variants.active_project_transition', {
            session_id: data.sessionId,
            success: data.success,
            reason_code: data.reasonCode,
            destination_path_hash: data.destinationPath
                ? this.hashTelemetryValue(data.destinationPath)
                : null,
            source: 'mcp',
        });
    }
    /**
     * Track a variant-request batch received via /api/mcp/queue-changes.
     * Variant-request batches do NOT start an apply run, so the normal
     * `mcp_changes_sent` / `changes_queued` / `agent_run_started` chain is
     * suppressed; this event takes its place at intake.
     */
    trackCommentVariantRequestReceived(data) {
        this.track('comment_variant_request_received', {
            requested_count: data.requestedCount,
            ...this.buildMCPCorrelationProperties(data),
            source: 'mcp',
        });
    }
    /**
     * Flush pending events without tearing down the client.
     * Safe to call between sessions when the process stays alive.
     */
    async flush() {
        if (this.posthog) {
            try {
                await this.posthog.flush();
                log.debug('Telemetry flush complete');
            }
            catch (error) {
                log.debug('Error during telemetry flush:', error);
            }
        }
    }
    /**
     * Flush any pending events and tear down the client.
     * Call once before the process exits.
     */
    async shutdown() {
        if (this.posthog) {
            const client = this.posthog;
            this.posthog = null;
            try {
                await client.shutdown();
                log.debug('Telemetry shutdown complete');
            }
            catch (error) {
                log.debug('Error during telemetry shutdown:', error);
            }
        }
    }
}
exports.TelemetryService = TelemetryService;
// Default telemetry instance is now instantiated where needed
//# sourceMappingURL=TelemetryService.js.map