openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
109 lines (108 loc) • 6.16 kB
JavaScript
import { i as executeSqliteQuerySync, o as getNodeSqliteKysely, s as iterateSqliteQuerySync, t as compileSqliteQueryBindings } from "./kysely-sync-DUWzQvCU.mjs";
import { n as decodeMemoryEmbedding, r as encodeMemoryEmbedding } from "./embedding-vector-DA_9H0FL.mjs";
import "./memory-core-host-engine-storage-D6wIwcVO.mjs";
import "./sqlite-worker-runtime-EkcIEvGh.mjs";
//#region extensions/memory-core/src/memory/manager-embedding-cache.ts
/** Require a finite, nonempty vector compatible with the active embedding dimensions. */
function isValidMemoryEmbedding(embedding, dimensions) {
return Array.isArray(embedding) && embedding.length > 0 && (dimensions === void 0 || embedding.length === dimensions) && embedding.every((coordinate) => typeof coordinate === "number" && Number.isFinite(coordinate));
}
function loadMemoryEmbeddingCache(params) {
if (params.providerIdentities.length === 0 || params.hashes.length === 0) return /* @__PURE__ */ new Map();
const unresolved = new Set(params.hashes.filter(Boolean));
if (unresolved.size === 0) return /* @__PURE__ */ new Map();
const db = getNodeSqliteKysely(params.db);
const out = /* @__PURE__ */ new Map();
const batchSize = 400;
for (const identity of params.providerIdentities) {
if (unresolved.size === 0) break;
const hashes = [...unresolved];
for (let start = 0; start < hashes.length; start += batchSize) {
const batch = hashes.slice(start, start + batchSize);
const query = db.selectFrom("memory_embedding_cache").select(["hash", "embedding"]).select((eb) => eb.or([eb("dims", "is", null), eb("dims", "=", eb(eb.fn("length", ["embedding"]), "/", eb.lit(8)))]).as("dimensions_match")).where("provider", "=", identity.provider).where("model", "=", identity.model).where("provider_key", "=", identity.providerKey).where("hash", "in", batch);
for (const row of iterateSqliteQuerySync(params.db, query)) {
const embedding = decodeMemoryEmbedding(row.embedding);
out.set(row.hash, row.dimensions_match && isValidMemoryEmbedding(embedding) ? embedding : []);
unresolved.delete(row.hash);
}
}
}
return out;
}
function countMemoryEmbeddingCache(database) {
const db = getNodeSqliteKysely(database);
return executeSqliteQuerySync(database, db.selectFrom("memory_embedding_cache").select((eb) => eb.fn.countAll().as("count"))).rows[0].count;
}
/** The caller holds the write transaction; another purge may have reduced the cache. */
function pruneMemoryEmbeddingCache(database, maxEntries) {
const excess = countMemoryEmbeddingCache(database) - maxEntries;
if (excess <= 0) return;
deleteOldestMemoryEmbeddingCacheRows(database, Math.min(excess, 100));
}
function deleteOldestMemoryEmbeddingCacheRows(database, limit) {
const db = getNodeSqliteKysely(database);
executeSqliteQuerySync(database, db.deleteFrom("memory_embedding_cache").where("rowid", "in", db.selectFrom("memory_embedding_cache").select("rowid").orderBy("updated_at", "asc").orderBy("rowid", "asc").limit(limit)));
}
/** Discard ambiguous vector spaces without removing unrelated provider caches or index rows. */
function clearMemoryEmbeddingCacheIdentities(database, identities) {
const db = getNodeSqliteKysely(database);
for (const identity of identities) executeSqliteQuerySync(database, db.deleteFrom("memory_embedding_cache").where("provider", "=", identity.provider).where("model", "=", identity.model).where("provider_key", "=", identity.providerKey));
}
function upsertMemoryEmbeddingCache(params) {
const provider = params.provider;
const lastRows = /* @__PURE__ */ new Map();
let row = 0;
for (const entry of params.entries()) lastRows.set(entry.hash, row++);
const uniqueRows = [...lastRows].toSorted((left, right) => left[1] - right[1]);
const maxEntries = typeof params.maxEntries === "number" && Number.isFinite(params.maxEntries) && params.maxEntries > 0 ? Math.floor(params.maxEntries) : void 0;
const retainedRows = maxEntries === void 0 ? uniqueRows : uniqueRows.slice(-maxEntries);
if (retainedRows.length === 0) return;
if (maxEntries !== void 0) {
const db = getNodeSqliteKysely(params.db);
const hashes = retainedRows.map(([hash]) => hash);
for (let start = 0; start < hashes.length; start += 400) executeSqliteQuerySync(params.db, db.deleteFrom("memory_embedding_cache").where("provider", "=", provider.id).where("model", "=", provider.model).where("provider_key", "=", params.providerKey).where("hash", "in", hashes.slice(start, start + 400)));
const excess = countMemoryEmbeddingCache(params.db) - (maxEntries - hashes.length);
if (excess > 0) deleteOldestMemoryEmbeddingCacheRows(params.db, excess);
}
const now = params.now ?? Date.now();
const { compiled, bind } = compileSqliteQueryBindings((parameter) => getNodeSqliteKysely(params.db).insertInto("memory_embedding_cache").values({
provider: provider.id,
model: provider.model,
provider_key: params.providerKey,
hash: parameter((entry) => entry.hash),
embedding: parameter((entry) => encodeMemoryEmbedding(entry.embedding)),
dims: parameter((entry) => entry.embedding.length),
updated_at: now
}).onConflict((conflict) => conflict.columns([
"provider",
"model",
"provider_key",
"hash"
]).doUpdateSet((eb) => ({
embedding: eb.ref("excluded.embedding"),
dims: eb.ref("excluded.dims"),
updated_at: eb.ref("excluded.updated_at")
}))));
const statement = params.db.prepare(compiled.sql);
statement.setReadBigInts(true);
const retained = new Set(retainedRows.map(([, index]) => index));
row = 0;
for (const entry of params.entries()) {
if (!retained.has(row++)) continue;
statement.run(...bind(entry));
}
}
function collectMemoryCachedEmbeddings(params) {
const missing = [];
return {
embeddings: params.hashes.map((hash, index) => {
const hit = hash ? params.cached.get(hash) : void 0;
if (hit && hit.length > 0) return hit;
missing.push(index);
return [];
}),
missing
};
}
//#endregion
export { loadMemoryEmbeddingCache as a, isValidMemoryEmbedding as i, collectMemoryCachedEmbeddings as n, pruneMemoryEmbeddingCache as o, countMemoryEmbeddingCache as r, upsertMemoryEmbeddingCache as s, clearMemoryEmbeddingCacheIdentities as t };