{"version":3,"file":"feature-telemetry-CKMYBeaO.cjs","names":["PostHog","z"],"sources":["../src/telemetry/posthog.ts","../src/telemetry/context.ts","../src/telemetry/feature-telemetry.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport os from 'node:os';\nimport { PostHog } from 'posthog-node';\n\nconst POSTHOG_API_KEY = 'phc_SBLpZVAB6jmHOct9CABq3PF0Yn5FU3G2FgT4xUr2XrT';\nconst POSTHOG_HOST = 'https://us.posthog.com';\nconst TRUTHY_DISABLED_VALUES = new Set(['1', 'true', 'yes']);\n\nlet client: PostHog | null = null;\n\nexport type EEEventName = 'ee_license_check' | 'ee_feature_used';\n\nexport type TelemetryEventName = EEEventName | 'mastra_model_token_usage' | 'mastra_feature_usage';\n\nexport function isTelemetryEnabled(): boolean {\n  const value = process.env['MASTRA_TELEMETRY_DISABLED'];\n  if (!value) {\n    return true;\n  }\n  return !TRUTHY_DISABLED_VALUES.has(value.trim().toLowerCase());\n}\n\nexport function hashTelemetryValue(value: string): string {\n  return createHash('sha256').update(value).digest('hex');\n}\n\nfunction getHashedHostname(): string {\n  return hashTelemetryValue(os.hostname() || 'unknown-host').slice(0, 16);\n}\n\nexport function getEETelemetryFallbackDistinctId(): string {\n  return `mastra-${getHashedHostname()}`;\n}\n\nfunction getClient(): PostHog | null {\n  if (!isTelemetryEnabled()) {\n    return null;\n  }\n\n  if (!client) {\n    client = new PostHog(POSTHOG_API_KEY, {\n      host: POSTHOG_HOST,\n      flushAt: 1,\n      flushInterval: 0,\n      disableGeoip: false,\n    });\n  }\n\n  return client;\n}\n\nfunction getSystemProperties(): Record<string, unknown> {\n  return {\n    os: process.platform,\n    os_version: os.release(),\n    node_version: process.version,\n    platform: process.arch,\n    machine_id: getHashedHostname(),\n    mastra_version: process.env['npm_package_version'] || 'unknown',\n  };\n}\n\nexport function captureTelemetryEvent(\n  event: TelemetryEventName,\n  distinctId: string | undefined,\n  properties?: Record<string, unknown>,\n): void {\n  try {\n    const posthog = getClient();\n    if (!posthog) {\n      return;\n    }\n\n    posthog.capture({\n      distinctId: distinctId || getEETelemetryFallbackDistinctId(),\n      event,\n      properties: {\n        ...getSystemProperties(),\n        ...properties,\n      },\n    });\n  } catch {\n    // Telemetry must never affect auth or EE feature behavior.\n  }\n}\n\nexport function captureEEEvent(\n  event: EEEventName,\n  distinctId: string | undefined,\n  properties?: Record<string, unknown>,\n): void {\n  captureTelemetryEvent(event, distinctId, properties);\n}\n\nexport function resetEETelemetryForTests(): void {\n  client = null;\n}\n","import { execFile } from 'node:child_process';\nimport { z } from 'zod/v4';\nimport { hashTelemetryValue } from './posthog';\n\nexport interface ServerTelemetryContext {\n  projectId: string;\n  projectId2: string | undefined;\n  distinctId: string | undefined;\n  command: string;\n  nodeEnv: string;\n}\n\nconst platformProjectIdSchema = z.uuid();\nlet cachedGitProjectId2: Promise<string | undefined> | undefined;\n\nfunction normalizeGitRemote(remote: string): string | undefined {\n  try {\n    // Local paths have no cross-machine repository identity.\n    if (/^(?:[a-z]:[\\\\/]|file:)/i.test(remote)) return undefined;\n\n    const scpRemote = /^(?:[^/@:\\s]+@)?(\\[[^\\]]+\\]|[^/:\\s]+):(.+)$/.exec(remote);\n    const url = new URL(!remote.includes('://') && scpRemote ? `ssh://${scpRemote[1]}/${scpRemote[2]}` : remote);\n    if (!['https:', 'http:', 'ssh:', 'git:', 'git+ssh:'].includes(url.protocol) || !url.hostname) {\n      return undefined;\n    }\n\n    const repositoryPath = url.pathname.replace(/^\\/+|\\/+$/g, '').replace(/\\.git$/, '');\n    return repositoryPath ? `${url.hostname.toLowerCase()}/${repositoryPath}` : undefined;\n  } catch {\n    return undefined;\n  }\n}\n\nasync function computeGitProjectId2(): Promise<string | undefined> {\n  try {\n    const remote = await new Promise<string>((resolve, reject) => {\n      execFile(\n        'git',\n        ['remote', 'get-url', 'origin'],\n        {\n          cwd: process.env.MASTRA_PROJECT_ROOT || process.cwd(),\n          encoding: 'utf-8',\n          timeout: 2000,\n          maxBuffer: 4096,\n        },\n        (error, stdout) => {\n          if (error) reject(error);\n          else resolve(stdout);\n        },\n      );\n    });\n    const normalizedRemote = normalizeGitRemote(remote.trim());\n    return normalizedRemote ? hashTelemetryValue(normalizedRemote).slice(0, 16) : undefined;\n  } catch {\n    // Missing git, an unavailable origin, or a timeout means no secondary id.\n    return undefined;\n  }\n}\n\n/**\n * Preserves UUID-shaped Platform project IDs for direct telemetry lookup.\n * Other values fall back to a hash of the normalized Git origin, if available.\n */\nasync function resolveProjectId2(): Promise<string | undefined> {\n  const platformProjectId = platformProjectIdSchema.safeParse(process.env.MASTRA_PROJECT_ID?.trim());\n  if (platformProjectId.success) {\n    return `mp_${platformProjectId.data}`;\n  }\n  cachedGitProjectId2 ??= computeGitProjectId2();\n  return cachedGitProjectId2;\n}\n\nexport async function getServerTelemetryContext(): Promise<ServerTelemetryContext> {\n  return {\n    projectId: hashTelemetryValue(process.env.MASTRA_PROJECT_ROOT || process.cwd()).slice(0, 16),\n    distinctId: process.env.MASTRA_CLI_DISTINCT_ID || undefined,\n    command: process.env.MASTRA_TELEMETRY_COMMAND || 'server',\n    nodeEnv: process.env.NODE_ENV || 'development',\n    projectId2: await resolveProjectId2(),\n  };\n}\n\nexport function resetProjectId2CacheForTests(): void {\n  cachedGitProjectId2 = undefined;\n}\n","import type { Mastra } from '../mastra';\nimport { getServerTelemetryContext } from './context';\nimport { captureTelemetryEvent, isTelemetryEnabled } from './posthog';\n\nexport const FEATURE_USAGE_EVENT = 'mastra_feature_usage';\n\ntype StorageLike = {\n  constructor?: { name?: string };\n  stores?: { observability?: unknown };\n};\n\ntype AgentLike = {\n  hasOwnMemory?: () => boolean;\n};\n\nfunction countCollection(collection: unknown): number {\n  if (!collection || typeof collection !== 'object') {\n    return 0;\n  }\n  if (collection instanceof Map || collection instanceof Set) {\n    return collection.size;\n  }\n\n  return Object.keys(collection).length;\n}\n\nfunction countAgentsWithMemory(agents: unknown): number {\n  if (!agents || typeof agents !== 'object') {\n    return 0;\n  }\n\n  return Object.values(agents).filter(agent => {\n    try {\n      return (agent as AgentLike | undefined)?.hasOwnMemory?.() === true;\n    } catch {\n      return false;\n    }\n  }).length;\n}\n\nfunction bucketStorageType(storage: StorageLike | undefined): string | null {\n  if (!storage) {\n    return null;\n  }\n\n  const constructorName = storage.constructor?.name?.toLowerCase();\n  if (!constructorName) {\n    return 'unknown';\n  }\n\n  if (constructorName.includes('memory')) {\n    return 'in-memory';\n  }\n  if (constructorName.includes('libsql')) {\n    return 'libsql';\n  }\n  if (constructorName.includes('postgres')) {\n    return 'postgres';\n  }\n  if (constructorName.includes('mongo')) {\n    return 'mongo';\n  }\n  if (constructorName.includes('upstash')) {\n    return 'upstash';\n  }\n  if (constructorName.includes('dynamodb')) {\n    return 'dynamodb';\n  }\n  if (constructorName.includes('redis')) {\n    return 'redis';\n  }\n\n  return 'unknown';\n}\n\nexport function trackFeatureUsage(name: string, metadata?: Record<string, unknown>): void {\n  try {\n    if (!isTelemetryEnabled()) {\n      return;\n    }\n\n    // Metadata is spread first so it can never override telemetry-controlled\n    // fields. project_id2 is stripped explicitly: unlike the always-set fields\n    // below, it is only emitted when an identifier actually resolved, so a\n    // caller-supplied value would otherwise leak through in the omitted case.\n    const safeMetadata = { ...metadata };\n    delete safeMetadata.project_id2;\n    void getServerTelemetryContext()\n      .then(({ projectId, projectId2, distinctId, command, nodeEnv }) => {\n        captureTelemetryEvent(FEATURE_USAGE_EVENT, distinctId, {\n          ...safeMetadata,\n          feature_name: name,\n          project_id: projectId,\n          ...(projectId2 ? { project_id2: projectId2 } : {}),\n          command,\n          node_env: nodeEnv,\n        });\n      })\n      .catch(() => {\n        // Async discovery must not affect server startup or runtime behavior.\n      });\n  } catch {\n    // Feature telemetry must never affect server startup or runtime behavior.\n  }\n}\n\nexport function syncFeatureUsageTelemetry(mastra: Mastra): void {\n  try {\n    if (!isTelemetryEnabled()) {\n      return;\n    }\n\n    const agents = mastra.listAgents?.();\n    const agentsWithMemoryCount = countAgentsWithMemory(agents);\n    const memory = mastra.listMemory?.();\n    const workspaces = mastra.listWorkspaces?.();\n    const tts = mastra.getTTS?.();\n    const promptBlocks = mastra.listPromptBlocks?.();\n    const processorConfigurations = mastra.listProcessorConfigurations?.();\n    const agentChannels = mastra.getChannels?.();\n    const storage = mastra.getStorage?.() as StorageLike | undefined;\n\n    trackFeatureUsage('mastra_instance_summary', {\n      agent_count: countCollection(agents),\n      agents_with_memory_count: agentsWithMemoryCount,\n      agent_controller_count: countCollection(mastra.listAgentControllers?.()),\n      workflow_count: countCollection(mastra.listWorkflows?.()),\n      tool_count: countCollection(mastra.listTools?.()),\n      processor_count: countCollection(mastra.listProcessors?.()),\n      processor_configuration_count: countCollection(processorConfigurations),\n      memory_count: countCollection(memory),\n      vector_count: countCollection(mastra.listVectors?.()),\n      scorer_count: countCollection(mastra.listScorers?.()),\n      workspace_count: countCollection(workspaces),\n      mcp_server_count: countCollection(mastra.listMCPServers?.()),\n      gateway_count: countCollection(mastra.listGateways?.()),\n      channel_count: countCollection(mastra.getChannelProviders?.()),\n      agent_channel_count: countCollection(agentChannels),\n      tts_count: countCollection(tts),\n      prompt_block_count: countCollection(promptBlocks),\n      editor_enabled: !!mastra.getEditor?.(),\n      studio_enabled: !!mastra.getStudio?.(),\n      server_middleware_enabled: !!mastra.getServerMiddleware?.(),\n      storage_type: bucketStorageType(storage),\n      observability_enabled: !!storage?.stores?.observability,\n    });\n  } catch {\n    // Feature telemetry must never affect server startup or runtime behavior.\n  }\n}\n"],"mappings":"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"}