From 1033ab227c86053fb71d2fd31551078062f71f5a Mon Sep 17 00:00:00 2001 From: Saket Aryan Date: Sun, 30 Mar 2025 12:49:36 +0530 Subject: [PATCH] Introduce Ping in Mem0 Client (#2472) --- docs/changelog/overview.mdx | 5 ++++ mem0-ts/package.json | 2 +- mem0-ts/src/client/mem0.ts | 53 ++++++++++++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/docs/changelog/overview.mdx b/docs/changelog/overview.mdx index 5f93ba38..15243350 100644 --- a/docs/changelog/overview.mdx +++ b/docs/changelog/overview.mdx @@ -56,6 +56,11 @@ mode: "wide" + +**Improvements:** +- **Introuced `ping` method to check if API key is valid and populate org/project id** + + **New Features:** - **Vercel AI SDK Update:** Support threshold and rerank diff --git a/mem0-ts/package.json b/mem0-ts/package.json index 4b47d02c..2b01b782 100644 --- a/mem0-ts/package.json +++ b/mem0-ts/package.json @@ -1,6 +1,6 @@ { "name": "mem0ai", - "version": "2.1.12", + "version": "2.1.13", "description": "The Memory Layer For Your AI Apps", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/mem0-ts/src/client/mem0.ts b/mem0-ts/src/client/mem0.ts index 14fc0c7a..82a4c59f 100644 --- a/mem0-ts/src/client/mem0.ts +++ b/mem0-ts/src/client/mem0.ts @@ -97,7 +97,6 @@ export default class MemoryClient { }); this._validateApiKey(); - this._validateOrgProject(); // Initialize with a temporary ID that will be updated this.telemetryId = ""; @@ -109,12 +108,20 @@ export default class MemoryClient { private async _initializeClient() { try { // Generate telemetry ID - this.telemetryId = generateHash(this.apiKey); + await this.ping(); + + if (!this.telemetryId) { + this.telemetryId = generateHash(this.apiKey); + } + + this._validateOrgProject(); // Capture initialization event - await captureClientEvent("init", this, { + captureClientEvent("init", this, { api_version: "v1", client_type: "MemoryClient", + }).catch((error: any) => { + console.error("Failed to capture event:", error); }); } catch (error: any) { console.error("Failed to initialize client:", error); @@ -171,10 +178,31 @@ export default class MemoryClient { ); } + async ping(): Promise { + const response = await fetch(`${this.host}/v1/ping/`, { + headers: { + Authorization: `Token ${this.apiKey}`, + }, + }); + + const data = await response.json(); + + if (data.status !== "ok") { + throw new Error("API Key is invalid"); + } + + const { org_id, project_id, user_email } = data; + + this.organizationId = org_id || null; + this.projectId = project_id || null; + this.telemetryId = user_email || ""; + } + async add( messages: string | Array, options: MemoryOptions = {}, ): Promise> { + if (this.telemetryId === "") await this.ping(); this._validateOrgProject(); if (this.organizationName != null && this.projectName != null) { options.org_name = this.organizationName; @@ -211,6 +239,7 @@ export default class MemoryClient { } async update(memoryId: string, message: string): Promise> { + if (this.telemetryId === "") await this.ping(); this._validateOrgProject(); const payload = { text: message, @@ -231,6 +260,7 @@ export default class MemoryClient { } async get(memoryId: string): Promise { + if (this.telemetryId === "") await this.ping(); this._captureEvent("get", []); return this._fetchWithErrorHandling( `${this.host}/v1/memories/${memoryId}/`, @@ -241,6 +271,7 @@ export default class MemoryClient { } async getAll(options?: SearchOptions): Promise> { + if (this.telemetryId === "") await this.ping(); this._validateOrgProject(); const payloadKeys = Object.keys(options || {}); this._captureEvent("get_all", [payloadKeys]); @@ -288,6 +319,7 @@ export default class MemoryClient { } async search(query: string, options?: SearchOptions): Promise> { + if (this.telemetryId === "") await this.ping(); this._validateOrgProject(); const payloadKeys = Object.keys(options || {}); this._captureEvent("search", [payloadKeys]); @@ -319,6 +351,7 @@ export default class MemoryClient { } async delete(memoryId: string): Promise<{ message: string }> { + if (this.telemetryId === "") await this.ping(); this._captureEvent("delete", []); return this._fetchWithErrorHandling( `${this.host}/v1/memories/${memoryId}/`, @@ -330,6 +363,7 @@ export default class MemoryClient { } async deleteAll(options: MemoryOptions = {}): Promise<{ message: string }> { + if (this.telemetryId === "") await this.ping(); this._validateOrgProject(); const payloadKeys = Object.keys(options || {}); this._captureEvent("delete_all", [payloadKeys]); @@ -358,6 +392,7 @@ export default class MemoryClient { } async history(memoryId: string): Promise> { + if (this.telemetryId === "") await this.ping(); this._captureEvent("history", []); const response = await this._fetchWithErrorHandling( `${this.host}/v1/memories/${memoryId}/history/`, @@ -369,6 +404,7 @@ export default class MemoryClient { } async users(): Promise { + if (this.telemetryId === "") await this.ping(); this._validateOrgProject(); this._captureEvent("users", []); const options: MemoryOptions = {}; @@ -399,6 +435,7 @@ export default class MemoryClient { entityId: string, entity: { type: string } = { type: "user" }, ): Promise<{ message: string }> { + if (this.telemetryId === "") await this.ping(); this._captureEvent("delete_user", []); const response = await this._fetchWithErrorHandling( `${this.host}/v1/entities/${entity.type}/${entityId}/`, @@ -411,6 +448,7 @@ export default class MemoryClient { } async deleteUsers(): Promise<{ message: string }> { + if (this.telemetryId === "") await this.ping(); this._validateOrgProject(); this._captureEvent("delete_users", []); const entities = await this.users(); @@ -437,6 +475,7 @@ export default class MemoryClient { } async batchUpdate(memories: Array): Promise { + if (this.telemetryId === "") await this.ping(); this._captureEvent("batch_update", []); const memoriesBody = memories.map((memory) => ({ memory_id: memory.memoryId, @@ -454,6 +493,7 @@ export default class MemoryClient { } async batchDelete(memories: Array): Promise { + if (this.telemetryId === "") await this.ping(); this._captureEvent("batch_delete", []); const memoriesBody = memories.map((memory) => ({ memory_id: memory, @@ -470,6 +510,7 @@ export default class MemoryClient { } async getProject(options: ProjectOptions): Promise { + if (this.telemetryId === "") await this.ping(); this._validateOrgProject(); const payloadKeys = Object.keys(options || {}); this._captureEvent("get_project", [payloadKeys]); @@ -496,6 +537,7 @@ export default class MemoryClient { async updateProject( prompts: PromptUpdatePayload, ): Promise> { + if (this.telemetryId === "") await this.ping(); this._validateOrgProject(); this._captureEvent("update_project", []); if (!(this.organizationId && this.projectId)) { @@ -517,6 +559,7 @@ export default class MemoryClient { // WebHooks async getWebhooks(data?: { projectId?: string }): Promise> { + if (this.telemetryId === "") await this.ping(); this._captureEvent("get_webhooks", []); const project_id = data?.projectId || this.projectId; const response = await this._fetchWithErrorHandling( @@ -529,6 +572,7 @@ export default class MemoryClient { } async createWebhook(webhook: WebhookPayload): Promise { + if (this.telemetryId === "") await this.ping(); this._captureEvent("create_webhook", []); const response = await this._fetchWithErrorHandling( `${this.host}/api/v1/webhooks/projects/${this.projectId}/`, @@ -542,6 +586,7 @@ export default class MemoryClient { } async updateWebhook(webhook: WebhookPayload): Promise<{ message: string }> { + if (this.telemetryId === "") await this.ping(); this._captureEvent("update_webhook", []); const project_id = webhook.projectId || this.projectId; const response = await this._fetchWithErrorHandling( @@ -561,6 +606,7 @@ export default class MemoryClient { async deleteWebhook(data: { webhookId: string; }): Promise<{ message: string }> { + if (this.telemetryId === "") await this.ping(); this._captureEvent("delete_webhook", []); const webhook_id = data.webhookId || data; const response = await this._fetchWithErrorHandling( @@ -574,6 +620,7 @@ export default class MemoryClient { } async feedback(data: FeedbackPayload): Promise<{ message: string }> { + if (this.telemetryId === "") await this.ping(); const payloadKeys = Object.keys(data || {}); this._captureEvent("feedback", [payloadKeys]); const response = await this._fetchWithErrorHandling(