feat(memory): surface llama.cpp diagnostics

This commit is contained in:
Vincent Koc
2026-07-10 21:14:56 -07:00
committed by Vincent Koc
parent 4b0e5f5461
commit 85a96409f1
13 changed files with 426 additions and 8 deletions
+28 -3
View File
@@ -14,6 +14,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
const memoryHostEmbeddingMocks = vi.hoisted(() => ({
createLocalEmbeddingProvider: vi.fn(),
}));
const LOCAL_EMBEDDING_RUNTIME_FACTS = Symbol.for("openclaw.localEmbeddingRuntimeFacts");
vi.mock("openclaw/plugin-sdk/memory-core-host-engine-embeddings", () => ({
createLocalEmbeddingProvider: memoryHostEmbeddingMocks.createLocalEmbeddingProvider,
@@ -59,7 +60,13 @@ describe("llama.cpp provider plugin", () => {
it("adapts the worker-backed local embedding provider", async () => {
const close = vi.fn();
memoryHostEmbeddingMocks.createLocalEmbeddingProvider.mockResolvedValue({
const getRuntimeFacts = vi.fn(() => ({
engine: "llama.cpp" as const,
state: "ready" as const,
backend: "metal" as const,
buildType: "prebuilt" as const,
}));
const workerProvider = {
id: "local",
model: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
maxInputTokens: 2048,
@@ -67,7 +74,11 @@ describe("llama.cpp provider plugin", () => {
embedBatchInputs: vi.fn(async () => [[0.3, 0.4]]),
embedBatch: vi.fn(async () => [[1, 0]]),
close,
};
Object.defineProperty(workerProvider, LOCAL_EMBEDDING_RUNTIME_FACTS, {
value: getRuntimeFacts,
});
memoryHostEmbeddingMocks.createLocalEmbeddingProvider.mockResolvedValue(workerProvider);
const abortController = new AbortController();
const result = await llamaCppEmbeddingProviderAdapter.create({
@@ -89,6 +100,20 @@ describe("llama.cpp provider plugin", () => {
expect(provider.model).toBe(DEFAULT_LLAMA_CPP_EMBEDDING_MODEL);
expect(provider.maxInputTokens).toBe(2048);
const adaptedGetRuntimeFacts = Reflect.get(provider, LOCAL_EMBEDDING_RUNTIME_FACTS);
if (typeof adaptedGetRuntimeFacts !== "function") {
throw new Error("expected llama.cpp runtime facts carrier");
}
expect(adaptedGetRuntimeFacts()).toEqual({
engine: "llama.cpp",
state: "ready",
backend: "metal",
buildType: "prebuilt",
});
expect(result.runtime?.cacheKeyData).toEqual({
provider: "local",
model: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
});
expect(close).toHaveBeenCalledTimes(1);
expect(memoryHostEmbeddingMocks.createLocalEmbeddingProvider).toHaveBeenCalledWith(
{
@@ -104,9 +129,9 @@ describe("llama.cpp provider plugin", () => {
nodeLlamaCppImportUrl: expect.stringContaining("node-llama-cpp"),
},
);
const workerProvider =
const createdWorkerProvider =
await memoryHostEmbeddingMocks.createLocalEmbeddingProvider.mock.results[0].value;
expect(workerProvider.embedBatchInputs).toHaveBeenCalledWith([{ text: "doc" }], {
expect(createdWorkerProvider.embedBatchInputs).toHaveBeenCalledWith([{ text: "doc" }], {
signal: abortController.signal,
});
});
+17 -1
View File
@@ -28,6 +28,7 @@ type LlamaCppEmbeddingProviderRuntimeOptions = {
};
const LLAMA_CPP_EMBEDDING_PROVIDER_ID = "local";
const LOCAL_EMBEDDING_RUNTIME_FACTS = Symbol.for("openclaw.localEmbeddingRuntimeFacts");
export const DEFAULT_LLAMA_CPP_EMBEDDING_MODEL =
"hf:ggml-org/embeddinggemma-300m-qat-q8_0-GGUF/embeddinggemma-300m-qat-Q8_0.gguf";
const DEFAULT_LLAMA_CPP_EMBEDDING_MODEL_CACHE_FILE_NAME =
@@ -159,8 +160,18 @@ function resolveNodeLlamaCppImportUrl(): string {
return pathToFileURL(requireFromPlugin.resolve("node-llama-cpp")).href;
}
function copyLocalRuntimeFacts(source: object, target: object): void {
const getRuntimeFacts = Reflect.get(source, LOCAL_EMBEDDING_RUNTIME_FACTS);
if (typeof getRuntimeFacts === "function") {
Object.defineProperty(target, LOCAL_EMBEDDING_RUNTIME_FACTS, {
enumerable: false,
value: getRuntimeFacts,
});
}
}
function adaptMemoryEmbeddingProvider(provider: MemoryEmbeddingProvider): EmbeddingProvider {
return {
const adapted: EmbeddingProvider = {
id: LLAMA_CPP_EMBEDDING_PROVIDER_ID,
model: provider.model,
maxInputTokens: provider.maxInputTokens,
@@ -180,6 +191,8 @@ function adaptMemoryEmbeddingProvider(provider: MemoryEmbeddingProvider): Embedd
},
close: provider.close,
};
copyLocalRuntimeFacts(provider, adapted);
return adapted;
}
export async function createLlamaCppMemoryEmbeddingProvider(
@@ -198,6 +211,9 @@ export async function createLlamaCppMemoryEmbeddingProvider(
);
const identifiedProvider =
identity.model === provider.model ? provider : { ...provider, model: identity.model };
if (identifiedProvider !== provider) {
copyLocalRuntimeFacts(provider, identifiedProvider);
}
return {
provider: identifiedProvider,
runtime: createLlamaCppEmbeddingProviderRuntime(identity),