@xdarkicex/openclaw-memory-libravdb 1.6.29 → 1.6.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +302 -21
- package/dist/memory-provider.js +18 -2
- package/dist/memory-runtime.d.ts +2 -1
- package/dist/memory-runtime.js +34 -18
- package/dist/memory-tools.d.ts +27 -0
- package/dist/memory-tools.js +251 -0
- package/openclaw.plugin.json +6 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25830,6 +25830,7 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
25830
25830
|
query: queryOrParams,
|
|
25831
25831
|
limit: opts.limit ?? opts.k ?? opts.maxResults ?? opts.topK,
|
|
25832
25832
|
minScore: opts.minScore,
|
|
25833
|
+
corpus: opts.corpus,
|
|
25833
25834
|
sessionId: opts.sessionId,
|
|
25834
25835
|
sessionKey: opts.sessionKey,
|
|
25835
25836
|
userId: opts.userId,
|
|
@@ -25841,6 +25842,7 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
25841
25842
|
return legacyCall ? { results: [], error: "Missing query text for LibraVDB memory search" } : [];
|
|
25842
25843
|
}
|
|
25843
25844
|
const dreamQuery = detectDreamQuerySignal(queryText);
|
|
25845
|
+
const searchCorpus = normalizeSearchCorpus(params.corpus);
|
|
25844
25846
|
const sessionId = firstString(params.sessionId, params.context?.sessionId);
|
|
25845
25847
|
const explicitUserId = firstString(params.userId, params.context?.userId);
|
|
25846
25848
|
const resolvedUserId = explicitUserId ?? getResolvedUserId(firstString(params.sessionKey, params.context?.sessionKey));
|
|
@@ -25853,17 +25855,19 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
25853
25855
|
const k = normalizePositiveInteger(params.k, params.limit, params.maxResults, params.topK, cfg.topK, 8);
|
|
25854
25856
|
const minScore = normalizeNumber(params.minScore);
|
|
25855
25857
|
const client = await getClient();
|
|
25856
|
-
const result = dreamQuery.active && cfg.crossSessionRecall !== false ? await client.searchText({
|
|
25858
|
+
const result = dreamQuery.active && cfg.crossSessionRecall !== false && searchCorpus !== "sessions" ? await client.searchText({
|
|
25857
25859
|
collection: resolveDreamCollection(userId),
|
|
25858
25860
|
text: queryText,
|
|
25859
25861
|
k
|
|
25860
|
-
}) : await searchResolvedCollections(client, cfg, userId, sessionId, queryText, k);
|
|
25862
|
+
}) : await searchResolvedCollections(client, cfg, userId, sessionId, queryText, k, searchCorpus);
|
|
25861
25863
|
const filteredResults = minScore === void 0 ? result.results : result.results.filter((item) => item.score >= minScore);
|
|
25862
25864
|
const legacyResults = filteredResults.map((item) => {
|
|
25863
25865
|
const meta = parseMetadataJson(item);
|
|
25866
|
+
const text = resolveSearchResultText(item, meta);
|
|
25864
25867
|
return {
|
|
25865
25868
|
...item,
|
|
25866
|
-
|
|
25869
|
+
text,
|
|
25870
|
+
content: text
|
|
25867
25871
|
};
|
|
25868
25872
|
});
|
|
25869
25873
|
if (legacyCall) {
|
|
@@ -25872,10 +25876,10 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
25872
25876
|
const memoryResults = filteredResults.map((item) => {
|
|
25873
25877
|
const meta = parseMetadataJson(item);
|
|
25874
25878
|
const collection = typeof meta.collection === "string" ? meta.collection : "memory";
|
|
25875
|
-
const effectiveText = item.text || (typeof meta.text === "string" ? meta.text : "") || "";
|
|
25876
25879
|
const relPath = encodeSearchResultPath(collection, item.id);
|
|
25877
|
-
|
|
25878
|
-
|
|
25880
|
+
const text = resolveSearchResultText(item, meta);
|
|
25881
|
+
returnedSearchPaths.set(relPath, text);
|
|
25882
|
+
return toMemorySearchResult(item, meta, text);
|
|
25879
25883
|
});
|
|
25880
25884
|
return memoryResults;
|
|
25881
25885
|
},
|
|
@@ -25916,8 +25920,8 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
25916
25920
|
}
|
|
25917
25921
|
};
|
|
25918
25922
|
}
|
|
25919
|
-
async function searchResolvedCollections(client, cfg, userId, sessionId, queryText, k) {
|
|
25920
|
-
const collections = resolveSearchCollections(cfg, userId, sessionId);
|
|
25923
|
+
async function searchResolvedCollections(client, cfg, userId, sessionId, queryText, k, corpus) {
|
|
25924
|
+
const collections = resolveSearchCollections(cfg, userId, sessionId, corpus);
|
|
25921
25925
|
if (collections.length === 0) {
|
|
25922
25926
|
return { results: [] };
|
|
25923
25927
|
}
|
|
@@ -25932,16 +25936,21 @@ async function searchResolvedCollections(client, cfg, userId, sessionId, queryTe
|
|
|
25932
25936
|
excludeByCollection: {}
|
|
25933
25937
|
});
|
|
25934
25938
|
}
|
|
25935
|
-
function resolveSearchCollections(cfg, userId, sessionId) {
|
|
25939
|
+
function resolveSearchCollections(cfg, userId, sessionId, corpus) {
|
|
25940
|
+
if (corpus === "sessions") {
|
|
25941
|
+
return sessionId ? [resolveSessionSearchCollection(cfg, sessionId)] : [];
|
|
25942
|
+
}
|
|
25943
|
+
const durableCollections = [resolveUserCollection(userId), "global"];
|
|
25944
|
+
if (corpus === "memory") {
|
|
25945
|
+
return durableCollections;
|
|
25946
|
+
}
|
|
25936
25947
|
if (cfg.crossSessionRecall === false) {
|
|
25937
25948
|
return sessionId ? [resolveSessionSearchCollection(cfg, sessionId)] : [];
|
|
25938
25949
|
}
|
|
25939
|
-
const collections = [resolveUserCollection(userId), "global"];
|
|
25940
25950
|
if (!sessionId) {
|
|
25941
|
-
return
|
|
25951
|
+
return durableCollections;
|
|
25942
25952
|
}
|
|
25943
|
-
|
|
25944
|
-
return collections;
|
|
25953
|
+
return [resolveSessionSearchCollection(cfg, sessionId), ...durableCollections];
|
|
25945
25954
|
}
|
|
25946
25955
|
function resolveSessionSearchCollection(cfg, sessionId) {
|
|
25947
25956
|
if (cfg.useSessionSummarySearchExperiment) {
|
|
@@ -25964,6 +25973,9 @@ function firstString(...values) {
|
|
|
25964
25973
|
}
|
|
25965
25974
|
return void 0;
|
|
25966
25975
|
}
|
|
25976
|
+
function normalizeSearchCorpus(value) {
|
|
25977
|
+
return value === "memory" || value === "sessions" ? value : "all";
|
|
25978
|
+
}
|
|
25967
25979
|
function parseMetadataJson(item) {
|
|
25968
25980
|
if (item.metadataJson && item.metadataJson.length > 0) {
|
|
25969
25981
|
try {
|
|
@@ -25973,16 +25985,20 @@ function parseMetadataJson(item) {
|
|
|
25973
25985
|
}
|
|
25974
25986
|
return {};
|
|
25975
25987
|
}
|
|
25976
|
-
function
|
|
25977
|
-
|
|
25988
|
+
function resolveSearchResultText(item, meta = parseMetadataJson(item)) {
|
|
25989
|
+
if (typeof item.text === "string" && item.text.length > 0) {
|
|
25990
|
+
return item.text;
|
|
25991
|
+
}
|
|
25992
|
+
return typeof meta.text === "string" ? meta.text : item.text;
|
|
25993
|
+
}
|
|
25994
|
+
function toMemorySearchResult(item, meta = parseMetadataJson(item), text = resolveSearchResultText(item, meta)) {
|
|
25978
25995
|
const collection = typeof meta.collection === "string" ? meta.collection : "memory";
|
|
25979
|
-
const effectiveText = item.text || (typeof meta.text === "string" ? meta.text : "") || "";
|
|
25980
25996
|
return {
|
|
25981
25997
|
path: encodeSearchResultPath(collection, item.id),
|
|
25982
25998
|
startLine: 1,
|
|
25983
|
-
endLine: Math.max(1,
|
|
25999
|
+
endLine: Math.max(1, text.split("\n").length),
|
|
25984
26000
|
score: item.score,
|
|
25985
|
-
snippet:
|
|
26001
|
+
snippet: text,
|
|
25986
26002
|
source: collection.startsWith("session:") || collection.startsWith("session_") ? "sessions" : "memory",
|
|
25987
26003
|
citation: `${collection}:${item.id}`
|
|
25988
26004
|
};
|
|
@@ -34727,12 +34743,271 @@ var MEMORY_PROMPT_HEADER = [
|
|
|
34727
34743
|
"in context via the context-engine assembler when available and relevant.",
|
|
34728
34744
|
""
|
|
34729
34745
|
];
|
|
34746
|
+
function buildToolGuidance(availableTools) {
|
|
34747
|
+
if (!availableTools?.has("memory_search")) {
|
|
34748
|
+
return [];
|
|
34749
|
+
}
|
|
34750
|
+
const lines = [
|
|
34751
|
+
"For explicit memory lookup requests, call `memory_search` first.",
|
|
34752
|
+
"Use it for prior turns, remembered facts, earliest interactions, and channel history.",
|
|
34753
|
+
"Do not answer memory lookup requests from prior transcript claims or earlier `memory_search` results; perform a fresh `memory_search` for the current request.",
|
|
34754
|
+
"For earliest or oldest memory questions, request enough results, compare timestamps in the returned snippets, and use `memory_get` if the snippet is not enough."
|
|
34755
|
+
];
|
|
34756
|
+
if (availableTools.has("memory_get")) {
|
|
34757
|
+
lines.push("After a `memory_search` hit, call `memory_get` when exact wording or more context is needed.");
|
|
34758
|
+
}
|
|
34759
|
+
lines.push(
|
|
34760
|
+
"Do not treat a missing `MEMORY.md` file as missing memory; LibraVDB memory is vector-backed and retrieved through the memory tools.",
|
|
34761
|
+
""
|
|
34762
|
+
);
|
|
34763
|
+
return lines;
|
|
34764
|
+
}
|
|
34730
34765
|
function buildMemoryPromptSection(_getClient, _cfg) {
|
|
34731
34766
|
return function memoryPromptSection({
|
|
34732
|
-
availableTools
|
|
34767
|
+
availableTools,
|
|
34733
34768
|
citationsMode: _citationsMode
|
|
34734
34769
|
}) {
|
|
34735
|
-
return [...MEMORY_PROMPT_HEADER];
|
|
34770
|
+
return [...MEMORY_PROMPT_HEADER, ...buildToolGuidance(availableTools)];
|
|
34771
|
+
};
|
|
34772
|
+
}
|
|
34773
|
+
|
|
34774
|
+
// src/memory-tools.ts
|
|
34775
|
+
var MEMORY_SEARCH_SCHEMA = {
|
|
34776
|
+
type: "object",
|
|
34777
|
+
additionalProperties: false,
|
|
34778
|
+
properties: {
|
|
34779
|
+
query: {
|
|
34780
|
+
type: "string",
|
|
34781
|
+
description: "Semantic recall query for prior work, preferences, decisions, dates, people, todos, or session context."
|
|
34782
|
+
},
|
|
34783
|
+
maxResults: {
|
|
34784
|
+
type: "number",
|
|
34785
|
+
minimum: 1,
|
|
34786
|
+
maximum: 50,
|
|
34787
|
+
description: "Maximum number of memory hits to return."
|
|
34788
|
+
},
|
|
34789
|
+
minScore: {
|
|
34790
|
+
type: "number",
|
|
34791
|
+
minimum: 0,
|
|
34792
|
+
maximum: 1,
|
|
34793
|
+
description: "Minimum similarity score for returned hits."
|
|
34794
|
+
},
|
|
34795
|
+
corpus: {
|
|
34796
|
+
type: "string",
|
|
34797
|
+
enum: ["memory", "wiki", "all", "sessions"],
|
|
34798
|
+
description: "Corpus filter. LibraVDB serves memory/session hits; wiki is unsupported unless another plugin owns wiki tools."
|
|
34799
|
+
}
|
|
34800
|
+
},
|
|
34801
|
+
required: ["query"]
|
|
34802
|
+
};
|
|
34803
|
+
var MEMORY_GET_SCHEMA = {
|
|
34804
|
+
type: "object",
|
|
34805
|
+
additionalProperties: false,
|
|
34806
|
+
properties: {
|
|
34807
|
+
path: {
|
|
34808
|
+
type: "string",
|
|
34809
|
+
description: "A path returned by memory_search."
|
|
34810
|
+
},
|
|
34811
|
+
from: {
|
|
34812
|
+
type: "number",
|
|
34813
|
+
minimum: 1,
|
|
34814
|
+
description: "1-based starting line."
|
|
34815
|
+
},
|
|
34816
|
+
lines: {
|
|
34817
|
+
type: "number",
|
|
34818
|
+
minimum: 1,
|
|
34819
|
+
description: "Maximum number of lines to read."
|
|
34820
|
+
},
|
|
34821
|
+
corpus: {
|
|
34822
|
+
type: "string",
|
|
34823
|
+
enum: ["memory", "wiki", "all"],
|
|
34824
|
+
description: "Corpus filter. LibraVDB reads paths returned by memory_search."
|
|
34825
|
+
}
|
|
34826
|
+
},
|
|
34827
|
+
required: ["path"]
|
|
34828
|
+
};
|
|
34829
|
+
function createLibraVdbMemoryTools(getClient, cfg, logger = console) {
|
|
34830
|
+
const bridge = buildMemoryRuntimeBridge(getClient, cfg);
|
|
34831
|
+
const managers = /* @__PURE__ */ new Map();
|
|
34832
|
+
async function getManager(ctx, purpose) {
|
|
34833
|
+
const key = managerCacheKey(ctx);
|
|
34834
|
+
let manager = managers.get(key);
|
|
34835
|
+
if (!manager) {
|
|
34836
|
+
manager = bridge.getMemorySearchManager({
|
|
34837
|
+
agentId: normalizeOptionalString(ctx.agentId),
|
|
34838
|
+
purpose
|
|
34839
|
+
}).then((result) => result.manager).catch((error2) => {
|
|
34840
|
+
managers.delete(key);
|
|
34841
|
+
throw error2;
|
|
34842
|
+
});
|
|
34843
|
+
managers.set(key, manager);
|
|
34844
|
+
}
|
|
34845
|
+
return await manager;
|
|
34846
|
+
}
|
|
34847
|
+
return {
|
|
34848
|
+
createSearchTool(ctx = {}) {
|
|
34849
|
+
return {
|
|
34850
|
+
name: "memory_search",
|
|
34851
|
+
label: "Memory Search",
|
|
34852
|
+
description: "Mandatory fresh LibraVDB recall step: semantically search durable memory and session recall before answering questions about prior work, decisions, dates, people, preferences, todos, or history. Do not reuse prior transcript claims or older memory_search results for a new memory lookup. For earliest/oldest questions, request enough results and compare timestamps in snippets. If response has disabled=true, memory retrieval is unavailable and should be surfaced to the user.",
|
|
34853
|
+
parameters: MEMORY_SEARCH_SCHEMA,
|
|
34854
|
+
execute: async (_toolCallId, rawParams) => {
|
|
34855
|
+
const params = asToolParamsRecord(rawParams);
|
|
34856
|
+
const query = readRequiredStringParam(params, "query");
|
|
34857
|
+
const corpus = readMemoryCorpus(params.corpus);
|
|
34858
|
+
const maxResults = readNumberParam(params, "maxResults", { integer: true });
|
|
34859
|
+
const minScore = readNumberParam(params, "minScore");
|
|
34860
|
+
if (corpus === "wiki") {
|
|
34861
|
+
return jsonToolResult({
|
|
34862
|
+
results: [],
|
|
34863
|
+
disabled: true,
|
|
34864
|
+
error: "LibraVDB memory_search does not provide the wiki corpus; use corpus=memory, corpus=sessions, or corpus=all."
|
|
34865
|
+
});
|
|
34866
|
+
}
|
|
34867
|
+
try {
|
|
34868
|
+
const manager = await getManager(ctx, "tool-search");
|
|
34869
|
+
const rawResults = await manager.search({
|
|
34870
|
+
query,
|
|
34871
|
+
corpus,
|
|
34872
|
+
...maxResults !== void 0 ? { maxResults } : {},
|
|
34873
|
+
...minScore !== void 0 ? { minScore } : {},
|
|
34874
|
+
...buildSearchContext(ctx)
|
|
34875
|
+
});
|
|
34876
|
+
const results = filterResultsByCorpus(rawResults, corpus);
|
|
34877
|
+
const status = manager.status();
|
|
34878
|
+
return jsonToolResult({
|
|
34879
|
+
results,
|
|
34880
|
+
provider: status.provider,
|
|
34881
|
+
model: status.model,
|
|
34882
|
+
backend: status.backend
|
|
34883
|
+
});
|
|
34884
|
+
} catch (error2) {
|
|
34885
|
+
logger.warn?.(`LibraVDB memory_search failed: ${formatError(error2)}`);
|
|
34886
|
+
return jsonToolResult({
|
|
34887
|
+
results: [],
|
|
34888
|
+
disabled: true,
|
|
34889
|
+
error: formatError(error2)
|
|
34890
|
+
});
|
|
34891
|
+
}
|
|
34892
|
+
}
|
|
34893
|
+
};
|
|
34894
|
+
},
|
|
34895
|
+
createGetTool(ctx = {}) {
|
|
34896
|
+
return {
|
|
34897
|
+
name: "memory_get",
|
|
34898
|
+
label: "Memory Get",
|
|
34899
|
+
description: "Read a bounded exact excerpt from a LibraVDB memory path returned by memory_search. Use this after memory_search when a hit needs exact wording or more context.",
|
|
34900
|
+
parameters: MEMORY_GET_SCHEMA,
|
|
34901
|
+
execute: async (_toolCallId, rawParams) => {
|
|
34902
|
+
const params = asToolParamsRecord(rawParams);
|
|
34903
|
+
const relPath = readRequiredStringParam(params, "path");
|
|
34904
|
+
const corpus = readMemoryGetCorpus(params.corpus);
|
|
34905
|
+
const from = readNumberParam(params, "from", { integer: true });
|
|
34906
|
+
const lines = readNumberParam(params, "lines", { integer: true });
|
|
34907
|
+
if (corpus === "wiki") {
|
|
34908
|
+
return jsonToolResult({
|
|
34909
|
+
path: relPath,
|
|
34910
|
+
text: "",
|
|
34911
|
+
disabled: true,
|
|
34912
|
+
error: "LibraVDB memory_get does not provide the wiki corpus; use paths returned by LibraVDB memory_search."
|
|
34913
|
+
});
|
|
34914
|
+
}
|
|
34915
|
+
try {
|
|
34916
|
+
const manager = await getManager(ctx, "tool-get");
|
|
34917
|
+
const result = await manager.readFile({
|
|
34918
|
+
relPath,
|
|
34919
|
+
...from !== void 0 ? { from } : {},
|
|
34920
|
+
...lines !== void 0 ? { lines } : {}
|
|
34921
|
+
});
|
|
34922
|
+
return jsonToolResult(result);
|
|
34923
|
+
} catch (error2) {
|
|
34924
|
+
logger.warn?.(`LibraVDB memory_get failed: ${formatError(error2)}`);
|
|
34925
|
+
return jsonToolResult({
|
|
34926
|
+
path: relPath,
|
|
34927
|
+
text: "",
|
|
34928
|
+
disabled: true,
|
|
34929
|
+
error: formatError(error2)
|
|
34930
|
+
});
|
|
34931
|
+
}
|
|
34932
|
+
}
|
|
34933
|
+
};
|
|
34934
|
+
}
|
|
34935
|
+
};
|
|
34936
|
+
}
|
|
34937
|
+
function buildSearchContext(ctx) {
|
|
34938
|
+
const agentId = normalizeOptionalString(ctx.agentId);
|
|
34939
|
+
const sessionId = normalizeOptionalString(ctx.sessionId);
|
|
34940
|
+
const sessionKey = normalizeOptionalString(ctx.sessionKey);
|
|
34941
|
+
return {
|
|
34942
|
+
...agentId ? { agentId } : {},
|
|
34943
|
+
...sessionId ? { sessionId } : {},
|
|
34944
|
+
...sessionKey ? { sessionKey } : {},
|
|
34945
|
+
context: {
|
|
34946
|
+
...agentId ? { agentId } : {},
|
|
34947
|
+
...sessionId ? { sessionId } : {},
|
|
34948
|
+
...sessionKey ? { sessionKey } : {}
|
|
34949
|
+
}
|
|
34950
|
+
};
|
|
34951
|
+
}
|
|
34952
|
+
function filterResultsByCorpus(results, corpus) {
|
|
34953
|
+
if (corpus === "sessions") {
|
|
34954
|
+
return results.filter((result) => result.source === "sessions");
|
|
34955
|
+
}
|
|
34956
|
+
if (corpus === "memory") {
|
|
34957
|
+
return results.filter((result) => result.source === "memory");
|
|
34958
|
+
}
|
|
34959
|
+
return results;
|
|
34960
|
+
}
|
|
34961
|
+
function managerCacheKey(ctx) {
|
|
34962
|
+
return [
|
|
34963
|
+
normalizeOptionalString(ctx.agentId) ?? "",
|
|
34964
|
+
normalizeOptionalString(ctx.sessionId) ?? "",
|
|
34965
|
+
normalizeOptionalString(ctx.sessionKey) ?? ""
|
|
34966
|
+
].join("\0");
|
|
34967
|
+
}
|
|
34968
|
+
function asToolParamsRecord(value) {
|
|
34969
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
34970
|
+
return {};
|
|
34971
|
+
}
|
|
34972
|
+
return value;
|
|
34973
|
+
}
|
|
34974
|
+
function readRequiredStringParam(params, key) {
|
|
34975
|
+
const value = normalizeOptionalString(params[key]);
|
|
34976
|
+
if (!value) {
|
|
34977
|
+
throw new Error(`memory tool requires ${key}`);
|
|
34978
|
+
}
|
|
34979
|
+
return value;
|
|
34980
|
+
}
|
|
34981
|
+
function readNumberParam(params, key, options = {}) {
|
|
34982
|
+
const value = params[key];
|
|
34983
|
+
const parsed = typeof value === "number" ? value : typeof value === "string" && value.trim().length > 0 ? Number(value) : void 0;
|
|
34984
|
+
if (parsed === void 0 || !Number.isFinite(parsed)) {
|
|
34985
|
+
return void 0;
|
|
34986
|
+
}
|
|
34987
|
+
return options.integer ? Math.max(1, Math.floor(parsed)) : parsed;
|
|
34988
|
+
}
|
|
34989
|
+
function readMemoryCorpus(value) {
|
|
34990
|
+
return value === "memory" || value === "wiki" || value === "all" || value === "sessions" ? value : "all";
|
|
34991
|
+
}
|
|
34992
|
+
function readMemoryGetCorpus(value) {
|
|
34993
|
+
return value === "memory" || value === "wiki" || value === "all" ? value : "memory";
|
|
34994
|
+
}
|
|
34995
|
+
function normalizeOptionalString(value) {
|
|
34996
|
+
if (typeof value !== "string") {
|
|
34997
|
+
return void 0;
|
|
34998
|
+
}
|
|
34999
|
+
const trimmed = value.trim();
|
|
35000
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
35001
|
+
}
|
|
35002
|
+
function jsonToolResult(details) {
|
|
35003
|
+
return {
|
|
35004
|
+
content: [
|
|
35005
|
+
{
|
|
35006
|
+
type: "text",
|
|
35007
|
+
text: JSON.stringify(details, null, 2)
|
|
35008
|
+
}
|
|
35009
|
+
],
|
|
35010
|
+
details
|
|
34736
35011
|
};
|
|
34737
35012
|
}
|
|
34738
35013
|
|
|
@@ -38061,7 +38336,7 @@ function enrichStartupError(error2, healthMessage) {
|
|
|
38061
38336
|
// src/index.ts
|
|
38062
38337
|
var MEMORY_ID = "libravdb-memory";
|
|
38063
38338
|
var LIGHTWEIGHT_MODES = /* @__PURE__ */ new Set(["cli-metadata", "setup-only"]);
|
|
38064
|
-
var RUNTIME_CLEANUP_SHUTDOWN_REASONS = /* @__PURE__ */ new Set(["delete"
|
|
38339
|
+
var RUNTIME_CLEANUP_SHUTDOWN_REASONS = /* @__PURE__ */ new Set(["delete"]);
|
|
38065
38340
|
function shouldShutdownRuntimeForLifecycleCleanup(reason) {
|
|
38066
38341
|
return RUNTIME_CLEANUP_SHUTDOWN_REASONS.has(reason);
|
|
38067
38342
|
}
|
|
@@ -38095,6 +38370,12 @@ function register(api) {
|
|
|
38095
38370
|
}
|
|
38096
38371
|
const runtimeOrNull = isLightweight ? null : createPluginRuntime(cfg, logger);
|
|
38097
38372
|
registerMemoryCli(api, runtimeOrNull, cfg, logger);
|
|
38373
|
+
const ownsMemorySlot = memSlot === MEMORY_ID;
|
|
38374
|
+
if (runtimeOrNull && ownsMemorySlot) {
|
|
38375
|
+
const memoryTools = createLibraVdbMemoryTools(runtimeOrNull.getClient, cfg, logger);
|
|
38376
|
+
api.registerTool?.((ctx) => memoryTools.createSearchTool(ctx), { names: ["memory_search"] });
|
|
38377
|
+
api.registerTool?.((ctx) => memoryTools.createGetTool(ctx), { names: ["memory_get"] });
|
|
38378
|
+
}
|
|
38098
38379
|
if (isLightweight || isDiscovery) {
|
|
38099
38380
|
if (!isLightweight) {
|
|
38100
38381
|
logger.info?.(
|
package/dist/memory-provider.js
CHANGED
|
@@ -4,10 +4,26 @@ const MEMORY_PROMPT_HEADER = [
|
|
|
4
4
|
"in context via the context-engine assembler when available and relevant.",
|
|
5
5
|
"",
|
|
6
6
|
];
|
|
7
|
+
function buildToolGuidance(availableTools) {
|
|
8
|
+
if (!availableTools?.has("memory_search")) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
const lines = [
|
|
12
|
+
"For explicit memory lookup requests, call `memory_search` first.",
|
|
13
|
+
"Use it for prior turns, remembered facts, earliest interactions, and channel history.",
|
|
14
|
+
"Do not answer memory lookup requests from prior transcript claims or earlier `memory_search` results; perform a fresh `memory_search` for the current request.",
|
|
15
|
+
"For earliest or oldest memory questions, request enough results, compare timestamps in the returned snippets, and use `memory_get` if the snippet is not enough.",
|
|
16
|
+
];
|
|
17
|
+
if (availableTools.has("memory_get")) {
|
|
18
|
+
lines.push("After a `memory_search` hit, call `memory_get` when exact wording or more context is needed.");
|
|
19
|
+
}
|
|
20
|
+
lines.push("Do not treat a missing `MEMORY.md` file as missing memory; LibraVDB memory is vector-backed and retrieved through the memory tools.", "");
|
|
21
|
+
return lines;
|
|
22
|
+
}
|
|
7
23
|
export function buildMemoryPromptSection(_getClient, _cfg) {
|
|
8
|
-
return function memoryPromptSection({ availableTools
|
|
24
|
+
return function memoryPromptSection({ availableTools, citationsMode: _citationsMode, }) {
|
|
9
25
|
// OpenClaw builds the memory prompt section synchronously for embedded runs.
|
|
10
26
|
// Actual retrieval and ranking happen in the context engine during assemble().
|
|
11
|
-
return [...MEMORY_PROMPT_HEADER];
|
|
27
|
+
return [...MEMORY_PROMPT_HEADER, ...buildToolGuidance(availableTools)];
|
|
12
28
|
};
|
|
13
29
|
}
|
package/dist/memory-runtime.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ type MemorySearchParams = {
|
|
|
10
10
|
maxResults?: number;
|
|
11
11
|
minScore?: number;
|
|
12
12
|
topK?: number;
|
|
13
|
+
corpus?: "all" | "memory" | "sessions";
|
|
13
14
|
userId?: string;
|
|
14
15
|
agentId?: string;
|
|
15
16
|
sessionId?: string;
|
|
@@ -49,10 +50,10 @@ export declare function buildMemoryRuntimeBridge(getClient: ClientGetter, cfg: P
|
|
|
49
50
|
error: string;
|
|
50
51
|
} | {
|
|
51
52
|
results: {
|
|
53
|
+
text: string;
|
|
52
54
|
content: string;
|
|
53
55
|
id: string;
|
|
54
56
|
score: number;
|
|
55
|
-
text: string;
|
|
56
57
|
metadataJson: Uint8Array<ArrayBuffer>;
|
|
57
58
|
version: bigint;
|
|
58
59
|
}[];
|
package/dist/memory-runtime.js
CHANGED
|
@@ -39,6 +39,7 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
39
39
|
query: queryOrParams,
|
|
40
40
|
limit: opts.limit ?? opts.k ?? opts.maxResults ?? opts.topK,
|
|
41
41
|
minScore: opts.minScore,
|
|
42
|
+
corpus: opts.corpus,
|
|
42
43
|
sessionId: opts.sessionId,
|
|
43
44
|
sessionKey: opts.sessionKey,
|
|
44
45
|
userId: opts.userId,
|
|
@@ -51,6 +52,7 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
51
52
|
return legacyCall ? { results: [], error: "Missing query text for LibraVDB memory search" } : [];
|
|
52
53
|
}
|
|
53
54
|
const dreamQuery = detectDreamQuerySignal(queryText);
|
|
55
|
+
const searchCorpus = normalizeSearchCorpus(params.corpus);
|
|
54
56
|
const sessionId = firstString(params.sessionId, params.context?.sessionId);
|
|
55
57
|
const explicitUserId = firstString(params.userId, params.context?.userId);
|
|
56
58
|
const resolvedUserId = explicitUserId ??
|
|
@@ -64,21 +66,23 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
64
66
|
const k = normalizePositiveInteger(params.k, params.limit, params.maxResults, params.topK, cfg.topK, 8);
|
|
65
67
|
const minScore = normalizeNumber(params.minScore);
|
|
66
68
|
const client = await getClient();
|
|
67
|
-
const result = dreamQuery.active && cfg.crossSessionRecall !== false
|
|
69
|
+
const result = dreamQuery.active && cfg.crossSessionRecall !== false && searchCorpus !== "sessions"
|
|
68
70
|
? await client.searchText({
|
|
69
71
|
collection: resolveDreamCollection(userId),
|
|
70
72
|
text: queryText,
|
|
71
73
|
k,
|
|
72
74
|
})
|
|
73
|
-
: await searchResolvedCollections(client, cfg, userId, sessionId, queryText, k);
|
|
75
|
+
: await searchResolvedCollections(client, cfg, userId, sessionId, queryText, k, searchCorpus);
|
|
74
76
|
const filteredResults = minScore === undefined
|
|
75
77
|
? result.results
|
|
76
78
|
: result.results.filter((item) => item.score >= minScore);
|
|
77
79
|
const legacyResults = filteredResults.map((item) => {
|
|
78
80
|
const meta = parseMetadataJson(item);
|
|
81
|
+
const text = resolveSearchResultText(item, meta);
|
|
79
82
|
return {
|
|
80
83
|
...item,
|
|
81
|
-
|
|
84
|
+
text,
|
|
85
|
+
content: text,
|
|
82
86
|
};
|
|
83
87
|
});
|
|
84
88
|
if (legacyCall) {
|
|
@@ -87,10 +91,10 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
87
91
|
const memoryResults = filteredResults.map((item) => {
|
|
88
92
|
const meta = parseMetadataJson(item);
|
|
89
93
|
const collection = typeof meta.collection === "string" ? meta.collection : "memory";
|
|
90
|
-
const effectiveText = item.text || (typeof meta.text === "string" ? meta.text : "") || "";
|
|
91
94
|
const relPath = encodeSearchResultPath(collection, item.id);
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
const text = resolveSearchResultText(item, meta);
|
|
96
|
+
returnedSearchPaths.set(relPath, text);
|
|
97
|
+
return toMemorySearchResult(item, meta, text);
|
|
94
98
|
});
|
|
95
99
|
return memoryResults;
|
|
96
100
|
},
|
|
@@ -134,8 +138,8 @@ function createMemorySearchManager(getClient, cfg, defaults, initialStatus) {
|
|
|
134
138
|
},
|
|
135
139
|
};
|
|
136
140
|
}
|
|
137
|
-
async function searchResolvedCollections(client, cfg, userId, sessionId, queryText, k) {
|
|
138
|
-
const collections = resolveSearchCollections(cfg, userId, sessionId);
|
|
141
|
+
async function searchResolvedCollections(client, cfg, userId, sessionId, queryText, k, corpus) {
|
|
142
|
+
const collections = resolveSearchCollections(cfg, userId, sessionId, corpus);
|
|
139
143
|
if (collections.length === 0) {
|
|
140
144
|
return { results: [] };
|
|
141
145
|
}
|
|
@@ -152,16 +156,21 @@ async function searchResolvedCollections(client, cfg, userId, sessionId, queryTe
|
|
|
152
156
|
excludeByCollection: {},
|
|
153
157
|
});
|
|
154
158
|
}
|
|
155
|
-
function resolveSearchCollections(cfg, userId, sessionId) {
|
|
159
|
+
function resolveSearchCollections(cfg, userId, sessionId, corpus) {
|
|
160
|
+
if (corpus === "sessions") {
|
|
161
|
+
return sessionId ? [resolveSessionSearchCollection(cfg, sessionId)] : [];
|
|
162
|
+
}
|
|
163
|
+
const durableCollections = [resolveUserCollection(userId), "global"];
|
|
164
|
+
if (corpus === "memory") {
|
|
165
|
+
return durableCollections;
|
|
166
|
+
}
|
|
156
167
|
if (cfg.crossSessionRecall === false) {
|
|
157
168
|
return sessionId ? [resolveSessionSearchCollection(cfg, sessionId)] : [];
|
|
158
169
|
}
|
|
159
|
-
const collections = [resolveUserCollection(userId), "global"];
|
|
160
170
|
if (!sessionId) {
|
|
161
|
-
return
|
|
171
|
+
return durableCollections;
|
|
162
172
|
}
|
|
163
|
-
|
|
164
|
-
return collections;
|
|
173
|
+
return [resolveSessionSearchCollection(cfg, sessionId), ...durableCollections];
|
|
165
174
|
}
|
|
166
175
|
function resolveSessionSearchCollection(cfg, sessionId) {
|
|
167
176
|
if (cfg.useSessionSummarySearchExperiment) {
|
|
@@ -184,6 +193,9 @@ function firstString(...values) {
|
|
|
184
193
|
}
|
|
185
194
|
return undefined;
|
|
186
195
|
}
|
|
196
|
+
function normalizeSearchCorpus(value) {
|
|
197
|
+
return value === "memory" || value === "sessions" ? value : "all";
|
|
198
|
+
}
|
|
187
199
|
function parseMetadataJson(item) {
|
|
188
200
|
if (item.metadataJson && item.metadataJson.length > 0) {
|
|
189
201
|
try {
|
|
@@ -195,16 +207,20 @@ function parseMetadataJson(item) {
|
|
|
195
207
|
}
|
|
196
208
|
return {};
|
|
197
209
|
}
|
|
198
|
-
function
|
|
199
|
-
|
|
210
|
+
function resolveSearchResultText(item, meta = parseMetadataJson(item)) {
|
|
211
|
+
if (typeof item.text === "string" && item.text.length > 0) {
|
|
212
|
+
return item.text;
|
|
213
|
+
}
|
|
214
|
+
return typeof meta.text === "string" ? meta.text : item.text;
|
|
215
|
+
}
|
|
216
|
+
function toMemorySearchResult(item, meta = parseMetadataJson(item), text = resolveSearchResultText(item, meta)) {
|
|
200
217
|
const collection = typeof meta.collection === "string" ? meta.collection : "memory";
|
|
201
|
-
const effectiveText = item.text || (typeof meta.text === "string" ? meta.text : "") || "";
|
|
202
218
|
return {
|
|
203
219
|
path: encodeSearchResultPath(collection, item.id),
|
|
204
220
|
startLine: 1,
|
|
205
|
-
endLine: Math.max(1,
|
|
221
|
+
endLine: Math.max(1, text.split("\n").length),
|
|
206
222
|
score: item.score,
|
|
207
|
-
snippet:
|
|
223
|
+
snippet: text,
|
|
208
224
|
source: collection.startsWith("session:") || collection.startsWith("session_") ? "sessions" : "memory",
|
|
209
225
|
citation: `${collection}:${item.id}`,
|
|
210
226
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ClientGetter } from "./plugin-runtime.js";
|
|
2
|
+
import type { LoggerLike, PluginConfig } from "./types.js";
|
|
3
|
+
type MemoryToolContext = {
|
|
4
|
+
agentId?: string;
|
|
5
|
+
sessionId?: string;
|
|
6
|
+
sessionKey?: string;
|
|
7
|
+
};
|
|
8
|
+
type ToolContent = {
|
|
9
|
+
type: "text";
|
|
10
|
+
text: string;
|
|
11
|
+
};
|
|
12
|
+
type ToolResult<TDetails> = {
|
|
13
|
+
content: ToolContent[];
|
|
14
|
+
details: TDetails;
|
|
15
|
+
};
|
|
16
|
+
type AgentTool = {
|
|
17
|
+
name: string;
|
|
18
|
+
label: string;
|
|
19
|
+
description: string;
|
|
20
|
+
parameters: unknown;
|
|
21
|
+
execute(toolCallId: string, params: unknown): Promise<ToolResult<unknown>>;
|
|
22
|
+
};
|
|
23
|
+
export declare function createLibraVdbMemoryTools(getClient: ClientGetter, cfg: PluginConfig, logger?: LoggerLike): {
|
|
24
|
+
createSearchTool(ctx?: MemoryToolContext): AgentTool;
|
|
25
|
+
createGetTool(ctx?: MemoryToolContext): AgentTool;
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { formatError } from "./format-error.js";
|
|
2
|
+
import { buildMemoryRuntimeBridge } from "./memory-runtime.js";
|
|
3
|
+
const MEMORY_SEARCH_SCHEMA = {
|
|
4
|
+
type: "object",
|
|
5
|
+
additionalProperties: false,
|
|
6
|
+
properties: {
|
|
7
|
+
query: {
|
|
8
|
+
type: "string",
|
|
9
|
+
description: "Semantic recall query for prior work, preferences, decisions, dates, people, todos, or session context.",
|
|
10
|
+
},
|
|
11
|
+
maxResults: {
|
|
12
|
+
type: "number",
|
|
13
|
+
minimum: 1,
|
|
14
|
+
maximum: 50,
|
|
15
|
+
description: "Maximum number of memory hits to return.",
|
|
16
|
+
},
|
|
17
|
+
minScore: {
|
|
18
|
+
type: "number",
|
|
19
|
+
minimum: 0,
|
|
20
|
+
maximum: 1,
|
|
21
|
+
description: "Minimum similarity score for returned hits.",
|
|
22
|
+
},
|
|
23
|
+
corpus: {
|
|
24
|
+
type: "string",
|
|
25
|
+
enum: ["memory", "wiki", "all", "sessions"],
|
|
26
|
+
description: "Corpus filter. LibraVDB serves memory/session hits; wiki is unsupported unless another plugin owns wiki tools.",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ["query"],
|
|
30
|
+
};
|
|
31
|
+
const MEMORY_GET_SCHEMA = {
|
|
32
|
+
type: "object",
|
|
33
|
+
additionalProperties: false,
|
|
34
|
+
properties: {
|
|
35
|
+
path: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "A path returned by memory_search.",
|
|
38
|
+
},
|
|
39
|
+
from: {
|
|
40
|
+
type: "number",
|
|
41
|
+
minimum: 1,
|
|
42
|
+
description: "1-based starting line.",
|
|
43
|
+
},
|
|
44
|
+
lines: {
|
|
45
|
+
type: "number",
|
|
46
|
+
minimum: 1,
|
|
47
|
+
description: "Maximum number of lines to read.",
|
|
48
|
+
},
|
|
49
|
+
corpus: {
|
|
50
|
+
type: "string",
|
|
51
|
+
enum: ["memory", "wiki", "all"],
|
|
52
|
+
description: "Corpus filter. LibraVDB reads paths returned by memory_search.",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
required: ["path"],
|
|
56
|
+
};
|
|
57
|
+
export function createLibraVdbMemoryTools(getClient, cfg, logger = console) {
|
|
58
|
+
const bridge = buildMemoryRuntimeBridge(getClient, cfg);
|
|
59
|
+
const managers = new Map();
|
|
60
|
+
async function getManager(ctx, purpose) {
|
|
61
|
+
const key = managerCacheKey(ctx);
|
|
62
|
+
let manager = managers.get(key);
|
|
63
|
+
if (!manager) {
|
|
64
|
+
manager = bridge
|
|
65
|
+
.getMemorySearchManager({
|
|
66
|
+
agentId: normalizeOptionalString(ctx.agentId),
|
|
67
|
+
purpose,
|
|
68
|
+
})
|
|
69
|
+
.then((result) => result.manager)
|
|
70
|
+
.catch((error) => {
|
|
71
|
+
managers.delete(key);
|
|
72
|
+
throw error;
|
|
73
|
+
});
|
|
74
|
+
managers.set(key, manager);
|
|
75
|
+
}
|
|
76
|
+
return await manager;
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
createSearchTool(ctx = {}) {
|
|
80
|
+
return {
|
|
81
|
+
name: "memory_search",
|
|
82
|
+
label: "Memory Search",
|
|
83
|
+
description: "Mandatory fresh LibraVDB recall step: semantically search durable memory and session recall before answering questions about prior work, decisions, dates, people, preferences, todos, or history. Do not reuse prior transcript claims or older memory_search results for a new memory lookup. For earliest/oldest questions, request enough results and compare timestamps in snippets. If response has disabled=true, memory retrieval is unavailable and should be surfaced to the user.",
|
|
84
|
+
parameters: MEMORY_SEARCH_SCHEMA,
|
|
85
|
+
execute: async (_toolCallId, rawParams) => {
|
|
86
|
+
const params = asToolParamsRecord(rawParams);
|
|
87
|
+
const query = readRequiredStringParam(params, "query");
|
|
88
|
+
const corpus = readMemoryCorpus(params.corpus);
|
|
89
|
+
const maxResults = readNumberParam(params, "maxResults", { integer: true });
|
|
90
|
+
const minScore = readNumberParam(params, "minScore");
|
|
91
|
+
if (corpus === "wiki") {
|
|
92
|
+
return jsonToolResult({
|
|
93
|
+
results: [],
|
|
94
|
+
disabled: true,
|
|
95
|
+
error: "LibraVDB memory_search does not provide the wiki corpus; use corpus=memory, corpus=sessions, or corpus=all.",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const manager = await getManager(ctx, "tool-search");
|
|
100
|
+
const rawResults = await manager.search({
|
|
101
|
+
query,
|
|
102
|
+
corpus,
|
|
103
|
+
...(maxResults !== undefined ? { maxResults } : {}),
|
|
104
|
+
...(minScore !== undefined ? { minScore } : {}),
|
|
105
|
+
...buildSearchContext(ctx),
|
|
106
|
+
});
|
|
107
|
+
const results = filterResultsByCorpus(rawResults, corpus);
|
|
108
|
+
const status = manager.status();
|
|
109
|
+
return jsonToolResult({
|
|
110
|
+
results,
|
|
111
|
+
provider: status.provider,
|
|
112
|
+
model: status.model,
|
|
113
|
+
backend: status.backend,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
logger.warn?.(`LibraVDB memory_search failed: ${formatError(error)}`);
|
|
118
|
+
return jsonToolResult({
|
|
119
|
+
results: [],
|
|
120
|
+
disabled: true,
|
|
121
|
+
error: formatError(error),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
createGetTool(ctx = {}) {
|
|
128
|
+
return {
|
|
129
|
+
name: "memory_get",
|
|
130
|
+
label: "Memory Get",
|
|
131
|
+
description: "Read a bounded exact excerpt from a LibraVDB memory path returned by memory_search. Use this after memory_search when a hit needs exact wording or more context.",
|
|
132
|
+
parameters: MEMORY_GET_SCHEMA,
|
|
133
|
+
execute: async (_toolCallId, rawParams) => {
|
|
134
|
+
const params = asToolParamsRecord(rawParams);
|
|
135
|
+
const relPath = readRequiredStringParam(params, "path");
|
|
136
|
+
const corpus = readMemoryGetCorpus(params.corpus);
|
|
137
|
+
const from = readNumberParam(params, "from", { integer: true });
|
|
138
|
+
const lines = readNumberParam(params, "lines", { integer: true });
|
|
139
|
+
if (corpus === "wiki") {
|
|
140
|
+
return jsonToolResult({
|
|
141
|
+
path: relPath,
|
|
142
|
+
text: "",
|
|
143
|
+
disabled: true,
|
|
144
|
+
error: "LibraVDB memory_get does not provide the wiki corpus; use paths returned by LibraVDB memory_search.",
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const manager = await getManager(ctx, "tool-get");
|
|
149
|
+
const result = await manager.readFile({
|
|
150
|
+
relPath,
|
|
151
|
+
...(from !== undefined ? { from } : {}),
|
|
152
|
+
...(lines !== undefined ? { lines } : {}),
|
|
153
|
+
});
|
|
154
|
+
return jsonToolResult(result);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
logger.warn?.(`LibraVDB memory_get failed: ${formatError(error)}`);
|
|
158
|
+
return jsonToolResult({
|
|
159
|
+
path: relPath,
|
|
160
|
+
text: "",
|
|
161
|
+
disabled: true,
|
|
162
|
+
error: formatError(error),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function buildSearchContext(ctx) {
|
|
171
|
+
const agentId = normalizeOptionalString(ctx.agentId);
|
|
172
|
+
const sessionId = normalizeOptionalString(ctx.sessionId);
|
|
173
|
+
const sessionKey = normalizeOptionalString(ctx.sessionKey);
|
|
174
|
+
return {
|
|
175
|
+
...(agentId ? { agentId } : {}),
|
|
176
|
+
...(sessionId ? { sessionId } : {}),
|
|
177
|
+
...(sessionKey ? { sessionKey } : {}),
|
|
178
|
+
context: {
|
|
179
|
+
...(agentId ? { agentId } : {}),
|
|
180
|
+
...(sessionId ? { sessionId } : {}),
|
|
181
|
+
...(sessionKey ? { sessionKey } : {}),
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function filterResultsByCorpus(results, corpus) {
|
|
186
|
+
if (corpus === "sessions") {
|
|
187
|
+
return results.filter((result) => result.source === "sessions");
|
|
188
|
+
}
|
|
189
|
+
if (corpus === "memory") {
|
|
190
|
+
return results.filter((result) => result.source === "memory");
|
|
191
|
+
}
|
|
192
|
+
return results;
|
|
193
|
+
}
|
|
194
|
+
function managerCacheKey(ctx) {
|
|
195
|
+
return [
|
|
196
|
+
normalizeOptionalString(ctx.agentId) ?? "",
|
|
197
|
+
normalizeOptionalString(ctx.sessionId) ?? "",
|
|
198
|
+
normalizeOptionalString(ctx.sessionKey) ?? "",
|
|
199
|
+
].join("\0");
|
|
200
|
+
}
|
|
201
|
+
function asToolParamsRecord(value) {
|
|
202
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
203
|
+
return {};
|
|
204
|
+
}
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
function readRequiredStringParam(params, key) {
|
|
208
|
+
const value = normalizeOptionalString(params[key]);
|
|
209
|
+
if (!value) {
|
|
210
|
+
throw new Error(`memory tool requires ${key}`);
|
|
211
|
+
}
|
|
212
|
+
return value;
|
|
213
|
+
}
|
|
214
|
+
function readNumberParam(params, key, options = {}) {
|
|
215
|
+
const value = params[key];
|
|
216
|
+
const parsed = typeof value === "number"
|
|
217
|
+
? value
|
|
218
|
+
: typeof value === "string" && value.trim().length > 0
|
|
219
|
+
? Number(value)
|
|
220
|
+
: undefined;
|
|
221
|
+
if (parsed === undefined || !Number.isFinite(parsed)) {
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
return options.integer ? Math.max(1, Math.floor(parsed)) : parsed;
|
|
225
|
+
}
|
|
226
|
+
function readMemoryCorpus(value) {
|
|
227
|
+
return value === "memory" || value === "wiki" || value === "all" || value === "sessions"
|
|
228
|
+
? value
|
|
229
|
+
: "all";
|
|
230
|
+
}
|
|
231
|
+
function readMemoryGetCorpus(value) {
|
|
232
|
+
return value === "memory" || value === "wiki" || value === "all" ? value : "memory";
|
|
233
|
+
}
|
|
234
|
+
function normalizeOptionalString(value) {
|
|
235
|
+
if (typeof value !== "string") {
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
const trimmed = value.trim();
|
|
239
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
240
|
+
}
|
|
241
|
+
function jsonToolResult(details) {
|
|
242
|
+
return {
|
|
243
|
+
content: [
|
|
244
|
+
{
|
|
245
|
+
type: "text",
|
|
246
|
+
text: JSON.stringify(details, null, 2),
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
details,
|
|
250
|
+
};
|
|
251
|
+
}
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
"id": "libravdb-memory",
|
|
3
3
|
"name": "LibraVDB Memory",
|
|
4
4
|
"description": "Persistent vector memory with three-tier hybrid scoring",
|
|
5
|
-
"version": "1.6.
|
|
5
|
+
"version": "1.6.30",
|
|
6
6
|
"kind": [
|
|
7
7
|
"memory",
|
|
8
8
|
"context-engine"
|
|
9
9
|
],
|
|
10
10
|
"contracts": {
|
|
11
11
|
"memory": true,
|
|
12
|
-
"contextEngine": true
|
|
12
|
+
"contextEngine": true,
|
|
13
|
+
"tools": [
|
|
14
|
+
"memory_search",
|
|
15
|
+
"memory_get"
|
|
16
|
+
]
|
|
13
17
|
},
|
|
14
18
|
"activation": {
|
|
15
19
|
"onCommands": [
|