f34e42eef3
MemoryClient init fired PostHog $identify for anon ids the SDKs had minted themselves (Python: setup_config() at import time; TS: getOrCreateMem0UserId() inside the alias path), so ~90% of stitches merged event-less anon persons into platform users, worst in ephemeral containers. - never create the anon id from platform client paths; Python mints lazily in Memory/AsyncMemory init, gated on MEM0_TELEMETRY - record telemetry.oss_used_at when OSS Memory genuinely initializes (both SDKs, shared ~/.mem0/config.json key) and only stitch the oss user_id when the marker is present; cli anon id stays presence-based - stamp client_version on $identify so fixed-SDK stitches are separable from old-SDK noise in PostHog
155 lines
3.9 KiB
TypeScript
155 lines
3.9 KiB
TypeScript
// @ts-nocheck
|
|
import type { TelemetryClient, TelemetryOptions } from "./telemetry.types";
|
|
|
|
// __MEM0_SDK_VERSION__ is inlined by tsup/esbuild's `define` at build time from
|
|
// package.json. In unbundled environments (ts-jest, jest globalSetup) the
|
|
// identifier is not defined, so guard with typeof to fall back safely.
|
|
let version =
|
|
typeof __MEM0_SDK_VERSION__ !== "undefined" ? __MEM0_SDK_VERSION__ : "dev";
|
|
|
|
// Safely check for process.env in different environments
|
|
let MEM0_TELEMETRY = true;
|
|
try {
|
|
MEM0_TELEMETRY = process?.env?.MEM0_TELEMETRY === "false" ? false : true;
|
|
} catch (error) {}
|
|
const POSTHOG_API_KEY = "phc_hgJkUVJFYtmaJqrvf6CYN67TIQ8yhXAkWzUn9AMU4yX";
|
|
const POSTHOG_HOST = "https://us.i.posthog.com/i/v0/e/";
|
|
|
|
// Simple hash function using random strings
|
|
function generateHash(input: string): string {
|
|
const randomStr =
|
|
Math.random().toString(36).substring(2, 15) +
|
|
Math.random().toString(36).substring(2, 15);
|
|
return randomStr;
|
|
}
|
|
|
|
class UnifiedTelemetry implements TelemetryClient {
|
|
private apiKey: string;
|
|
private host: string;
|
|
|
|
constructor(projectApiKey: string, host: string) {
|
|
this.apiKey = projectApiKey;
|
|
this.host = host;
|
|
}
|
|
|
|
async captureEvent(
|
|
distinctId: string,
|
|
eventName: string,
|
|
properties = {},
|
|
): Promise<boolean> {
|
|
if (!MEM0_TELEMETRY) return false;
|
|
|
|
const eventProperties = {
|
|
client_version: version,
|
|
timestamp: new Date().toISOString(),
|
|
...properties,
|
|
$process_person_profile: false,
|
|
$lib: "posthog-node",
|
|
};
|
|
|
|
const payload = {
|
|
api_key: this.apiKey,
|
|
distinct_id: distinctId,
|
|
event: eventName,
|
|
properties: eventProperties,
|
|
};
|
|
|
|
try {
|
|
const response = await fetch(this.host, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(payload),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
console.error("Telemetry event capture failed:", await response.text());
|
|
return false;
|
|
}
|
|
return true;
|
|
} catch (error) {
|
|
console.error("Telemetry event capture failed:", error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async captureIdentify(anonId: string, email: string): Promise<boolean> {
|
|
if (!MEM0_TELEMETRY) return false;
|
|
if (!anonId || !email || anonId === email) return false;
|
|
|
|
const payload = {
|
|
api_key: this.apiKey,
|
|
distinct_id: email,
|
|
event: "$identify",
|
|
properties: {
|
|
$anon_distinct_id: anonId,
|
|
client_source: "typescript",
|
|
client_version: version,
|
|
$lib: "posthog-node",
|
|
},
|
|
};
|
|
|
|
try {
|
|
const response = await fetch(this.host, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(payload),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
console.error(
|
|
"Telemetry identify capture failed:",
|
|
await response.text(),
|
|
);
|
|
return false;
|
|
}
|
|
return true;
|
|
} catch (error) {
|
|
console.error("Telemetry identify capture failed:", error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async shutdown() {
|
|
// No shutdown needed for direct API calls
|
|
}
|
|
}
|
|
|
|
function isTelemetryEnabled(): boolean {
|
|
return MEM0_TELEMETRY;
|
|
}
|
|
|
|
const telemetry = new UnifiedTelemetry(POSTHOG_API_KEY, POSTHOG_HOST);
|
|
|
|
async function captureClientEvent(
|
|
eventName: string,
|
|
instance: any,
|
|
additionalData = {},
|
|
) {
|
|
if (!instance.telemetryId) {
|
|
console.warn("No telemetry ID found for instance");
|
|
return;
|
|
}
|
|
|
|
const eventData = {
|
|
function: `${instance.constructor.name}`,
|
|
method: eventName,
|
|
api_host: instance.host,
|
|
timestamp: new Date().toISOString(),
|
|
client_version: version,
|
|
keys: additionalData?.keys || [],
|
|
...additionalData,
|
|
};
|
|
|
|
await telemetry.captureEvent(
|
|
instance.telemetryId,
|
|
`client.${eventName}`,
|
|
eventData,
|
|
);
|
|
}
|
|
|
|
export { telemetry, captureClientEvent, generateHash, isTelemetryEnabled };
|