fix(ts-oss): coerce non-string entity ids instead of crashing on trim() (#6263)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
This commit is contained in:
co-authored by
kartik-mem0
parent
c2bc28e589
commit
39551145b8
@@ -126,18 +126,19 @@ function rejectTopLevelEntityParams(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates and normalizes an entity ID.
|
* Validates and normalizes an entity ID.
|
||||||
|
* - Coerces non-string ids (e.g. numeric database keys) to string
|
||||||
* - Trims leading/trailing whitespace
|
* - Trims leading/trailing whitespace
|
||||||
* - Rejects empty or whitespace-only strings
|
* - Rejects empty or whitespace-only strings
|
||||||
* - Rejects strings containing internal whitespace
|
* - Rejects strings containing internal whitespace
|
||||||
* @returns The trimmed entity ID, or undefined if input is undefined
|
* @returns The trimmed entity ID, or undefined if input is undefined/null
|
||||||
* @throws Error if entity ID is invalid
|
* @throws Error if entity ID is invalid
|
||||||
*/
|
*/
|
||||||
function validateAndTrimEntityId(
|
function validateAndTrimEntityId(
|
||||||
value: string | undefined,
|
value: string | number | undefined | null,
|
||||||
name: string,
|
name: string,
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
if (value === undefined) return undefined;
|
if (value == null) return undefined;
|
||||||
const trimmed = value.trim();
|
const trimmed = String(value).trim();
|
||||||
if (trimmed === "") {
|
if (trimmed === "") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Invalid ${name}: cannot be empty or whitespace-only. Provide a valid identifier.`,
|
`Invalid ${name}: cannot be empty or whitespace-only. Provide a valid identifier.`,
|
||||||
|
|||||||
@@ -253,6 +253,34 @@ describe("Memory Input Validation", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("non-string entity ID coercion", () => {
|
||||||
|
it("coerces an integer user_id in getAll filters to its string form", async () => {
|
||||||
|
const listSpy = jest
|
||||||
|
.spyOn((memory as any).vectorStore, "list")
|
||||||
|
.mockResolvedValue([[], 0]);
|
||||||
|
|
||||||
|
await memory.getAll({ filters: { user_id: 42 as any } });
|
||||||
|
|
||||||
|
const passedFilters = listSpy.mock.calls[0][0] as Record<string, any>;
|
||||||
|
expect(passedFilters.user_id).toBe("42");
|
||||||
|
|
||||||
|
listSpy.mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("coerces an integer user_id in search filters to its string form", async () => {
|
||||||
|
const searchSpy = jest
|
||||||
|
.spyOn((memory as any).vectorStore, "search")
|
||||||
|
.mockResolvedValue([]);
|
||||||
|
|
||||||
|
await memory.search("q", { filters: { user_id: 42 as any } });
|
||||||
|
|
||||||
|
const passedFilters = searchSpy.mock.calls[0][2] as Record<string, any>;
|
||||||
|
expect(passedFilters.user_id).toBe("42");
|
||||||
|
|
||||||
|
searchSpy.mockRestore();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("search() filter entity ID validation", () => {
|
describe("search() filter entity ID validation", () => {
|
||||||
it("should throw error when user_id in filters is whitespace-only", async () => {
|
it("should throw error when user_id in filters is whitespace-only", async () => {
|
||||||
await expect(
|
await expect(
|
||||||
|
|||||||
Reference in New Issue
Block a user