( apiKey?: string, baseUrl?: string, )
| 31 | // ── Helpers ────────────────────────────────────────────────────────────── |
| 32 | |
| 33 | async function getBackendAndConfig( |
| 34 | apiKey?: string, |
| 35 | baseUrl?: string, |
| 36 | ): Promise<{ backend: Backend; config: Mem0Config }> { |
| 37 | const config = loadConfig(); |
| 38 | |
| 39 | if (apiKey) config.platform.apiKey = apiKey; |
| 40 | if (baseUrl) config.platform.baseUrl = baseUrl; |
| 41 | |
| 42 | if (!config.platform.apiKey) { |
| 43 | printError( |
| 44 | "No API key configured.", |
| 45 | "Run 'mem0 init' or set MEM0_API_KEY environment variable.", |
| 46 | ); |
| 47 | process.exit(1); |
| 48 | } |
| 49 | |
| 50 | const backend = getBackend(config); |
| 51 | |
| 52 | // Validate the API key upfront with a fast timeout |
| 53 | try { |
| 54 | const pingData = (await Promise.race([ |
| 55 | backend.ping(), |
| 56 | new Promise<never>((_, reject) => |
| 57 | setTimeout(() => reject(new Error("timeout")), 5000), |
| 58 | ), |
| 59 | ])) as Record<string, unknown>; |
| 60 | |
| 61 | const email = pingData?.user_email as string | undefined; |
| 62 | if (email) { |
| 63 | _validatedUserEmail = email; |
| 64 | if (config.platform.userEmail !== email) { |
| 65 | config.platform.userEmail = email; |
| 66 | try { |
| 67 | saveConfig(config); |
| 68 | } catch { |
| 69 | /* ignore */ |
| 70 | } |
| 71 | } |
| 72 | } |
| 73 | } catch (e) { |
| 74 | if (e instanceof AuthError) { |
| 75 | printError( |
| 76 | "Invalid or expired API key.", |
| 77 | "Run 'mem0 init' or set MEM0_API_KEY environment variable.", |
| 78 | ); |
| 79 | process.exit(1); |
| 80 | } |
| 81 | // Network error / timeout — warn but proceed |
| 82 | printWarning( |
| 83 | "Could not validate API key (network issue). Proceeding anyway.", |
| 84 | ); |
| 85 | } |
| 86 | |
| 87 | return { backend, config }; |
| 88 | } |
| 89 | |
| 90 | async function getBackendOnly( |
no test coverage detected