From 133625bbc6d8930024adb684b03fcccc7e5499e0 Mon Sep 17 00:00:00 2001 From: kartik-mem0 Date: Tue, 14 Apr 2026 02:54:21 +0530 Subject: [PATCH] refactor: update MemoryClient to support snake_case filter keys and separate filters --- mem0-ts/src/client/mem0.ts | 19 +++++++++++++++---- .../src/client/tests/integration/crud.test.ts | 6 +++--- .../src/client/tests/integration/helpers.ts | 2 +- .../client/tests/integration/search.test.ts | 6 +++--- .../client/tests/memoryClient.search.test.ts | 8 ++++---- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/mem0-ts/src/client/mem0.ts b/mem0-ts/src/client/mem0.ts index 29c7d6e4a..d4bcc6f98 100644 --- a/mem0-ts/src/client/mem0.ts +++ b/mem0-ts/src/client/mem0.ts @@ -257,10 +257,11 @@ export default class MemoryClient { if (this.telemetryId === "") await this.ping(); const payloadKeys = Object.keys(options || {}); this._captureEvent("get_all", [payloadKeys]); - const { page, pageSize, ...rest } = options ?? {}; + const { page, pageSize, filters, ...rest } = options ?? {}; const body: Record = { output_format: "v1.1", ...camelToSnakeKeys(rest), + ...(filters && { filters }), }; let url = `${this.host}/v2/memories/`; @@ -283,10 +284,12 @@ export default class MemoryClient { if (this.telemetryId === "") await this.ping(); const payloadKeys = Object.keys(options || {}); this._captureEvent("search", [payloadKeys]); + const { filters, ...rest } = options ?? {}; const payload: Record = { query, output_format: "v1.1", - ...camelToSnakeKeys(options ?? {}), + ...camelToSnakeKeys(rest), + ...(filters && { filters }), }; const response = await this._fetchWithErrorHandling( @@ -612,12 +615,16 @@ export default class MemoryClient { throw new Error("Missing filters or schema"); } + const { filters, ...rest } = data; const response = await this._fetchWithErrorHandling( `${this.host}/v1/exports/`, { method: "POST", headers: this.headers, - body: JSON.stringify(camelToSnakeKeys(data)), + body: JSON.stringify({ + ...camelToSnakeKeys(rest), + filters, + }), }, ); @@ -634,12 +641,16 @@ export default class MemoryClient { throw new Error("Missing memoryExportId or filters"); } + const { filters, ...rest } = data; const response = await this._fetchWithErrorHandling( `${this.host}/v1/exports/get/`, { method: "POST", headers: this.headers, - body: JSON.stringify(camelToSnakeKeys(data)), + body: JSON.stringify({ + ...camelToSnakeKeys(rest), + ...(filters && { filters }), + }), }, ); return response; diff --git a/mem0-ts/src/client/tests/integration/crud.test.ts b/mem0-ts/src/client/tests/integration/crud.test.ts index 7003f87d6..78b51edb4 100644 --- a/mem0-ts/src/client/tests/integration/crud.test.ts +++ b/mem0-ts/src/client/tests/integration/crud.test.ts @@ -117,7 +117,7 @@ describeIntegration("MemoryClient Integration — CRUD", () => { describe("get all memories", () => { test("returns all memories for test user", async () => { const memories = await client.getAll({ - filters: { userId: TEST_USER_ID }, + filters: { user_id: TEST_USER_ID }, }); expect(Array.isArray(memories)).toBe(true); @@ -131,7 +131,7 @@ describeIntegration("MemoryClient Integration — CRUD", () => { test("returns paginated results with page and page_size", async () => { const page1 = await client.getAll({ - filters: { userId: TEST_USER_ID }, + filters: { user_id: TEST_USER_ID }, page: 1, pageSize: 1, }); @@ -195,7 +195,7 @@ describeIntegration("MemoryClient Integration — CRUD", () => { test("getAll for non-existent user returns empty array", async () => { const memories = await client.getAll({ - filters: { userId: `nonexistent-user-${randomUUID()}` }, + filters: { user_id: `nonexistent-user-${randomUUID()}` }, }); expect(Array.isArray(memories)).toBe(true); diff --git a/mem0-ts/src/client/tests/integration/helpers.ts b/mem0-ts/src/client/tests/integration/helpers.ts index 8afd9df8d..b08274cac 100644 --- a/mem0-ts/src/client/tests/integration/helpers.ts +++ b/mem0-ts/src/client/tests/integration/helpers.ts @@ -64,7 +64,7 @@ export async function waitForMemories( ): Promise { for (let attempt = 1; attempt <= maxRetries; attempt++) { const memories = await withRetry(() => - client.getAll({ filters: { userId } }), + client.getAll({ filters: { user_id: userId } }), ); if (Array.isArray(memories) && memories.length >= minCount) { return memories; diff --git a/mem0-ts/src/client/tests/integration/search.test.ts b/mem0-ts/src/client/tests/integration/search.test.ts index b326ebb43..a9e2c0104 100644 --- a/mem0-ts/src/client/tests/integration/search.test.ts +++ b/mem0-ts/src/client/tests/integration/search.test.ts @@ -43,7 +43,7 @@ describeIntegration("MemoryClient Integration — Search & History", () => { const results = await waitForSearchResults( client, "What is my favorite color?", - { filters: { userId: TEST_USER_ID } }, + { filters: { user_id: TEST_USER_ID } }, ); expect(Array.isArray(results)).toBe(true); @@ -64,7 +64,7 @@ describeIntegration("MemoryClient Integration — Search & History", () => { client, "What do you know about me?", { - filters: { OR: [{ userId: TEST_USER_ID }] }, + filters: { OR: [{ user_id: TEST_USER_ID }] }, }, ); @@ -120,7 +120,7 @@ describeIntegration("MemoryClient Integration — Search & History", () => { const response = await client.search( "Tell me about integration test user", { - filters: { userId: TEST_USER_ID }, + filters: { user_id: TEST_USER_ID }, topK: 1, }, ); diff --git a/mem0-ts/src/client/tests/memoryClient.search.test.ts b/mem0-ts/src/client/tests/memoryClient.search.test.ts index 4cfe27116..0933faece 100644 --- a/mem0-ts/src/client/tests/memoryClient.search.test.ts +++ b/mem0-ts/src/client/tests/memoryClient.search.test.ts @@ -25,7 +25,7 @@ describe("MemoryClient - search()", () => { const client = new MemoryClient({ apiKey: TEST_API_KEY }); await client.search("What is my name?", { - filters: { userId: "u1" }, + filters: { user_id: "u1" }, }); expect(findFetchCall(mock, "/v3/memories/search/", "POST")).toBeDefined(); @@ -41,7 +41,7 @@ describe("MemoryClient - search()", () => { const client = new MemoryClient({ apiKey: TEST_API_KEY }); await client.search("What is my name?", { - filters: { userId: "u1" }, + filters: { user_id: "u1" }, }); const call = findFetchCall(mock, "/v3/memories/search/", "POST"); @@ -57,7 +57,7 @@ describe("MemoryClient - search()", () => { const mock = setupMockFetch(extra); const client = new MemoryClient({ apiKey: TEST_API_KEY }); - await client.search("test", { filters: { userId: "u1" } }); + await client.search("test", { filters: { user_id: "u1" } }); const call = findFetchCall(mock, "/v3/memories/search/", "POST"); expect(getFetchBody(call!).filters).toEqual({ user_id: "u1" }); @@ -106,7 +106,7 @@ describe("MemoryClient - search()", () => { const client = new MemoryClient({ apiKey: TEST_API_KEY }); const result = await client.search("nonexistent query", { - filters: { userId: "u1" }, + filters: { user_id: "u1" }, }); expect(result.results).toHaveLength(0); });