chroe(ts-sdk): fix lints (#4334)
This commit is contained in:
@@ -210,11 +210,7 @@ describe("backward compat: MemoryVectorStore", () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const store = new MemoryVectorStore({ dimension: 3, dbPath });
|
const store = new MemoryVectorStore({ dimension: 3, dbPath });
|
||||||
await store.insert(
|
await store.insert([normalize([1, 0, 0])], ["id1"], [{ text: "hello" }]);
|
||||||
[normalize([1, 0, 0])],
|
|
||||||
["id1"],
|
|
||||||
[{ text: "hello" }],
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(fs.existsSync(dbPath)).toBe(true);
|
expect(fs.existsSync(dbPath)).toBe(true);
|
||||||
|
|
||||||
|
|||||||
@@ -200,9 +200,9 @@ describe("MemoryVectorStore – path handling", () => {
|
|||||||
expect(
|
expect(
|
||||||
fs.existsSync(path.join(fakeHome, ".mem0", "vector_store.db")),
|
fs.existsSync(path.join(fakeHome, ".mem0", "vector_store.db")),
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
expect(
|
expect(fs.existsSync(path.join(readOnlyCwd, "vector_store.db"))).toBe(
|
||||||
fs.existsSync(path.join(readOnlyCwd, "vector_store.db")),
|
false,
|
||||||
).toBe(false);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
fs.chmodSync(readOnlyCwd, 0o755);
|
fs.chmodSync(readOnlyCwd, 0o755);
|
||||||
fs.rmSync(fakeHome, { recursive: true, force: true });
|
fs.rmSync(fakeHome, { recursive: true, force: true });
|
||||||
|
|||||||
@@ -273,10 +273,7 @@ export class Qdrant implements VectorStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async ensureCollection(
|
private async ensureCollection(name: string, size: number): Promise<void> {
|
||||||
name: string,
|
|
||||||
size: number,
|
|
||||||
): Promise<void> {
|
|
||||||
try {
|
try {
|
||||||
await this.client.createCollection(name, {
|
await this.client.createCollection(name, {
|
||||||
vectors: {
|
vectors: {
|
||||||
|
|||||||
@@ -13,7 +13,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { MemoryGraph } from "../src/memory/graph_memory";
|
import { MemoryGraph } from "../src/memory/graph_memory";
|
||||||
import { EXTRACT_RELATIONS_PROMPT, getDeleteMessages } from "../src/graphs/utils";
|
import {
|
||||||
|
EXTRACT_RELATIONS_PROMPT,
|
||||||
|
getDeleteMessages,
|
||||||
|
} from "../src/graphs/utils";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Mocks – we replace heavy dependencies so tests run without Neo4j / OpenAI
|
// Mocks – we replace heavy dependencies so tests run without Neo4j / OpenAI
|
||||||
@@ -100,7 +103,10 @@ describe("_retrieveNodesFromData", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mg = graph();
|
const mg = graph();
|
||||||
const result = await mg._retrieveNodesFromData("Alice likes pizza", FILTERS);
|
const result = await mg._retrieveNodesFromData(
|
||||||
|
"Alice likes pizza",
|
||||||
|
FILTERS,
|
||||||
|
);
|
||||||
|
|
||||||
expect(result).toEqual({ alice: "person", pizza: "food" });
|
expect(result).toEqual({ alice: "person", pizza: "food" });
|
||||||
});
|
});
|
||||||
@@ -166,7 +172,9 @@ describe("_retrieveNodesFromData", () => {
|
|||||||
toolCalls: [
|
toolCalls: [
|
||||||
{
|
{
|
||||||
name: "some_other_tool",
|
name: "some_other_tool",
|
||||||
arguments: JSON.stringify({ entities: [{ entity: "X", entity_type: "Y" }] }),
|
arguments: JSON.stringify({
|
||||||
|
entities: [{ entity: "X", entity_type: "Y" }],
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -273,9 +281,7 @@ describe("_establishNodesRelationsFromData", () => {
|
|||||||
|
|
||||||
it("throws on malformed JSON in tool call arguments (no try/catch in source)", async () => {
|
it("throws on malformed JSON in tool call arguments (no try/catch in source)", async () => {
|
||||||
mockGenerateResponse.mockResolvedValueOnce({
|
mockGenerateResponse.mockResolvedValueOnce({
|
||||||
toolCalls: [
|
toolCalls: [{ name: "establish_relationships", arguments: "<<BROKEN>>" }],
|
||||||
{ name: "establish_relationships", arguments: "<<BROKEN>>" },
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mg = graph();
|
const mg = graph();
|
||||||
@@ -347,7 +353,11 @@ describe("_getDeleteEntitiesFromSearchOutput", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mg = graph();
|
const mg = graph();
|
||||||
const result = await mg._getDeleteEntitiesFromSearchOutput(SEARCH_OUTPUT, "Alice hates pizza", FILTERS);
|
const result = await mg._getDeleteEntitiesFromSearchOutput(
|
||||||
|
SEARCH_OUTPUT,
|
||||||
|
"Alice hates pizza",
|
||||||
|
FILTERS,
|
||||||
|
);
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
{ source: "alice", relationship: "likes", destination: "pizza" },
|
{ source: "alice", relationship: "likes", destination: "pizza" },
|
||||||
@@ -358,7 +368,11 @@ describe("_getDeleteEntitiesFromSearchOutput", () => {
|
|||||||
mockGenerateResponse.mockResolvedValueOnce("string response");
|
mockGenerateResponse.mockResolvedValueOnce("string response");
|
||||||
|
|
||||||
const mg = graph();
|
const mg = graph();
|
||||||
const result = await mg._getDeleteEntitiesFromSearchOutput(SEARCH_OUTPUT, "x", FILTERS);
|
const result = await mg._getDeleteEntitiesFromSearchOutput(
|
||||||
|
SEARCH_OUTPUT,
|
||||||
|
"x",
|
||||||
|
FILTERS,
|
||||||
|
);
|
||||||
expect(result).toEqual([]);
|
expect(result).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -366,7 +380,11 @@ describe("_getDeleteEntitiesFromSearchOutput", () => {
|
|||||||
mockGenerateResponse.mockResolvedValueOnce({ toolCalls: [] });
|
mockGenerateResponse.mockResolvedValueOnce({ toolCalls: [] });
|
||||||
|
|
||||||
const mg = graph();
|
const mg = graph();
|
||||||
const result = await mg._getDeleteEntitiesFromSearchOutput(SEARCH_OUTPUT, "x", FILTERS);
|
const result = await mg._getDeleteEntitiesFromSearchOutput(
|
||||||
|
SEARCH_OUTPUT,
|
||||||
|
"x",
|
||||||
|
FILTERS,
|
||||||
|
);
|
||||||
expect(result).toEqual([]);
|
expect(result).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -381,7 +399,11 @@ describe("_getDeleteEntitiesFromSearchOutput", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mg = graph();
|
const mg = graph();
|
||||||
const result = await mg._getDeleteEntitiesFromSearchOutput(SEARCH_OUTPUT, "x", FILTERS);
|
const result = await mg._getDeleteEntitiesFromSearchOutput(
|
||||||
|
SEARCH_OUTPUT,
|
||||||
|
"x",
|
||||||
|
FILTERS,
|
||||||
|
);
|
||||||
expect(result).toEqual([]);
|
expect(result).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -390,17 +412,29 @@ describe("_getDeleteEntitiesFromSearchOutput", () => {
|
|||||||
toolCalls: [
|
toolCalls: [
|
||||||
{
|
{
|
||||||
name: "delete_graph_memory",
|
name: "delete_graph_memory",
|
||||||
arguments: JSON.stringify({ source: "A", relationship: "r1", destination: "B" }),
|
arguments: JSON.stringify({
|
||||||
|
source: "A",
|
||||||
|
relationship: "r1",
|
||||||
|
destination: "B",
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "delete_graph_memory",
|
name: "delete_graph_memory",
|
||||||
arguments: JSON.stringify({ source: "C", relationship: "r2", destination: "D" }),
|
arguments: JSON.stringify({
|
||||||
|
source: "C",
|
||||||
|
relationship: "r2",
|
||||||
|
destination: "D",
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const mg = graph();
|
const mg = graph();
|
||||||
const result = await mg._getDeleteEntitiesFromSearchOutput(SEARCH_OUTPUT, "x", FILTERS);
|
const result = await mg._getDeleteEntitiesFromSearchOutput(
|
||||||
|
SEARCH_OUTPUT,
|
||||||
|
"x",
|
||||||
|
FILTERS,
|
||||||
|
);
|
||||||
expect(result).toHaveLength(2);
|
expect(result).toHaveLength(2);
|
||||||
expect(result[0].source).toBe("a");
|
expect(result[0].source).toBe("a");
|
||||||
expect(result[1].source).toBe("c");
|
expect(result[1].source).toBe("c");
|
||||||
@@ -425,7 +459,11 @@ describe("_getDeleteEntitiesFromSearchOutput", () => {
|
|||||||
mockGenerateResponse.mockResolvedValueOnce({ toolCalls: [] });
|
mockGenerateResponse.mockResolvedValueOnce({ toolCalls: [] });
|
||||||
|
|
||||||
const mg = graph();
|
const mg = graph();
|
||||||
const result = await mg._getDeleteEntitiesFromSearchOutput([], "data", FILTERS);
|
const result = await mg._getDeleteEntitiesFromSearchOutput(
|
||||||
|
[],
|
||||||
|
"data",
|
||||||
|
FILTERS,
|
||||||
|
);
|
||||||
expect(result).toEqual([]);
|
expect(result).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -481,7 +519,11 @@ describe("_removeSpacesFromEntities (via _establishNodesRelationsFromData)", ()
|
|||||||
name: "establish_relationships",
|
name: "establish_relationships",
|
||||||
arguments: JSON.stringify({
|
arguments: JSON.stringify({
|
||||||
entities: [
|
entities: [
|
||||||
{ source: "New York", relationship: "Capital Of", destination: "United States" },
|
{
|
||||||
|
source: "New York",
|
||||||
|
relationship: "Capital Of",
|
||||||
|
destination: "United States",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -489,10 +531,18 @@ describe("_removeSpacesFromEntities (via _establishNodesRelationsFromData)", ()
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mg = graph();
|
const mg = graph();
|
||||||
const result = await mg._establishNodesRelationsFromData("test", FILTERS, {});
|
const result = await mg._establishNodesRelationsFromData(
|
||||||
|
"test",
|
||||||
|
FILTERS,
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
{ source: "new_york", relationship: "capital_of", destination: "united_states" },
|
{
|
||||||
|
source: "new_york",
|
||||||
|
relationship: "capital_of",
|
||||||
|
destination: "united_states",
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ describe("Graph prompts — JSON keyword requirement", () => {
|
|||||||
it("EXTRACT_RELATIONS_PROMPT produces a message containing 'json' once the suffix is appended", () => {
|
it("EXTRACT_RELATIONS_PROMPT produces a message containing 'json' once the suffix is appended", () => {
|
||||||
// graph_memory.ts appends "\nPlease provide your response in JSON format."
|
// graph_memory.ts appends "\nPlease provide your response in JSON format."
|
||||||
const withSuffix =
|
const withSuffix =
|
||||||
EXTRACT_RELATIONS_PROMPT + "\nPlease provide your response in JSON format.";
|
EXTRACT_RELATIONS_PROMPT +
|
||||||
|
"\nPlease provide your response in JSON format.";
|
||||||
expect(withSuffix.toLowerCase()).toContain("json");
|
expect(withSuffix.toLowerCase()).toContain("json");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,13 +87,21 @@ describe("getDeleteMessages", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("handles special characters in userId (e.g. angle brackets, quotes)", () => {
|
it("handles special characters in userId (e.g. angle brackets, quotes)", () => {
|
||||||
const [system] = getDeleteMessages("mem", "data", '<script>alert("xss")</script>');
|
const [system] = getDeleteMessages(
|
||||||
|
"mem",
|
||||||
|
"data",
|
||||||
|
'<script>alert("xss")</script>',
|
||||||
|
);
|
||||||
expect(system).toContain('<script>alert("xss")</script>');
|
expect(system).toContain('<script>alert("xss")</script>');
|
||||||
expect(system).not.toContain("USER_ID");
|
expect(system).not.toContain("USER_ID");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("handles unicode input", () => {
|
it("handles unicode input", () => {
|
||||||
const [system, user] = getDeleteMessages("日本語メモリ", "新しい情報", "ユーザー1");
|
const [system, user] = getDeleteMessages(
|
||||||
|
"日本語メモリ",
|
||||||
|
"新しい情報",
|
||||||
|
"ユーザー1",
|
||||||
|
);
|
||||||
expect(system).toContain("ユーザー1");
|
expect(system).toContain("ユーザー1");
|
||||||
expect(user).toContain("日本語メモリ");
|
expect(user).toContain("日本語メモリ");
|
||||||
expect(user).toContain("新しい情報");
|
expect(user).toContain("新しい情報");
|
||||||
@@ -130,7 +139,7 @@ describe("formatEntities", () => {
|
|||||||
|
|
||||||
it("preserves special characters in entity fields", () => {
|
it("preserves special characters in entity fields", () => {
|
||||||
const result = formatEntities([
|
const result = formatEntities([
|
||||||
{ source: "O'Brien", relationship: "said \"hello\"", destination: "café" },
|
{ source: "O'Brien", relationship: 'said "hello"', destination: "café" },
|
||||||
]);
|
]);
|
||||||
expect(result).toContain("O'Brien");
|
expect(result).toContain("O'Brien");
|
||||||
expect(result).toContain('said "hello"');
|
expect(result).toContain('said "hello"');
|
||||||
|
|||||||
@@ -151,10 +151,14 @@ describeIfQdrant("Issue #4212/#4173: Qdrant dimension mismatch", () => {
|
|||||||
const id1 = uuidv4();
|
const id1 = uuidv4();
|
||||||
const id2 = uuidv4();
|
const id2 = uuidv4();
|
||||||
|
|
||||||
await store.insert([vec1, vec2], [id1, id2], [
|
await store.insert(
|
||||||
{ data: "hello", userId: "u1" },
|
[vec1, vec2],
|
||||||
{ data: "world", userId: "u1" },
|
[id1, id2],
|
||||||
]);
|
[
|
||||||
|
{ data: "hello", userId: "u1" },
|
||||||
|
{ data: "world", userId: "u1" },
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
// Search with 768-dim query — this USED TO fail with Bad Request
|
// Search with 768-dim query — this USED TO fail with Bad Request
|
||||||
const results = await store.search(vec1, 2, { userId: "u1" });
|
const results = await store.search(vec1, 2, { userId: "u1" });
|
||||||
@@ -203,9 +207,11 @@ describeIfQdrant("Issue #4212/#4173: Qdrant dimension mismatch", () => {
|
|||||||
return {
|
return {
|
||||||
EmbedderFactory: { create: jest.fn().mockReturnValue(fakeEmbedder) },
|
EmbedderFactory: { create: jest.fn().mockReturnValue(fakeEmbedder) },
|
||||||
VectorStoreFactory: {
|
VectorStoreFactory: {
|
||||||
create: jest.fn().mockImplementation((_provider: string, config: any) => {
|
create: jest
|
||||||
return new QdrantStore(config);
|
.fn()
|
||||||
}),
|
.mockImplementation((_provider: string, config: any) => {
|
||||||
|
return new QdrantStore(config);
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
LLMFactory: {
|
LLMFactory: {
|
||||||
create: jest.fn().mockReturnValue({
|
create: jest.fn().mockReturnValue({
|
||||||
@@ -280,9 +286,11 @@ describeIfQdrant("Issue #4212/#4173: Qdrant dimension mismatch", () => {
|
|||||||
return {
|
return {
|
||||||
EmbedderFactory: { create: jest.fn().mockReturnValue(fakeEmbedder) },
|
EmbedderFactory: { create: jest.fn().mockReturnValue(fakeEmbedder) },
|
||||||
VectorStoreFactory: {
|
VectorStoreFactory: {
|
||||||
create: jest.fn().mockImplementation((_provider: string, config: any) => {
|
create: jest
|
||||||
return new QdrantStore(config);
|
.fn()
|
||||||
}),
|
.mockImplementation((_provider: string, config: any) => {
|
||||||
|
return new QdrantStore(config);
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
LLMFactory: {
|
LLMFactory: {
|
||||||
create: jest.fn().mockReturnValue({
|
create: jest.fn().mockReturnValue({
|
||||||
@@ -350,9 +358,11 @@ describeIfQdrant("Issue #4212/#4173: Qdrant dimension mismatch", () => {
|
|||||||
return {
|
return {
|
||||||
EmbedderFactory: { create: jest.fn().mockReturnValue(fakeEmbedder) },
|
EmbedderFactory: { create: jest.fn().mockReturnValue(fakeEmbedder) },
|
||||||
VectorStoreFactory: {
|
VectorStoreFactory: {
|
||||||
create: jest.fn().mockImplementation((_provider: string, config: any) => {
|
create: jest
|
||||||
return new QdrantStore(config);
|
.fn()
|
||||||
}),
|
.mockImplementation((_provider: string, config: any) => {
|
||||||
|
return new QdrantStore(config);
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
LLMFactory: {
|
LLMFactory: {
|
||||||
create: jest.fn().mockReturnValue({
|
create: jest.fn().mockReturnValue({
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ describe("removeCodeBlocks", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("handles Claude-style response with surrounding text", () => {
|
it("handles Claude-style response with surrounding text", () => {
|
||||||
const input = 'Here is the JSON:\n```json\n{"facts": ["user likes TypeScript"]}\n```';
|
const input =
|
||||||
|
'Here is the JSON:\n```json\n{"facts": ["user likes TypeScript"]}\n```';
|
||||||
expect(removeCodeBlocks(input)).toContain('"facts"');
|
expect(removeCodeBlocks(input)).toContain('"facts"');
|
||||||
expect(removeCodeBlocks(input)).not.toContain("```");
|
expect(removeCodeBlocks(input)).not.toContain("```");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -76,10 +76,14 @@ describe("MemoryVectorStore – full backward compat", () => {
|
|||||||
vec2[1] = 1.0;
|
vec2[1] = 1.0;
|
||||||
|
|
||||||
// Insert
|
// Insert
|
||||||
await store.insert([vec1, vec2], ["id-1", "id-2"], [
|
await store.insert(
|
||||||
{ data: "alpha", userId: "u1" },
|
[vec1, vec2],
|
||||||
{ data: "beta", userId: "u1" },
|
["id-1", "id-2"],
|
||||||
]);
|
[
|
||||||
|
{ data: "alpha", userId: "u1" },
|
||||||
|
{ data: "beta", userId: "u1" },
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
// Get
|
// Get
|
||||||
const item = await store.get("id-1");
|
const item = await store.get("id-1");
|
||||||
@@ -204,66 +208,87 @@ describe("MemoryVectorStore – full backward compat", () => {
|
|||||||
describe("Qdrant – backward compat with mocked client", () => {
|
describe("Qdrant – backward compat with mocked client", () => {
|
||||||
function createMockQdrantClient() {
|
function createMockQdrantClient() {
|
||||||
const collections = new Map<string, number>();
|
const collections = new Map<string, number>();
|
||||||
const points = new Map<string, { id: string; vector: number[]; payload: any }>();
|
const points = new Map<
|
||||||
|
string,
|
||||||
|
{ id: string; vector: number[]; payload: any }
|
||||||
|
>();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_collections: collections,
|
_collections: collections,
|
||||||
_points: points,
|
_points: points,
|
||||||
createCollection: jest.fn().mockImplementation(async (name: string, opts: any) => {
|
createCollection: jest
|
||||||
if (collections.has(name)) {
|
.fn()
|
||||||
const err: any = new Error("Collection already exists");
|
.mockImplementation(async (name: string, opts: any) => {
|
||||||
err.status = 409;
|
if (collections.has(name)) {
|
||||||
throw err;
|
const err: any = new Error("Collection already exists");
|
||||||
}
|
err.status = 409;
|
||||||
collections.set(name, opts.vectors.size);
|
throw err;
|
||||||
}),
|
}
|
||||||
|
collections.set(name, opts.vectors.size);
|
||||||
|
}),
|
||||||
getCollection: jest.fn().mockImplementation(async (name: string) => {
|
getCollection: jest.fn().mockImplementation(async (name: string) => {
|
||||||
if (!collections.has(name)) {
|
if (!collections.has(name)) {
|
||||||
const err: any = new Error("Not found");
|
const err: any = new Error("Not found");
|
||||||
err.status = 404;
|
err.status = 404;
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
return { config: { params: { vectors: { size: collections.get(name) } } } };
|
return {
|
||||||
|
config: { params: { vectors: { size: collections.get(name) } } },
|
||||||
|
};
|
||||||
}),
|
}),
|
||||||
getCollections: jest.fn().mockResolvedValue({
|
getCollections: jest.fn().mockResolvedValue({
|
||||||
collections: [],
|
collections: [],
|
||||||
}),
|
}),
|
||||||
upsert: jest.fn().mockImplementation(async (collName: string, opts: any) => {
|
upsert: jest
|
||||||
for (const pt of opts.points) {
|
.fn()
|
||||||
points.set(`${collName}:${pt.id}`, { id: pt.id, vector: pt.vector, payload: pt.payload });
|
.mockImplementation(async (collName: string, opts: any) => {
|
||||||
}
|
for (const pt of opts.points) {
|
||||||
}),
|
points.set(`${collName}:${pt.id}`, {
|
||||||
retrieve: jest.fn().mockImplementation(async (collName: string, opts: any) => {
|
id: pt.id,
|
||||||
const results = [];
|
vector: pt.vector,
|
||||||
for (const id of opts.ids) {
|
payload: pt.payload,
|
||||||
const pt = points.get(`${collName}:${id}`);
|
});
|
||||||
if (pt) results.push({ id: pt.id, payload: pt.payload });
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}),
|
|
||||||
search: jest.fn().mockImplementation(async (collName: string, opts: any) => {
|
|
||||||
const results: any[] = [];
|
|
||||||
points.forEach((pt, key) => {
|
|
||||||
if (key.startsWith(`${collName}:`)) {
|
|
||||||
results.push({ id: pt.id, payload: pt.payload, score: 0.9 });
|
|
||||||
}
|
}
|
||||||
});
|
}),
|
||||||
return results.slice(0, opts.limit);
|
retrieve: jest
|
||||||
}),
|
.fn()
|
||||||
scroll: jest.fn().mockImplementation(async (collName: string, opts: any) => {
|
.mockImplementation(async (collName: string, opts: any) => {
|
||||||
const results: any[] = [];
|
const results = [];
|
||||||
points.forEach((pt, key) => {
|
for (const id of opts.ids) {
|
||||||
if (key.startsWith(`${collName}:`)) {
|
const pt = points.get(`${collName}:${id}`);
|
||||||
results.push({ id: pt.id, payload: pt.payload });
|
if (pt) results.push({ id: pt.id, payload: pt.payload });
|
||||||
}
|
}
|
||||||
});
|
return results;
|
||||||
return { points: results.slice(0, opts.limit) };
|
}),
|
||||||
}),
|
search: jest
|
||||||
delete: jest.fn().mockImplementation(async (collName: string, opts: any) => {
|
.fn()
|
||||||
for (const id of opts.points) {
|
.mockImplementation(async (collName: string, opts: any) => {
|
||||||
points.delete(`${collName}:${id}`);
|
const results: any[] = [];
|
||||||
}
|
points.forEach((pt, key) => {
|
||||||
}),
|
if (key.startsWith(`${collName}:`)) {
|
||||||
|
results.push({ id: pt.id, payload: pt.payload, score: 0.9 });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return results.slice(0, opts.limit);
|
||||||
|
}),
|
||||||
|
scroll: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(async (collName: string, opts: any) => {
|
||||||
|
const results: any[] = [];
|
||||||
|
points.forEach((pt, key) => {
|
||||||
|
if (key.startsWith(`${collName}:`)) {
|
||||||
|
results.push({ id: pt.id, payload: pt.payload });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { points: results.slice(0, opts.limit) };
|
||||||
|
}),
|
||||||
|
delete: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(async (collName: string, opts: any) => {
|
||||||
|
for (const id of opts.points) {
|
||||||
|
points.delete(`${collName}:${id}`);
|
||||||
|
}
|
||||||
|
}),
|
||||||
deleteCollection: jest.fn().mockImplementation(async (name: string) => {
|
deleteCollection: jest.fn().mockImplementation(async (name: string) => {
|
||||||
collections.delete(name);
|
collections.delete(name);
|
||||||
}),
|
}),
|
||||||
@@ -324,7 +349,10 @@ describe("Qdrant – backward compat with mocked client", () => {
|
|||||||
|
|
||||||
// Insert
|
// Insert
|
||||||
await store.insert(
|
await store.insert(
|
||||||
[[1, 2, 3], [4, 5, 6]],
|
[
|
||||||
|
[1, 2, 3],
|
||||||
|
[4, 5, 6],
|
||||||
|
],
|
||||||
["id-1", "id-2"],
|
["id-1", "id-2"],
|
||||||
[{ data: "alpha" }, { data: "beta" }],
|
[{ data: "alpha" }, { data: "beta" }],
|
||||||
);
|
);
|
||||||
@@ -391,9 +419,9 @@ describe("Redis – backward compat with mocked client", () => {
|
|||||||
connect: jest.fn().mockResolvedValue(undefined),
|
connect: jest.fn().mockResolvedValue(undefined),
|
||||||
on: jest.fn(),
|
on: jest.fn(),
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
moduleList: jest.fn().mockResolvedValue([
|
moduleList: jest
|
||||||
["name", "search", "ver", 20000],
|
.fn()
|
||||||
]),
|
.mockResolvedValue([["name", "search", "ver", 20000]]),
|
||||||
ft: {
|
ft: {
|
||||||
dropIndex: jest.fn().mockResolvedValue(undefined),
|
dropIndex: jest.fn().mockResolvedValue(undefined),
|
||||||
create: jest.fn().mockResolvedValue(undefined),
|
create: jest.fn().mockResolvedValue(undefined),
|
||||||
@@ -599,14 +627,17 @@ describe("AzureAISearch – backward compat with mocked client", () => {
|
|||||||
createOrUpdateIndex: jest.fn().mockResolvedValue({}),
|
createOrUpdateIndex: jest.fn().mockResolvedValue({}),
|
||||||
deleteIndex: jest.fn().mockResolvedValue({}),
|
deleteIndex: jest.fn().mockResolvedValue({}),
|
||||||
})),
|
})),
|
||||||
AzureKeyCredential: jest.fn().mockImplementation((key: string) => ({ key })),
|
AzureKeyCredential: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation((key: string) => ({ key })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.doMock("@azure/identity", () => ({
|
jest.doMock("@azure/identity", () => ({
|
||||||
DefaultAzureCredential: jest.fn(),
|
DefaultAzureCredential: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
AzureAISearch = require("../src/vector_stores/azure_ai_search").AzureAISearch;
|
AzureAISearch =
|
||||||
|
require("../src/vector_stores/azure_ai_search").AzureAISearch;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -661,7 +692,9 @@ describe("Vectorize – backward compat with mocked client", () => {
|
|||||||
jest.doMock("cloudflare", () => {
|
jest.doMock("cloudflare", () => {
|
||||||
const mockIndexes = {
|
const mockIndexes = {
|
||||||
list: jest.fn().mockReturnValue({
|
list: jest.fn().mockReturnValue({
|
||||||
[Symbol.asyncIterator]: () => ({ next: async () => ({ done: true }) }),
|
[Symbol.asyncIterator]: () => ({
|
||||||
|
next: async () => ({ done: true }),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
create: jest.fn().mockResolvedValue({}),
|
create: jest.fn().mockResolvedValue({}),
|
||||||
delete: jest.fn().mockResolvedValue({}),
|
delete: jest.fn().mockResolvedValue({}),
|
||||||
@@ -772,9 +805,14 @@ describe("LangchainVectorStore – backward compat", () => {
|
|||||||
const { LangchainVectorStore } = require("../src/vector_stores/langchain");
|
const { LangchainVectorStore } = require("../src/vector_stores/langchain");
|
||||||
const mockLcStore = {
|
const mockLcStore = {
|
||||||
addVectors: jest.fn().mockResolvedValue(undefined),
|
addVectors: jest.fn().mockResolvedValue(undefined),
|
||||||
similaritySearchVectorWithScore: jest.fn().mockResolvedValue([
|
similaritySearchVectorWithScore: jest
|
||||||
[{ metadata: { _mem0_id: "id-1", data: "test" }, pageContent: "" }, 0.95],
|
.fn()
|
||||||
]),
|
.mockResolvedValue([
|
||||||
|
[
|
||||||
|
{ metadata: { _mem0_id: "id-1", data: "test" }, pageContent: "" },
|
||||||
|
0.95,
|
||||||
|
],
|
||||||
|
]),
|
||||||
};
|
};
|
||||||
const store = new LangchainVectorStore({
|
const store = new LangchainVectorStore({
|
||||||
client: mockLcStore,
|
client: mockLcStore,
|
||||||
@@ -821,9 +859,9 @@ describe("LangchainVectorStore – backward compat", () => {
|
|||||||
dimension: 4,
|
dimension: 4,
|
||||||
});
|
});
|
||||||
|
|
||||||
await expect(
|
await expect(store.insert([[1, 2, 3]], ["id-1"], [{}])).rejects.toThrow(
|
||||||
store.insert([[1, 2, 3]], ["id-1"], [{}]),
|
"Vector dimension mismatch",
|
||||||
).rejects.toThrow("Vector dimension mismatch");
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -976,11 +1014,27 @@ describe("Memory class – backward compat with all providers", () => {
|
|||||||
]);
|
]);
|
||||||
mockVStore.get.mockResolvedValue({
|
mockVStore.get.mockResolvedValue({
|
||||||
id: "id-1",
|
id: "id-1",
|
||||||
payload: { memory: "test", hash: "h", created_at: new Date().toISOString(), updated_at: new Date().toISOString() },
|
payload: {
|
||||||
|
memory: "test",
|
||||||
|
hash: "h",
|
||||||
|
created_at: new Date().toISOString(),
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
mockVStore.list.mockResolvedValue([[
|
mockVStore.list.mockResolvedValue([
|
||||||
{ id: "id-1", payload: { memory: "test", hash: "h", created_at: new Date().toISOString(), updated_at: new Date().toISOString() } },
|
[
|
||||||
], 1]);
|
{
|
||||||
|
id: "id-1",
|
||||||
|
payload: {
|
||||||
|
memory: "test",
|
||||||
|
hash: "h",
|
||||||
|
created_at: new Date().toISOString(),
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
1,
|
||||||
|
]);
|
||||||
mockVectorStoreFactory.create.mockReturnValue(mockVStore);
|
mockVectorStoreFactory.create.mockReturnValue(mockVStore);
|
||||||
|
|
||||||
const mem = new MemoryClass({
|
const mem = new MemoryClass({
|
||||||
@@ -1055,7 +1109,9 @@ describe("Memory class – backward compat with all providers", () => {
|
|||||||
};
|
};
|
||||||
mockEmbedderFactory.create.mockReturnValue(failingEmbedder);
|
mockEmbedderFactory.create.mockReturnValue(failingEmbedder);
|
||||||
|
|
||||||
const consoleSpy = jest.spyOn(console, "error").mockImplementation(() => {});
|
const consoleSpy = jest
|
||||||
|
.spyOn(console, "error")
|
||||||
|
.mockImplementation(() => {});
|
||||||
|
|
||||||
const mem = new MemoryClass({
|
const mem = new MemoryClass({
|
||||||
embedder: { provider: "ollama", config: { model: "test" } },
|
embedder: { provider: "ollama", config: { model: "test" } },
|
||||||
@@ -1077,4 +1133,3 @@ describe("Memory class – backward compat with all providers", () => {
|
|||||||
consoleSpy.mockRestore();
|
consoleSpy.mockRestore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user