repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | import { MemoryClient } from "../mem0"; |
| #2 | import dotenv from "dotenv"; |
| #3 | |
| #4 | dotenv.config(); |
| #5 | |
| #6 | const apiKey = process.env.MEM0_API_KEY || ""; |
| #7 | // const client = new MemoryClient({ apiKey, host: 'https://api.mem0.ai', organizationId: "org_gRNd1RrQa4y52iK4tG8o59hXyVbaULikgq4kethC", projectId: "proj_7RfMkWs0PMgXYweGUNKqV9M9mgIRNt5XcupE7mSP" }); |
| #8 | // const client = new MemoryClient({ apiKey, host: 'https://api.mem0.ai', organizationName: "saket-default-org", projectName: "default-project" }); |
| #9 | const client = new MemoryClient({ apiKey, host: "https://api.mem0.ai" }); |
| #10 | |
| #11 | // Generate a random string |
| #12 | const randomString = () => { |
| #13 | return ( |
| #14 | Math.random().toString(36).substring(2, 15) + |
| #15 | Math.random().toString(36).substring(2, 15) |
| #16 | ); |
| #17 | }; |
| #18 | |
| #19 | describe("MemoryClient API", () => { |
| #20 | let userId: string, memoryId: string; |
| #21 | |
| #22 | beforeAll(() => { |
| #23 | userId = randomString(); |
| #24 | }); |
| #25 | |
| #26 | const messages1 = [ |
| #27 | { role: "user", content: "Hey, I am Alex. I'm now a vegetarian." }, |
| #28 | { role: "assistant", content: "Hello Alex! Glad to hear!" }, |
| #29 | ]; |
| #30 | |
| #31 | it("should add messages successfully", async () => { |
| #32 | const res = await client.add(messages1, { user_id: userId || "" }); |
| #33 | |
| #34 | // Validate the response contains an iterable list |
| #35 | expect(Array.isArray(res)).toBe(true); |
| #36 | |
| #37 | // Validate the fields of the first message in the response |
| #38 | const message = res[0]; |
| #39 | expect(typeof message.id).toBe("string"); |
| #40 | expect(typeof message.data?.memory).toBe("string"); |
| #41 | expect(typeof message.event).toBe("string"); |
| #42 | |
| #43 | // Store the memory ID for later use |
| #44 | memoryId = message.id; |
| #45 | }); |
| #46 | |
| #47 | it("should retrieve the specific memory by ID", async () => { |
| #48 | const memory = await client.get(memoryId); |
| #49 | |
| #50 | // Validate that the memory fields have the correct types and values |
| #51 | |
| #52 | // Should be a string (memory id) |
| #53 | expect(typeof memory.id).toBe("string"); |
| #54 | |
| #55 | // Should be a string (the actual memory content) |
| #56 | expect(typeof memory.memory).toBe("string"); |
| #57 | |
| #58 | // Should be a string and equal to the userId |
| #59 | expect(typeof memory.user_id).toBe("string"); |
| #60 | expect(memory.user_id).toBe(userId); |
| #61 | |
| #62 | // Should be null or any object (metadata) |
| #63 | expect( |
| #64 | memory.metadata === null || typeof memory.metadata === "object", |
| #65 | ).toBe(true); |
| #66 | |
| #67 | // Should be an array of strings or null (categories) |
| #68 | expect(Array.isArray(memory.categories) || memory.categories === null).toBe( |
| #69 | true, |
| #70 | ); |
| #71 | if (Array.isArray(memory.categories)) { |
| #72 | memory.categories.forEach((category) => { |
| #73 | expect(typeof category).toBe("string"); |
| #74 | }); |
| #75 | } |
| #76 | |
| #77 | // Should be a valid date (created_at) |
| #78 | expect(new Date(memory.created_at || "").toString()).not.toBe( |
| #79 | "Invalid Date", |
| #80 | ); |
| #81 | |
| #82 | // Should be a valid date (updated_at) |
| #83 | expect(new Date(memory.updated_at || "").toString()).not.toBe( |
| #84 | "Invalid Date", |
| #85 | ); |
| #86 | }); |
| #87 | |
| #88 | it("should retrieve all users successfully", async () => { |
| #89 | const allUsers = await client.users(); |
| #90 | |
| #91 | // Validate the number of users is a number |
| #92 | expect(typeof allUsers.count).toBe("number"); |
| #93 | |
| #94 | // Validate the structure of the first user |
| #95 | const firstUser = allUsers.results[0]; |
| #96 | expect(typeof firstUser.id).toBe("string"); |
| #97 | expect(typeof firstUser.name).toBe("string"); |
| #98 | expect(typeof firstUser.created_at).toBe("string"); |
| #99 | expect(typeof firstUser.updated_at).toBe("string"); |
| #100 | expect(typeof firstUser.total_memories).toBe("number"); |
| #101 | expect(typeof firstUser.type).toBe("string"); |
| #102 | |
| #103 | // Find the user with the name matching userId |
| #104 | const entity = allUsers.results.find((user) => user.name === userId); |
| #105 | expect(entity).not.toBeUndefined(); |
| #106 | |
| #107 | // Store the entity ID for later use |
| #108 | const entity_id = entity?.id; |
| #109 | expect(typeof entity_id).toBe("string"); |
| #110 | }); |
| #111 | |
| #112 | it("should retrieve all memories for the user", async () => { |
| #113 | const res3 = await client.getAll({ user_id: userId }); |
| #114 | |
| #115 | // Validate that res3 is an iterable list (array) |
| #116 | expect(Array.isArray(res3)).toBe(true); |
| #117 | |
| #118 | if (res3.length > 0) { |
| #119 | // Iterate through the first memory for validation (you can loop through all if needed) |
| #120 | const memory = res3[0]; |
| #121 | |
| #122 | // Should be a string (memory id) |
| #123 | expect(typeof memory.id).toBe("string"); |
| #124 | |
| #125 | // Should be a string (the actual memory content) |
| #126 | expect(typeof memory.memory).toBe("string"); |
| #127 | |
| #128 | // Should be a string and equal to the userId |
| #129 | expect(typeof memory.user_id).toBe("string"); |
| #130 | expect(memory.user_id).toBe(userId); |
| #131 | |
| #132 | // Should be null or an object (metadata) |
| #133 | expect( |
| #134 | memory.metadata === null || typeof memory.metadata === "object", |
| #135 | ).toBe(true); |
| #136 | |
| #137 | // Should be an array of strings or null (categories) |
| #138 | expect( |
| #139 | Array.isArray(memory.categories) || memory.categories === null, |
| #140 | ).toBe(true); |
| #141 | if (Array.isArray(memory.categories)) { |
| #142 | memory.categories.forEach((category) => { |
| #143 | expect(typeof category).toBe("string"); |
| #144 | }); |
| #145 | } |
| #146 | |
| #147 | // Should be a valid date (created_at) |
| #148 | expect(new Date(memory.created_at || "").toString()).not.toBe( |
| #149 | "Invalid Date", |
| #150 | ); |
| #151 | |
| #152 | // Should be a valid date (updated_at) |
| #153 | expect(new Date(memory.updated_at || "").toString()).not.toBe( |
| #154 | "Invalid Date", |
| #155 | ); |
| #156 | } else { |
| #157 | // If there are no memories, assert that the list is empty |
| #158 | expect(res3.length).toBe(0); |
| #159 | } |
| #160 | }); |
| #161 | |
| #162 | it("should search and return results based on provided query and filters (API version 2)", async () => { |
| #163 | const searchOptionsV2 = { |
| #164 | query: "What do you know about me?", |
| #165 | filters: { |
| #166 | OR: [{ user_id: userId }, { agent_id: "shopping-assistant" }], |
| #167 | }, |
| #168 | threshold: 0.1, |
| #169 | api_version: "v2", |
| #170 | }; |
| #171 | |
| #172 | const searchResultV2 = await client.search( |
| #173 | "What do you know about me?", |
| #174 | searchOptionsV2, |
| #175 | ); |
| #176 | |
| #177 | // Validate that searchResultV2 is an iterable list (array) |
| #178 | expect(Array.isArray(searchResultV2)).toBe(true); |
| #179 | |
| #180 | if (searchResultV2.length > 0) { |
| #181 | // Iterate through the first search result for validation (you can loop through all if needed) |
| #182 | const memory = searchResultV2[0]; |
| #183 | |
| #184 | // Should be a string (memory id) |
| #185 | expect(typeof memory.id).toBe("string"); |
| #186 | |
| #187 | // Should be a string (the actual memory content) |
| #188 | expect(typeof memory.memory).toBe("string"); |
| #189 | |
| #190 | if (memory.user_id) { |
| #191 | // Should be a string and equal to userId |
| #192 | expect(typeof memory.user_id).toBe("string"); |
| #193 | expect(memory.user_id).toBe(userId); |
| #194 | } |
| #195 | |
| #196 | if (memory.agent_id) { |
| #197 | // Should be a string (agent_id) |
| #198 | expect(typeof memory.agent_id).toBe("string"); |
| #199 | expect(memory.agent_id).toBe("shopping-assistant"); |
| #200 | } |
| #201 | |
| #202 | // Should be null or an object (metadata) |
| #203 | expect( |
| #204 | memory.metadata === null || typeof memory.metadata === "object", |
| #205 | ).toBe(true); |
| #206 | |
| #207 | // Should be an array of strings or null (categories) |
| #208 | expect( |
| #209 | Array.isArray(memory.categories) || memory.categories === null, |
| #210 | ).toBe(true); |
| #211 | if (Array.isArray(memory.categories)) { |
| #212 | memory.categories.forEach((category) => { |
| #213 | expect(typeof category).toBe("string"); |
| #214 | }); |
| #215 | } |
| #216 | |
| #217 | // Should be a valid date (created_at) |
| #218 | expect(new Date(memory.created_at || "").toString()).not.toBe( |
| #219 | "Invalid Date", |
| #220 | ); |
| #221 | |
| #222 | // Should be a valid date (updated_at) |
| #223 | expect(new Date(memory.updated_at || "").toString()).not.toBe( |
| #224 | "Invalid Date", |
| #225 | ); |
| #226 | |
| #227 | // Should be a number (score) |
| #228 | expect(typeof memory.score).toBe("number"); |
| #229 | } else { |
| #230 | // If no search results, assert that the list is empty |
| #231 | expect(searchResultV2.length).toBe(0); |
| #232 | } |
| #233 | }); |
| #234 | |
| #235 | it("should search and return results based on provided query (API version 1)", async () => { |
| #236 | const searchResultV1 = await client.search("What is my name?", { |
| #237 | user_id: userId, |
| #238 | }); |
| #239 | |
| #240 | // Validate that searchResultV1 is an iterable list (array) |
| #241 | expect(Array.isArray(searchResultV1)).toBe(true); |
| #242 | |
| #243 | if (searchResultV1.length > 0) { |
| #244 | // Iterate through the first search result for validation (you can loop through all if needed) |
| #245 | const memory = searchResultV1[0]; |
| #246 | |
| #247 | // Should be a string (memory id) |
| #248 | expect(typeof memory.id).toBe("string"); |
| #249 | |
| #250 | // Should be a string (the actual memory content) |
| #251 | expect(typeof memory.memory).toBe("string"); |
| #252 | |
| #253 | // Should be a string and equal to userId |
| #254 | expect(typeof memory.user_id).toBe("string"); |
| #255 | expect(memory.user_id).toBe(userId); |
| #256 | |
| #257 | // Should be null or an object (metadata) |
| #258 | expect( |
| #259 | memory.metadata === null || typeof memory.metadata === "object", |
| #260 | ).toBe(true); |
| #261 | |
| #262 | // Should be an array of strings or null (categories) |
| #263 | expect( |
| #264 | Array.isArray(memory.categories) || memory.categories === null, |
| #265 | ).toBe(true); |
| #266 | if (Array.isArray(memory.categories)) { |
| #267 | memory.categories.forEach((category) => { |
| #268 | expect(typeof category).toBe("string"); |
| #269 | }); |
| #270 | } |
| #271 | |
| #272 | // Should be a valid date (created_at) |
| #273 | expect(new Date(memory.created_at || "").toString()).not.toBe( |
| #274 | "Invalid Date", |
| #275 | ); |
| #276 | |
| #277 | // Should be a valid date (updated_at) |
| #278 | expect(new Date(memory.updated_at || "").toString()).not.toBe( |
| #279 | "Invalid Date", |
| #280 | ); |
| #281 | |
| #282 | // Should be a number (score) |
| #283 | expect(typeof memory.score).toBe("number"); |
| #284 | } else { |
| #285 | // If no search results, assert that the list is empty |
| #286 | expect(searchResultV1.length).toBe(0); |
| #287 | } |
| #288 | }); |
| #289 | |
| #290 | it("should retrieve history of a specific memory and validate the fields", async () => { |
| #291 | const res22 = await client.history(memoryId); |
| #292 | |
| #293 | // Validate that res22 is an iterable list (array) |
| #294 | expect(Array.isArray(res22)).toBe(true); |
| #295 | |
| #296 | if (res22.length > 0) { |
| #297 | // Iterate through the first history entry for validation (you can loop through all if needed) |
| #298 | const historyEntry = res22[0]; |
| #299 | |
| #300 | // Should be a string (history entry id) |
| #301 | expect(typeof historyEntry.id).toBe("string"); |
| #302 | |
| #303 | // Should be a string (memory id related to the history entry) |
| #304 | expect(typeof historyEntry.memory_id).toBe("string"); |
| #305 | |
| #306 | // Should be a string and equal to userId |
| #307 | expect(typeof historyEntry.user_id).toBe("string"); |
| #308 | expect(historyEntry.user_id).toBe(userId); |
| #309 | |
| #310 | // Should be a string or null (old memory) |
| #311 | expect( |
| #312 | historyEntry.old_memory === null || |
| #313 | typeof historyEntry.old_memory === "string", |
| #314 | ).toBe(true); |
| #315 | |
| #316 | // Should be a string or null (new memory) |
| #317 | expect( |
| #318 | historyEntry.new_memory === null || |
| #319 | typeof historyEntry.new_memory === "string", |
| #320 | ).toBe(true); |
| #321 | |
| #322 | // Should be an array of strings or null (categories) |
| #323 | expect( |
| #324 | Array.isArray(historyEntry.categories) || |
| #325 | historyEntry.categories === null, |
| #326 | ).toBe(true); |
| #327 | if (Array.isArray(historyEntry.categories)) { |
| #328 | historyEntry.categories.forEach((category) => { |
| #329 | expect(typeof category).toBe("string"); |
| #330 | }); |
| #331 | } |
| #332 | |
| #333 | // Should be a valid date (created_at) |
| #334 | expect(new Date(historyEntry.created_at).toString()).not.toBe( |
| #335 | "Invalid Date", |
| #336 | ); |
| #337 | |
| #338 | // Should be a valid date (updated_at) |
| #339 | expect(new Date(historyEntry.updated_at).toString()).not.toBe( |
| #340 | "Invalid Date", |
| #341 | ); |
| #342 | |
| #343 | // Should be a string, one of: ADD, UPDATE, DELETE, NOOP |
| #344 | expect(["ADD", "UPDATE", "DELETE", "NOOP"]).toContain(historyEntry.event); |
| #345 | |
| #346 | // Validate conditions based on event type |
| #347 | if (historyEntry.event === "ADD") { |
| #348 | expect(historyEntry.old_memory).toBeNull(); |
| #349 | expect(historyEntry.new_memory).not.toBeNull(); |
| #350 | } else if (historyEntry.event === "UPDATE") { |
| #351 | expect(historyEntry.old_memory).not.toBeNull(); |
| #352 | expect(historyEntry.new_memory).not.toBeNull(); |
| #353 | } else if (historyEntry.event === "DELETE") { |
| #354 | expect(historyEntry.old_memory).not.toBeNull(); |
| #355 | expect(historyEntry.new_memory).toBeNull(); |
| #356 | } |
| #357 | |
| #358 | // Should be a list of objects or null (input) |
| #359 | expect( |
| #360 | Array.isArray(historyEntry.input) || historyEntry.input === null, |
| #361 | ).toBe(true); |
| #362 | if (Array.isArray(historyEntry.input)) { |
| #363 | historyEntry.input.forEach((input) => { |
| #364 | // Each input should be an object |
| #365 | expect(typeof input).toBe("object"); |
| #366 | |
| #367 | // Should have string content |
| #368 | expect(typeof input.content).toBe("string"); |
| #369 | |
| #370 | // Should have a role that is either 'user' or 'assistant' |
| #371 | expect(["user", "assistant"]).toContain(input.role); |
| #372 | }); |
| #373 | } |
| #374 | } else { |
| #375 | // If no history entries, assert that the list is empty |
| #376 | expect(res22.length).toBe(0); |
| #377 | } |
| #378 | }); |
| #379 | |
| #380 | it("should delete the user successfully", async () => { |
| #381 | const allUsers = await client.users(); |
| #382 | const entity = allUsers.results.find((user) => user.name === userId); |
| #383 | |
| #384 | if (entity) { |
| #385 | const deletedUser = await client.deleteUser(entity.id); |
| #386 | |
| #387 | // Validate the deletion message |
| #388 | expect(deletedUser.message).toBe("Entity deleted successfully!"); |
| #389 | } |
| #390 | }); |
| #391 | }); |
| #392 |