diff --git a/mem0-ts/src/client/mem0.types.ts b/mem0-ts/src/client/mem0.types.ts index 185b1dbea..ba778415d 100644 --- a/mem0-ts/src/client/mem0.types.ts +++ b/mem0-ts/src/client/mem0.types.ts @@ -169,7 +169,9 @@ export interface PaginatedMemories { export interface ProjectResponse { customInstructions?: string; - customCategories?: string[]; + // The API returns category objects (`[{ "": "" }]`), + // not bare strings (see issue #5738). + customCategories?: custom_categories[]; [key: string]: any; } diff --git a/mem0-ts/src/client/tests/utils.test.ts b/mem0-ts/src/client/tests/utils.test.ts index 9007a6b87..d76385845 100644 --- a/mem0-ts/src/client/tests/utils.test.ts +++ b/mem0-ts/src/client/tests/utils.test.ts @@ -99,4 +99,50 @@ describe("camelToSnakeKeys / snakeToCamelKeys", () => { }); }); }); + + describe("user-controlled customCategories names (issue #5738)", () => { + it("converts the outer key but leaves multi-word category names on write", () => { + expect( + camelToSnakeKeys({ + customCategories: [ + { work_life_balance: "desc" }, + { AIResearch: "desc" }, + ], + }), + ).toEqual({ + // outer SDK key is snake_cased, user-defined category names are not + custom_categories: [ + { work_life_balance: "desc" }, + { AIResearch: "desc" }, + ], + }); + }); + + it("converts the outer key but leaves category names verbatim on read", () => { + expect( + snakeToCamelKeys({ + custom_categories: [ + { work_life_balance: "desc" }, + { AIResearch: "desc" }, + ], + }), + ).toEqual({ + customCategories: [ + { work_life_balance: "desc" }, + { AIResearch: "desc" }, + ], + }); + }); + + it("round-trips category names losslessly (write then read)", () => { + const customCategories = [ + { work_life_balance: "balance between work and life" }, + { AIResearch: "artificial intelligence research" }, + ]; + const roundTripped = snakeToCamelKeys( + camelToSnakeKeys({ customCategories }), + ); + expect(roundTripped.customCategories).toEqual(customCategories); + }); + }); }); diff --git a/mem0-ts/src/client/utils.ts b/mem0-ts/src/client/utils.ts index 817dd02cf..aca9ffbcd 100644 --- a/mem0-ts/src/client/utils.ts +++ b/mem0-ts/src/client/utils.ts @@ -29,6 +29,11 @@ const OPAQUE_VALUE_KEYS = new Set([ "metadata", "structuredDataSchema", "structured_data_schema", + // Custom-category names are user-controlled keys (`[{ "": "" }]`). + // Listed in both casings so they round-trip verbatim in both directions + // (see issue #5738; same class as `metadata`/`structuredDataSchema`). + "customCategories", + "custom_categories", ]); /**