@xdarkicex/openclaw-memory-libravdb 1.9.10-beta.17 → 1.9.10-beta.19
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/context-engine.d.ts +5 -0
- package/dist/context-engine.js +23 -0
- package/dist/index.js +214 -76
- package/dist/libravdb-client.d.ts +2 -1
- package/dist/libravdb-client.js +4 -0
- package/dist/tools/memory-recall.d.ts +21 -0
- package/dist/tools/memory-recall.js +55 -0
- package/openclaw.plugin.json +5 -3
- package/package.json +1 -1
package/dist/context-engine.d.ts
CHANGED
|
@@ -20,6 +20,11 @@ type OpenClawCompatibleAssembleResult = {
|
|
|
20
20
|
promptAuthority: OpenClawCompatiblePromptAuthority;
|
|
21
21
|
debug?: AssembleContextInternalResponse["debug"];
|
|
22
22
|
};
|
|
23
|
+
export interface Speaker {
|
|
24
|
+
name: string;
|
|
25
|
+
displayName: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function extractSpeakers(messages: OpenClawCompatibleMessage[]): Speaker[];
|
|
23
28
|
type OpenClawCompatibleCompactResult = {
|
|
24
29
|
ok: boolean;
|
|
25
30
|
compacted: boolean;
|
package/dist/context-engine.js
CHANGED
|
@@ -24,6 +24,29 @@ const SELECTED_CONTEXT_HEADER = "Conversation context (untrusted, chronological,
|
|
|
24
24
|
const RETRIEVAL_QUERY_MAX_CHARS = 1000;
|
|
25
25
|
const SELECTED_CONTEXT_TURN_RE = /^#\d+\s+[A-Za-z]{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}(?::\d{2})?\s+\S+\s+([^:\n]{1,80}):\s*(.*)$/;
|
|
26
26
|
const ASSISTANT_SPEAKER_RE = /\b(?:assistant|openclaw|z3robot|bot)\b/i;
|
|
27
|
+
// Multi-speaker envelope regex: matches [HH:MM] Speaker: text
|
|
28
|
+
const MULTI_SPEAKER_LINE_RE = /^\[\d{2}:\d{2}\]\s+(\S[^:]{0,80}):\s/;
|
|
29
|
+
export function extractSpeakers(messages) {
|
|
30
|
+
const seen = new Set();
|
|
31
|
+
const speakers = [];
|
|
32
|
+
for (const msg of messages) {
|
|
33
|
+
if (msg.role !== "user")
|
|
34
|
+
continue;
|
|
35
|
+
const text = normalizeKernelContent(msg.content);
|
|
36
|
+
for (const line of text.split("\n")) {
|
|
37
|
+
const match = line.match(MULTI_SPEAKER_LINE_RE);
|
|
38
|
+
if (match) {
|
|
39
|
+
const displayName = match[1].trim();
|
|
40
|
+
const name = displayName.toLowerCase();
|
|
41
|
+
if (name && !ASSISTANT_SPEAKER_RE.test(name) && !seen.has(name)) {
|
|
42
|
+
seen.add(name);
|
|
43
|
+
speakers.push({ name, displayName });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return speakers;
|
|
49
|
+
}
|
|
27
50
|
const OPENCLAW_METADATA_HEADERS = [
|
|
28
51
|
"Conversation info (untrusted metadata):",
|
|
29
52
|
"Sender (untrusted metadata):",
|
package/dist/index.js
CHANGED
|
@@ -16789,82 +16789,6 @@ var require_undici = __commonJS({
|
|
|
16789
16789
|
}
|
|
16790
16790
|
});
|
|
16791
16791
|
|
|
16792
|
-
// src/index.ts
|
|
16793
|
-
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
16794
|
-
|
|
16795
|
-
// src/cli.ts
|
|
16796
|
-
import { createInterface } from "node:readline/promises";
|
|
16797
|
-
import { stdin, stdout } from "node:process";
|
|
16798
|
-
|
|
16799
|
-
// src/cli-descriptors.ts
|
|
16800
|
-
var PLUGIN_ID = "libravdb-memory";
|
|
16801
|
-
var MEMORY_CLI_DESCRIPTOR = {
|
|
16802
|
-
name: "memory",
|
|
16803
|
-
description: "Manage LibraVDB memory",
|
|
16804
|
-
hasSubcommands: true
|
|
16805
|
-
};
|
|
16806
|
-
function isMemorySlotSelected(api) {
|
|
16807
|
-
const slots = api.config?.plugins?.slots;
|
|
16808
|
-
return slots?.memory === PLUGIN_ID;
|
|
16809
|
-
}
|
|
16810
|
-
function registerMemoryCliMetadata(api) {
|
|
16811
|
-
if (!isMemorySlotSelected(api)) {
|
|
16812
|
-
return;
|
|
16813
|
-
}
|
|
16814
|
-
api.registerCli?.(() => {
|
|
16815
|
-
}, {
|
|
16816
|
-
descriptors: [MEMORY_CLI_DESCRIPTOR]
|
|
16817
|
-
});
|
|
16818
|
-
}
|
|
16819
|
-
|
|
16820
|
-
// src/memory-scopes.ts
|
|
16821
|
-
var SESSION_KEY_NAMESPACE_PREFIX = "session-key:";
|
|
16822
|
-
var AGENT_ID_NAMESPACE_PREFIX = "agent-id:";
|
|
16823
|
-
var USER_COLLECTION_PREFIX = "user:";
|
|
16824
|
-
var RESERVED_NAMESPACE_PREFIXES = [SESSION_KEY_NAMESPACE_PREFIX, AGENT_ID_NAMESPACE_PREFIX, USER_COLLECTION_PREFIX];
|
|
16825
|
-
var COLLECTION_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_.:@#-]{0,127}$/;
|
|
16826
|
-
function validateNamespace(name) {
|
|
16827
|
-
if (!COLLECTION_NAME_RE.test(name)) {
|
|
16828
|
-
throw new Error(
|
|
16829
|
-
`Invalid collection namespace: "${name}". Must match ${COLLECTION_NAME_RE.source}`
|
|
16830
|
-
);
|
|
16831
|
-
}
|
|
16832
|
-
return name;
|
|
16833
|
-
}
|
|
16834
|
-
function resolveDurableNamespace(params) {
|
|
16835
|
-
const explicitUserId = firstNonEmpty(params.userId);
|
|
16836
|
-
if (explicitUserId) {
|
|
16837
|
-
for (const prefix of RESERVED_NAMESPACE_PREFIXES) {
|
|
16838
|
-
if (explicitUserId.startsWith(prefix)) {
|
|
16839
|
-
throw new Error(
|
|
16840
|
-
`Invalid userId "${explicitUserId}": must not start with reserved prefix "${prefix}"`
|
|
16841
|
-
);
|
|
16842
|
-
}
|
|
16843
|
-
}
|
|
16844
|
-
return validateNamespace(explicitUserId);
|
|
16845
|
-
}
|
|
16846
|
-
const sessionKey = firstNonEmpty(params.sessionKey);
|
|
16847
|
-
if (sessionKey) return validateNamespace(`${SESSION_KEY_NAMESPACE_PREFIX}${sessionKey}`);
|
|
16848
|
-
const agentId = firstNonEmpty(params.agentId);
|
|
16849
|
-
if (agentId) return validateNamespace(`${AGENT_ID_NAMESPACE_PREFIX}${agentId}`);
|
|
16850
|
-
const fallback2 = firstNonEmpty(params.fallback);
|
|
16851
|
-
if (fallback2) return validateNamespace(fallback2);
|
|
16852
|
-
return "default";
|
|
16853
|
-
}
|
|
16854
|
-
function resolveUserCollection(userId) {
|
|
16855
|
-
const namespace = firstNonEmpty(userId);
|
|
16856
|
-
if (!namespace) {
|
|
16857
|
-
throw new Error("Invalid user collection namespace: userId must be non-empty");
|
|
16858
|
-
}
|
|
16859
|
-
validateNamespace(namespace);
|
|
16860
|
-
return validateNamespace(`${USER_COLLECTION_PREFIX}${namespace}`);
|
|
16861
|
-
}
|
|
16862
|
-
function firstNonEmpty(value) {
|
|
16863
|
-
if (typeof value !== "string") return void 0;
|
|
16864
|
-
const trimmed = value.trim();
|
|
16865
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
16866
|
-
}
|
|
16867
|
-
|
|
16868
16792
|
// src/identity.ts
|
|
16869
16793
|
import { userInfo, hostname } from "node:os";
|
|
16870
16794
|
import { createHash } from "node:crypto";
|
|
@@ -16987,6 +16911,82 @@ function resolveTenantKey(cfg) {
|
|
|
16987
16911
|
}).userId;
|
|
16988
16912
|
}
|
|
16989
16913
|
|
|
16914
|
+
// src/index.ts
|
|
16915
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
16916
|
+
|
|
16917
|
+
// src/cli.ts
|
|
16918
|
+
import { createInterface } from "node:readline/promises";
|
|
16919
|
+
import { stdin, stdout } from "node:process";
|
|
16920
|
+
|
|
16921
|
+
// src/cli-descriptors.ts
|
|
16922
|
+
var PLUGIN_ID = "libravdb-memory";
|
|
16923
|
+
var MEMORY_CLI_DESCRIPTOR = {
|
|
16924
|
+
name: "memory",
|
|
16925
|
+
description: "Manage LibraVDB memory",
|
|
16926
|
+
hasSubcommands: true
|
|
16927
|
+
};
|
|
16928
|
+
function isMemorySlotSelected(api) {
|
|
16929
|
+
const slots = api.config?.plugins?.slots;
|
|
16930
|
+
return slots?.memory === PLUGIN_ID;
|
|
16931
|
+
}
|
|
16932
|
+
function registerMemoryCliMetadata(api) {
|
|
16933
|
+
if (!isMemorySlotSelected(api)) {
|
|
16934
|
+
return;
|
|
16935
|
+
}
|
|
16936
|
+
api.registerCli?.(() => {
|
|
16937
|
+
}, {
|
|
16938
|
+
descriptors: [MEMORY_CLI_DESCRIPTOR]
|
|
16939
|
+
});
|
|
16940
|
+
}
|
|
16941
|
+
|
|
16942
|
+
// src/memory-scopes.ts
|
|
16943
|
+
var SESSION_KEY_NAMESPACE_PREFIX = "session-key:";
|
|
16944
|
+
var AGENT_ID_NAMESPACE_PREFIX = "agent-id:";
|
|
16945
|
+
var USER_COLLECTION_PREFIX = "user:";
|
|
16946
|
+
var RESERVED_NAMESPACE_PREFIXES = [SESSION_KEY_NAMESPACE_PREFIX, AGENT_ID_NAMESPACE_PREFIX, USER_COLLECTION_PREFIX];
|
|
16947
|
+
var COLLECTION_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_.:@#-]{0,127}$/;
|
|
16948
|
+
function validateNamespace(name) {
|
|
16949
|
+
if (!COLLECTION_NAME_RE.test(name)) {
|
|
16950
|
+
throw new Error(
|
|
16951
|
+
`Invalid collection namespace: "${name}". Must match ${COLLECTION_NAME_RE.source}`
|
|
16952
|
+
);
|
|
16953
|
+
}
|
|
16954
|
+
return name;
|
|
16955
|
+
}
|
|
16956
|
+
function resolveDurableNamespace(params) {
|
|
16957
|
+
const explicitUserId = firstNonEmpty(params.userId);
|
|
16958
|
+
if (explicitUserId) {
|
|
16959
|
+
for (const prefix of RESERVED_NAMESPACE_PREFIXES) {
|
|
16960
|
+
if (explicitUserId.startsWith(prefix)) {
|
|
16961
|
+
throw new Error(
|
|
16962
|
+
`Invalid userId "${explicitUserId}": must not start with reserved prefix "${prefix}"`
|
|
16963
|
+
);
|
|
16964
|
+
}
|
|
16965
|
+
}
|
|
16966
|
+
return validateNamespace(explicitUserId);
|
|
16967
|
+
}
|
|
16968
|
+
const sessionKey = firstNonEmpty(params.sessionKey);
|
|
16969
|
+
if (sessionKey) return validateNamespace(`${SESSION_KEY_NAMESPACE_PREFIX}${sessionKey}`);
|
|
16970
|
+
const agentId = firstNonEmpty(params.agentId);
|
|
16971
|
+
if (agentId) return validateNamespace(`${AGENT_ID_NAMESPACE_PREFIX}${agentId}`);
|
|
16972
|
+
const fallback2 = firstNonEmpty(params.fallback);
|
|
16973
|
+
if (fallback2) return validateNamespace(fallback2);
|
|
16974
|
+
return "default";
|
|
16975
|
+
}
|
|
16976
|
+
function resolveUserCollection(userId) {
|
|
16977
|
+
const namespace = firstNonEmpty(userId);
|
|
16978
|
+
if (!namespace) {
|
|
16979
|
+
throw new Error("Invalid user collection namespace: userId must be non-empty");
|
|
16980
|
+
}
|
|
16981
|
+
validateNamespace(namespace);
|
|
16982
|
+
return validateNamespace(`${USER_COLLECTION_PREFIX}${namespace}`);
|
|
16983
|
+
}
|
|
16984
|
+
function firstNonEmpty(value) {
|
|
16985
|
+
if (typeof value !== "string") return void 0;
|
|
16986
|
+
const trimmed = value.trim();
|
|
16987
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
16988
|
+
}
|
|
16989
|
+
|
|
16990
16990
|
// src/format-error.ts
|
|
16991
16991
|
function formatError(error2) {
|
|
16992
16992
|
if (error2 instanceof Error && error2.message.trim()) {
|
|
@@ -18646,6 +18646,27 @@ var SELECTED_CONTEXT_HEADER = "Conversation context (untrusted, chronological, s
|
|
|
18646
18646
|
var RETRIEVAL_QUERY_MAX_CHARS = 1e3;
|
|
18647
18647
|
var SELECTED_CONTEXT_TURN_RE = /^#\d+\s+[A-Za-z]{3}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}(?::\d{2})?\s+\S+\s+([^:\n]{1,80}):\s*(.*)$/;
|
|
18648
18648
|
var ASSISTANT_SPEAKER_RE = /\b(?:assistant|openclaw|z3robot|bot)\b/i;
|
|
18649
|
+
var MULTI_SPEAKER_LINE_RE = /^\[\d{2}:\d{2}\]\s+(\S[^:]{0,80}):\s/;
|
|
18650
|
+
function extractSpeakers(messages) {
|
|
18651
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18652
|
+
const speakers = [];
|
|
18653
|
+
for (const msg of messages) {
|
|
18654
|
+
if (msg.role !== "user") continue;
|
|
18655
|
+
const text = normalizeKernelContent(msg.content);
|
|
18656
|
+
for (const line of text.split("\n")) {
|
|
18657
|
+
const match = line.match(MULTI_SPEAKER_LINE_RE);
|
|
18658
|
+
if (match) {
|
|
18659
|
+
const displayName = match[1].trim();
|
|
18660
|
+
const name = displayName.toLowerCase();
|
|
18661
|
+
if (name && !ASSISTANT_SPEAKER_RE.test(name) && !seen.has(name)) {
|
|
18662
|
+
seen.add(name);
|
|
18663
|
+
speakers.push({ name, displayName });
|
|
18664
|
+
}
|
|
18665
|
+
}
|
|
18666
|
+
}
|
|
18667
|
+
}
|
|
18668
|
+
return speakers;
|
|
18669
|
+
}
|
|
18649
18670
|
var OPENCLAW_METADATA_HEADERS = [
|
|
18650
18671
|
"Conversation info (untrusted metadata):",
|
|
18651
18672
|
"Sender (untrusted metadata):",
|
|
@@ -31337,6 +31358,56 @@ function createGetUserCardTool(getClient, logger = console) {
|
|
|
31337
31358
|
}
|
|
31338
31359
|
};
|
|
31339
31360
|
}
|
|
31361
|
+
function createListUserCardsTool(getClient, logger = console) {
|
|
31362
|
+
return {
|
|
31363
|
+
name: "list_user_cards",
|
|
31364
|
+
label: "List User Cards",
|
|
31365
|
+
description: "List every person you have a user card for. Returns user IDs and card previews. Use this when asked 'who do you know?' or when you need to see the full roster. For detailed information about a specific person, use get_user_card.",
|
|
31366
|
+
parameters: { type: "object", additionalProperties: false, properties: {} },
|
|
31367
|
+
execute: async (_toolCallId, _rawParams) => {
|
|
31368
|
+
try {
|
|
31369
|
+
const client = await getClient();
|
|
31370
|
+
const resp = await client.listByMeta({
|
|
31371
|
+
collection: "",
|
|
31372
|
+
key: "type",
|
|
31373
|
+
value: "user_card"
|
|
31374
|
+
});
|
|
31375
|
+
const users = [];
|
|
31376
|
+
for (const result of resp.results) {
|
|
31377
|
+
let userId = "";
|
|
31378
|
+
let preview = "";
|
|
31379
|
+
let updatedAt;
|
|
31380
|
+
let version;
|
|
31381
|
+
if (result.metadataJson && result.metadataJson.length > 0) {
|
|
31382
|
+
try {
|
|
31383
|
+
const decoder = new TextDecoder();
|
|
31384
|
+
const meta = JSON.parse(decoder.decode(result.metadataJson));
|
|
31385
|
+
userId = typeof meta._user_id === "string" ? meta._user_id : "";
|
|
31386
|
+
const cardJson = typeof meta.card_json === "string" ? meta.card_json : null;
|
|
31387
|
+
if (cardJson) {
|
|
31388
|
+
try {
|
|
31389
|
+
preview = JSON.parse(cardJson).card ?? cardJson;
|
|
31390
|
+
} catch {
|
|
31391
|
+
preview = cardJson;
|
|
31392
|
+
}
|
|
31393
|
+
preview = preview.slice(0, 200);
|
|
31394
|
+
}
|
|
31395
|
+
updatedAt = typeof meta.updated_at === "number" ? meta.updated_at : void 0;
|
|
31396
|
+
version = typeof meta.version === "number" ? meta.version : void 0;
|
|
31397
|
+
} catch {
|
|
31398
|
+
}
|
|
31399
|
+
}
|
|
31400
|
+
if (!userId) continue;
|
|
31401
|
+
users.push({ user_id: userId, preview, updated_at: updatedAt, version });
|
|
31402
|
+
}
|
|
31403
|
+
return jsonResult({ users, total: users.length });
|
|
31404
|
+
} catch (error2) {
|
|
31405
|
+
logger.warn?.(`list_user_cards failed: ${formatError(error2)}`);
|
|
31406
|
+
return jsonResult({ users: [], total: 0, error: formatError(error2) });
|
|
31407
|
+
}
|
|
31408
|
+
}
|
|
31409
|
+
};
|
|
31410
|
+
}
|
|
31340
31411
|
|
|
31341
31412
|
// src/memory-tools.ts
|
|
31342
31413
|
var MEMORY_SEARCH_SCHEMA = {
|
|
@@ -34780,6 +34851,10 @@ var LibravDBClient = class {
|
|
|
34780
34851
|
this.guardOpen();
|
|
34781
34852
|
return this.client.getUserCard(req);
|
|
34782
34853
|
}
|
|
34854
|
+
async listByMeta(req) {
|
|
34855
|
+
this.guardOpen();
|
|
34856
|
+
return this.client.listByMeta(req);
|
|
34857
|
+
}
|
|
34783
34858
|
close() {
|
|
34784
34859
|
this.closed = true;
|
|
34785
34860
|
}
|
|
@@ -35107,6 +35182,10 @@ function register(api) {
|
|
|
35107
35182
|
const getClient = runtimeOrNull.getClient;
|
|
35108
35183
|
return createGetUserCardTool(getClient, logger);
|
|
35109
35184
|
}, { names: ["get_user_card"] });
|
|
35185
|
+
api.registerTool?.((ctx) => {
|
|
35186
|
+
const getClient = runtimeOrNull.getClient;
|
|
35187
|
+
return createListUserCardsTool(getClient, logger);
|
|
35188
|
+
}, { names: ["list_user_cards"] });
|
|
35110
35189
|
}
|
|
35111
35190
|
if (isLightweight || isDiscovery) {
|
|
35112
35191
|
if (!isLightweight) {
|
|
@@ -35213,6 +35292,65 @@ function register(api) {
|
|
|
35213
35292
|
const trigger = ctx?.trigger;
|
|
35214
35293
|
if (sessionId) setSessionTrigger(sessionId, trigger);
|
|
35215
35294
|
});
|
|
35295
|
+
const MULTI_SPEAKER_PROVIDERS = /* @__PURE__ */ new Set([
|
|
35296
|
+
"discord",
|
|
35297
|
+
"telegram",
|
|
35298
|
+
"imessage",
|
|
35299
|
+
"slack",
|
|
35300
|
+
"whatsapp",
|
|
35301
|
+
"signal",
|
|
35302
|
+
"matrix",
|
|
35303
|
+
"irc"
|
|
35304
|
+
]);
|
|
35305
|
+
api.on("before_prompt_build", async (event, ctx) => {
|
|
35306
|
+
const c = ctx;
|
|
35307
|
+
const provider = c.messageProvider;
|
|
35308
|
+
if (!provider || !MULTI_SPEAKER_PROVIDERS.has(provider.toLowerCase())) return;
|
|
35309
|
+
const e = event;
|
|
35310
|
+
const messages = e.messages ?? [];
|
|
35311
|
+
const speakers = extractSpeakers(messages);
|
|
35312
|
+
if (speakers.length === 0) return;
|
|
35313
|
+
const mainIdentity = resolveIdentity({
|
|
35314
|
+
configUserId: cfg.userId,
|
|
35315
|
+
identityPath: cfg.identityPath,
|
|
35316
|
+
sessionKey: c.sessionKey,
|
|
35317
|
+
logger,
|
|
35318
|
+
noAutoPersist: true
|
|
35319
|
+
});
|
|
35320
|
+
const mainUserId = mainIdentity.userId.toLowerCase();
|
|
35321
|
+
const otherSpeakers = speakers.filter((s) => s.name !== mainUserId);
|
|
35322
|
+
if (otherSpeakers.length === 0) return;
|
|
35323
|
+
try {
|
|
35324
|
+
const client = await runtime.getClient();
|
|
35325
|
+
const results = await Promise.all(
|
|
35326
|
+
otherSpeakers.map(async (speaker) => {
|
|
35327
|
+
try {
|
|
35328
|
+
const resp = await client.getUserCard({ userId: speaker.name });
|
|
35329
|
+
if (!resp.cardJson) return null;
|
|
35330
|
+
let card;
|
|
35331
|
+
try {
|
|
35332
|
+
card = JSON.parse(resp.cardJson).card ?? resp.cardJson;
|
|
35333
|
+
} catch {
|
|
35334
|
+
card = resp.cardJson;
|
|
35335
|
+
}
|
|
35336
|
+
if (!card || !card.trim()) return null;
|
|
35337
|
+
return `<speaker_context speaker="${speaker.displayName}">
|
|
35338
|
+
${card.trim()}
|
|
35339
|
+
</speaker_context>`;
|
|
35340
|
+
} catch {
|
|
35341
|
+
return null;
|
|
35342
|
+
}
|
|
35343
|
+
})
|
|
35344
|
+
);
|
|
35345
|
+
const validCards = results.filter((c2) => c2 !== null);
|
|
35346
|
+
if (validCards.length === 0) return;
|
|
35347
|
+
return { appendSystemContext: validCards.join("\n") };
|
|
35348
|
+
} catch (error2) {
|
|
35349
|
+
logger.warn?.(
|
|
35350
|
+
`LibraVDB speaker card injection failed: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
35351
|
+
);
|
|
35352
|
+
}
|
|
35353
|
+
});
|
|
35216
35354
|
api.on("session_end", async (_event, ctx) => {
|
|
35217
35355
|
const sessionId = ctx?.sessionId;
|
|
35218
35356
|
if (sessionId) clearSessionTrigger(sessionId);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Interceptor } from "@connectrpc/connect";
|
|
2
2
|
import type { PartialMessage } from "@bufbuild/protobuf";
|
|
3
3
|
import type { LoggerLike } from "./types.js";
|
|
4
|
-
import type { AfterTurnKernelRequest, AfterTurnKernelResponse, BeforeTurnKernelRequest, BeforeTurnKernelResponse, AssembleContextInternalRequest, AssembleContextInternalResponse, BootstrapSessionKernelRequest, BootstrapSessionKernelResponse, CompactSessionRequest, CompactSessionResponse, DeleteAuthoredDocumentRequest, DeleteAuthoredDocumentResponse, DreamPromotionResponse, ExportMemoryRequest, ExportMemoryResponse, FlushNamespaceRequest, FlushNamespaceResponse, FlushRequest, FlushResponse, HealthRequest, HealthResponse, IngestMarkdownDocumentRequest, IngestMarkdownDocumentResponse, IngestMessageKernelRequest, IngestMessageKernelResponse, ListCollectionRequest, ListCollectionResponse, ListLifecycleJournalRequest, ListLifecycleJournalResponse, MarkMemorySupersededRequest, MarkMemorySupersededResponse, MemoryStatusRequest, MemoryStatusResponse, PromoteDreamEntriesRequest, RankCandidatesRequest, RankCandidatesResponse, RebuildIndexRequest, RebuildIndexResponse, ReindexAuthoredDocumentRequest, ReindexAuthoredDocumentResponse, SearchTextCollectionsRequest, SearchTextRequest, SearchTextResponse, SessionLifecycleHintRequest, SessionLifecycleHintResponse, SummarizeMessagesRequest, SummarizeMessagesResponse, ExpandSummaryRequest, ExpandSummaryResponse, UpsertUserCardRequest, UpsertUserCardResponse, GetUserCardRequest, GetUserCardResponse } from "@xdarkicex/libravdb-contracts";
|
|
4
|
+
import type { AfterTurnKernelRequest, AfterTurnKernelResponse, BeforeTurnKernelRequest, BeforeTurnKernelResponse, AssembleContextInternalRequest, AssembleContextInternalResponse, BootstrapSessionKernelRequest, BootstrapSessionKernelResponse, CompactSessionRequest, CompactSessionResponse, DeleteAuthoredDocumentRequest, DeleteAuthoredDocumentResponse, DreamPromotionResponse, ExportMemoryRequest, ExportMemoryResponse, FlushNamespaceRequest, FlushNamespaceResponse, FlushRequest, FlushResponse, HealthRequest, HealthResponse, IngestMarkdownDocumentRequest, IngestMarkdownDocumentResponse, IngestMessageKernelRequest, IngestMessageKernelResponse, ListByMetaRequest, ListByMetaResponse, ListCollectionRequest, ListCollectionResponse, ListLifecycleJournalRequest, ListLifecycleJournalResponse, MarkMemorySupersededRequest, MarkMemorySupersededResponse, MemoryStatusRequest, MemoryStatusResponse, PromoteDreamEntriesRequest, RankCandidatesRequest, RankCandidatesResponse, RebuildIndexRequest, RebuildIndexResponse, ReindexAuthoredDocumentRequest, ReindexAuthoredDocumentResponse, SearchTextCollectionsRequest, SearchTextRequest, SearchTextResponse, SessionLifecycleHintRequest, SessionLifecycleHintResponse, SummarizeMessagesRequest, SummarizeMessagesResponse, ExpandSummaryRequest, ExpandSummaryResponse, UpsertUserCardRequest, UpsertUserCardResponse, GetUserCardRequest, GetUserCardResponse } from "@xdarkicex/libravdb-contracts";
|
|
5
5
|
export interface LibravDBClientOptions {
|
|
6
6
|
endpoint?: string;
|
|
7
7
|
secret?: string;
|
|
@@ -67,6 +67,7 @@ export declare class LibravDBClient {
|
|
|
67
67
|
rankCandidates(req: PartialMessage<RankCandidatesRequest>): Promise<RankCandidatesResponse>;
|
|
68
68
|
upsertUserCard(req: PartialMessage<UpsertUserCardRequest>): Promise<UpsertUserCardResponse>;
|
|
69
69
|
getUserCard(req: PartialMessage<GetUserCardRequest>): Promise<GetUserCardResponse>;
|
|
70
|
+
listByMeta(req: PartialMessage<ListByMetaRequest>): Promise<ListByMetaResponse>;
|
|
70
71
|
close(): void;
|
|
71
72
|
}
|
|
72
73
|
export declare function loadSecretFromEnv(logger?: LoggerLike): string | undefined;
|
package/dist/libravdb-client.js
CHANGED
|
@@ -189,4 +189,25 @@ export declare function createGetUserCardTool(getClient: ClientGetter, logger?:
|
|
|
189
189
|
};
|
|
190
190
|
execute: (_toolCallId: string, rawParams: unknown) => Promise<ToolResult<GetUserCardDetails>>;
|
|
191
191
|
};
|
|
192
|
+
type ListUserCardsDetails = {
|
|
193
|
+
users: Array<{
|
|
194
|
+
user_id: string;
|
|
195
|
+
preview: string;
|
|
196
|
+
updated_at?: number;
|
|
197
|
+
version?: number;
|
|
198
|
+
}>;
|
|
199
|
+
total: number;
|
|
200
|
+
error?: string;
|
|
201
|
+
};
|
|
202
|
+
export declare function createListUserCardsTool(getClient: ClientGetter, logger?: LoggerLike): {
|
|
203
|
+
name: string;
|
|
204
|
+
label: string;
|
|
205
|
+
description: string;
|
|
206
|
+
parameters: {
|
|
207
|
+
readonly type: "object";
|
|
208
|
+
readonly additionalProperties: false;
|
|
209
|
+
readonly properties: {};
|
|
210
|
+
};
|
|
211
|
+
execute: (_toolCallId: string, _rawParams: unknown) => Promise<ToolResult<ListUserCardsDetails>>;
|
|
212
|
+
};
|
|
192
213
|
export {};
|
|
@@ -511,3 +511,58 @@ export function createGetUserCardTool(getClient, logger = console) {
|
|
|
511
511
|
},
|
|
512
512
|
};
|
|
513
513
|
}
|
|
514
|
+
export function createListUserCardsTool(getClient, logger = console) {
|
|
515
|
+
return {
|
|
516
|
+
name: "list_user_cards",
|
|
517
|
+
label: "List User Cards",
|
|
518
|
+
description: "List every person you have a user card for. Returns user IDs and card previews. " +
|
|
519
|
+
"Use this when asked 'who do you know?' or when you need to see the full roster. " +
|
|
520
|
+
"For detailed information about a specific person, use get_user_card.",
|
|
521
|
+
parameters: { type: "object", additionalProperties: false, properties: {} },
|
|
522
|
+
execute: async (_toolCallId, _rawParams) => {
|
|
523
|
+
try {
|
|
524
|
+
const client = await getClient();
|
|
525
|
+
const resp = await client.listByMeta({
|
|
526
|
+
collection: "",
|
|
527
|
+
key: "type",
|
|
528
|
+
value: "user_card",
|
|
529
|
+
});
|
|
530
|
+
const users = [];
|
|
531
|
+
for (const result of resp.results) {
|
|
532
|
+
let userId = "";
|
|
533
|
+
let preview = "";
|
|
534
|
+
let updatedAt;
|
|
535
|
+
let version;
|
|
536
|
+
if (result.metadataJson && result.metadataJson.length > 0) {
|
|
537
|
+
try {
|
|
538
|
+
const decoder = new TextDecoder();
|
|
539
|
+
const meta = JSON.parse(decoder.decode(result.metadataJson));
|
|
540
|
+
userId = typeof meta._user_id === "string" ? meta._user_id : "";
|
|
541
|
+
const cardJson = typeof meta.card_json === "string" ? meta.card_json : null;
|
|
542
|
+
if (cardJson) {
|
|
543
|
+
try {
|
|
544
|
+
preview = JSON.parse(cardJson).card ?? cardJson;
|
|
545
|
+
}
|
|
546
|
+
catch {
|
|
547
|
+
preview = cardJson;
|
|
548
|
+
}
|
|
549
|
+
preview = preview.slice(0, 200);
|
|
550
|
+
}
|
|
551
|
+
updatedAt = typeof meta.updated_at === "number" ? meta.updated_at : undefined;
|
|
552
|
+
version = typeof meta.version === "number" ? meta.version : undefined;
|
|
553
|
+
}
|
|
554
|
+
catch { /* best-effort metadata parse */ }
|
|
555
|
+
}
|
|
556
|
+
if (!userId)
|
|
557
|
+
continue;
|
|
558
|
+
users.push({ user_id: userId, preview, updated_at: updatedAt, version });
|
|
559
|
+
}
|
|
560
|
+
return jsonResult({ users, total: users.length });
|
|
561
|
+
}
|
|
562
|
+
catch (error) {
|
|
563
|
+
logger.warn?.(`list_user_cards failed: ${formatError(error)}`);
|
|
564
|
+
return jsonResult({ users: [], total: 0, error: formatError(error) });
|
|
565
|
+
}
|
|
566
|
+
},
|
|
567
|
+
};
|
|
568
|
+
}
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "libravdb-memory",
|
|
3
3
|
"name": "LibraVDB Memory",
|
|
4
|
-
"description": "
|
|
5
|
-
"version": "1.9.10-beta.
|
|
4
|
+
"description": "Cognitive memory engine — causal graph reasoning, predictive context, identity tracking, and hybrid vector recall with back-door adjustment scoring",
|
|
5
|
+
"version": "1.9.10-beta.18",
|
|
6
6
|
"kind": [
|
|
7
7
|
"memory",
|
|
8
8
|
"context-engine"
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
"memory_get",
|
|
16
16
|
"memory_describe",
|
|
17
17
|
"memory_expand",
|
|
18
|
-
"memory_grep"
|
|
18
|
+
"memory_grep",
|
|
19
|
+
"update_user_card",
|
|
20
|
+
"get_user_card"
|
|
19
21
|
]
|
|
20
22
|
},
|
|
21
23
|
"activation": {
|