fiemwl / src /lib /memory /__tests__ /injection.test.ts
automindy's picture
Upload 1980 files
6111b2b verified
Raw
History Blame Contribute Delete
7.67 kB
import { describe, test, expect } from "vitest";
import {
injectMemory,
shouldInjectMemory,
formatMemoryContext,
providerSupportsSystemMessage,
ChatRequest,
} from "../injection";
import { Memory, MemoryType } from "../types";
function makeMemory(content: string, overrides: Partial<Memory> = {}): Memory {
return {
id: "mem-1",
apiKeyId: "key-1",
sessionId: "sess-1",
type: MemoryType.FACTUAL,
key: "test-key",
content,
metadata: {},
createdAt: new Date(),
updatedAt: new Date(),
expiresAt: null,
...overrides,
};
}
function makeRequest(overrides: Partial<ChatRequest> = {}): ChatRequest {
return {
model: "gpt-4",
messages: [{ role: "user", content: "Hello" }],
...overrides,
};
}
describe("formatMemoryContext", () => {
test("returns empty string for empty array", () => {
expect(formatMemoryContext([])).toBe("");
});
test("single memory is formatted with 'Memory context:' prefix", () => {
const result = formatMemoryContext([makeMemory("User prefers dark mode")]);
expect(result).toBe("Memory context: User prefers dark mode");
});
test("multiple memories are joined with newline", () => {
const memories = [makeMemory("fact one"), makeMemory("fact two")];
const result = formatMemoryContext(memories);
expect(result).toBe("Memory context: fact one\nfact two");
});
test("trims whitespace from individual memory content", () => {
const result = formatMemoryContext([makeMemory(" padded content ")]);
expect(result).toBe("Memory context: padded content");
});
test("filters out blank memories", () => {
const memories = [makeMemory("real content"), makeMemory(" ")];
const result = formatMemoryContext(memories);
expect(result).toBe("Memory context: real content");
});
});
describe("providerSupportsSystemMessage", () => {
test("returns true for null/undefined provider", () => {
expect(providerSupportsSystemMessage(null)).toBe(true);
expect(providerSupportsSystemMessage(undefined)).toBe(true);
});
test("returns true for standard providers", () => {
expect(providerSupportsSystemMessage("openai")).toBe(true);
expect(providerSupportsSystemMessage("anthropic")).toBe(true);
expect(providerSupportsSystemMessage("deepseek")).toBe(true);
expect(providerSupportsSystemMessage("google")).toBe(true);
});
test("returns false for o1 family providers", () => {
expect(providerSupportsSystemMessage("o1")).toBe(false);
expect(providerSupportsSystemMessage("o1-mini")).toBe(false);
expect(providerSupportsSystemMessage("o1-preview")).toBe(false);
});
test("comparison is case-insensitive", () => {
expect(providerSupportsSystemMessage("O1")).toBe(false);
expect(providerSupportsSystemMessage("O1-MINI")).toBe(false);
});
});
describe("injectMemory — system message injection", () => {
test("injects memory as system message when provider supports it", () => {
const request = makeRequest();
const memories = [makeMemory("User prefers concise answers")];
const result = injectMemory(request, memories, "openai");
expect(result.messages[0].role).toBe("system");
expect(result.messages[0].content).toBe("Memory context: User prefers concise answers");
expect(result.messages[1]).toEqual({ role: "user", content: "Hello" });
});
test("preserves existing messages after injected system message", () => {
const request = makeRequest({
messages: [
{ role: "system", content: "You are helpful" },
{ role: "user", content: "Hello" },
],
});
const memories = [makeMemory("User is an expert developer")];
const result = injectMemory(request, memories, "anthropic");
expect(result.messages).toHaveLength(3);
expect(result.messages[0].role).toBe("system");
expect(result.messages[0].content).toContain("Memory context:");
expect(result.messages[1]).toEqual({ role: "system", content: "You are helpful" });
expect(result.messages[2]).toEqual({ role: "user", content: "Hello" });
});
test("does not mutate the original request", () => {
const request = makeRequest();
const originalMessages = [...request.messages];
const memories = [makeMemory("Some fact")];
injectMemory(request, memories, "openai");
expect(request.messages).toEqual(originalMessages);
});
test("preserves all other request fields", () => {
const request = makeRequest({ temperature: 0.7, max_tokens: 256, stream: true });
const memories = [makeMemory("fact")];
const result = injectMemory(request, memories, "openai");
expect(result.temperature).toBe(0.7);
expect(result.max_tokens).toBe(256);
expect(result.stream).toBe(true);
expect(result.model).toBe("gpt-4");
});
});
describe("injectMemory — message prefix fallback", () => {
test("injects memory as first user message for o1 provider", () => {
const request = makeRequest();
const memories = [makeMemory("User context detail")];
const result = injectMemory(request, memories, "o1");
expect(result.messages[0].role).toBe("user");
expect(result.messages[0].content).toBe("Memory context: User context detail");
expect(result.messages[1]).toEqual({ role: "user", content: "Hello" });
});
test("injects memory as first user message for o1-mini", () => {
const request = makeRequest();
const memories = [makeMemory("Preference")];
const result = injectMemory(request, memories, "o1-mini");
expect(result.messages[0].role).toBe("user");
expect(result.messages[0].content).toContain("Memory context:");
});
});
describe("injectMemory — edge cases", () => {
test("returns original request when memories array is empty", () => {
const request = makeRequest();
const result = injectMemory(request, [], "openai");
expect(result).toBe(request);
});
test("returns original request when memories is null-ish", () => {
const request = makeRequest();
const result = injectMemory(request, null as unknown as Memory[], "openai");
expect(result).toBe(request);
});
test("handles request with empty messages array", () => {
const request = makeRequest({ messages: [] });
const memories = [makeMemory("fact")];
const result = injectMemory(request, memories, "openai");
expect(result.messages).toHaveLength(1);
expect(result.messages[0].role).toBe("system");
});
test("handles multiple memories combined into single injection", () => {
const request = makeRequest();
const memories = [makeMemory("fact A"), makeMemory("fact B"), makeMemory("fact C")];
const result = injectMemory(request, memories, "openai");
expect(result.messages[0].role).toBe("system");
expect(result.messages[0].content).toBe("Memory context: fact A\nfact B\nfact C");
expect(result.messages).toHaveLength(2);
});
});
describe("shouldInjectMemory", () => {
test("returns true when messages are present and enabled not set", () => {
const request = makeRequest();
expect(shouldInjectMemory(request)).toBe(true);
});
test("returns false when config.enabled is false", () => {
const request = makeRequest();
expect(shouldInjectMemory(request, { enabled: false })).toBe(false);
});
test("returns false when messages array is empty", () => {
const request = makeRequest({ messages: [] });
expect(shouldInjectMemory(request)).toBe(false);
});
});