@xdarkicex/openclaw-memory-libravdb 1.10.9 → 1.10.13

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.
@@ -1725,6 +1725,26 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
1725
1725
  return null;
1726
1726
  }
1727
1727
  }
1728
+ async function injectPersonaContext(params) {
1729
+ try {
1730
+ const resp = await params.client.getUserCard({ userId: "__bot_persona__" });
1731
+ if (!resp.cardJson)
1732
+ return null;
1733
+ let card;
1734
+ try {
1735
+ card = JSON.parse(resp.cardJson).card ?? resp.cardJson;
1736
+ }
1737
+ catch {
1738
+ card = resp.cardJson;
1739
+ }
1740
+ if (!card || card.trim().length === 0)
1741
+ return null;
1742
+ return '<bot_persona>\n' + card + '\n</bot_persona>';
1743
+ }
1744
+ catch {
1745
+ return null;
1746
+ }
1747
+ }
1728
1748
  async function runCompaction(args) {
1729
1749
  const request = buildCompactSessionRequest(args);
1730
1750
  try {
@@ -2029,12 +2049,16 @@ export function buildContextEngineFactory(runtime, cfg, logger = console) {
2029
2049
  systemPromptAddition: assembled.systemPromptAddition,
2030
2050
  });
2031
2051
  const userCardContext = await injectUserCardContext({ client, userId });
2052
+ const personaContext = await injectPersonaContext({ client });
2032
2053
  const rulesContext = buildRulesContext();
2033
- // Only inject continuity, user card, and rules on session bootstrap.
2034
- // After the first turn, predictive context handles it.
2054
+ // Only inject on session bootstrap.
2035
2055
  const isSessionBootstrap = messages.length <= 1;
2036
2056
  let withContext = assembled;
2037
2057
  if (isSessionBootstrap) {
2058
+ // Persona first — identity of the bot itself.
2059
+ if (personaContext) {
2060
+ withContext = { ...withContext, systemPromptAddition: appendSystemPromptAddition(withContext.systemPromptAddition, personaContext) };
2061
+ }
2038
2062
  if (userCardContext) {
2039
2063
  withContext = { ...withContext, systemPromptAddition: appendSystemPromptAddition(withContext.systemPromptAddition, userCardContext) };
2040
2064
  }
package/dist/index.js CHANGED
@@ -20281,6 +20281,22 @@ ${cached}
20281
20281
  return null;
20282
20282
  }
20283
20283
  }
20284
+ async function injectPersonaContext(params) {
20285
+ try {
20286
+ const resp = await params.client.getUserCard({ userId: "__bot_persona__" });
20287
+ if (!resp.cardJson) return null;
20288
+ let card;
20289
+ try {
20290
+ card = JSON.parse(resp.cardJson).card ?? resp.cardJson;
20291
+ } catch {
20292
+ card = resp.cardJson;
20293
+ }
20294
+ if (!card || card.trim().length === 0) return null;
20295
+ return "<bot_persona>\n" + card + "\n</bot_persona>";
20296
+ } catch {
20297
+ return null;
20298
+ }
20299
+ }
20284
20300
  async function runCompaction(args) {
20285
20301
  const request3 = buildCompactSessionRequest(args);
20286
20302
  try {
@@ -20575,10 +20591,14 @@ ${cached}
20575
20591
  systemPromptAddition: assembled.systemPromptAddition
20576
20592
  });
20577
20593
  const userCardContext = await injectUserCardContext({ client, userId });
20594
+ const personaContext = await injectPersonaContext({ client });
20578
20595
  const rulesContext = buildRulesContext();
20579
20596
  const isSessionBootstrap = messages.length <= 1;
20580
20597
  let withContext = assembled;
20581
20598
  if (isSessionBootstrap) {
20599
+ if (personaContext) {
20600
+ withContext = { ...withContext, systemPromptAddition: appendSystemPromptAddition(withContext.systemPromptAddition, personaContext) };
20601
+ }
20582
20602
  if (userCardContext) {
20583
20603
  withContext = { ...withContext, systemPromptAddition: appendSystemPromptAddition(withContext.systemPromptAddition, userCardContext) };
20584
20604
  }
@@ -31187,7 +31207,8 @@ function buildToolGuidance(availableTools) {
31187
31207
  "Only use memory_search if the card is empty or missing.",
31188
31208
  "",
31189
31209
  "**Autonomous card maintenance:**",
31190
- hasGetCard ? "- When you learn something new about ANY speaker (relationships, jobs, life events, preferences, beliefs), silently call `update_user_card` to keep their card current. You are building a picture of the user's world \u2014 everyone they mention matters. Don't wait to be asked. Update cards proactively." : "",
31210
+ hasGetCard ? "- When ANY speaker is mentioned with new or changed information (status, relationships, jobs, life events, feelings), call `update_user_card` BEFORE responding. Update the card first, then reply. Do NOT wait to be asked. Build the world picture proactively. Every person the user mentions matters." : "",
31211
+ hasGetCard ? "- If a card for the speaker doesn't exist yet, CREATE one with `update_user_card`. Better to have a stub card than no card at all." : "",
31191
31212
  ""
31192
31213
  );
31193
31214
  }
@@ -31196,7 +31217,10 @@ function buildToolGuidance(availableTools) {
31196
31217
  "facts, earliest interactions, and channel history. Do not answer memory",
31197
31218
  "questions from prior transcript claims \u2014 perform a search every time.",
31198
31219
  "After receiving results, use them directly; do not re-call in the same turn.",
31199
- ...availableTools.has("memory_get") ? ["After a `memory_search` hit, call `memory_get` when exact wording or more context is needed."] : [],
31220
+ ...availableTools.has("memory_get") ? [
31221
+ "After a `memory_search` hit, call `memory_get` when exact wording or more context is needed.",
31222
+ "IMPORTANT: If a search snippet is cluttered with metadata, do NOT claim nothing was found. Call `memory_get` on the hit's path to read the full record first. The data is there \u2014 expand before giving up."
31223
+ ] : [],
31200
31224
  ""
31201
31225
  );
31202
31226
  const hasDescribe = availableTools.has("memory_describe");
@@ -31784,6 +31808,55 @@ function createListUserCardsTool(getClient, logger = console) {
31784
31808
  }
31785
31809
  };
31786
31810
  }
31811
+ function createSetPersonaTool(getClient, logger = console) {
31812
+ return {
31813
+ name: "set_persona",
31814
+ label: "Set Persona",
31815
+ description: "Define who YOU are \u2014 your personality, tone, boundaries, and behavior. Write in prose like you're describing yourself. This is injected as <bot_persona> at the start of every session. Update it when your persona changes. The LLM will embody this persona in all interactions.",
31816
+ parameters: {
31817
+ type: "object",
31818
+ additionalProperties: false,
31819
+ properties: {
31820
+ persona: { type: "string", description: "Prose description of how you should behave." }
31821
+ },
31822
+ required: ["persona"]
31823
+ },
31824
+ execute: async (_toolCallId, rawParams) => {
31825
+ const params = rawParams;
31826
+ const persona = typeof params?.persona === "string" ? params.persona.trim() : "";
31827
+ if (!persona) return jsonResult2({ ok: false, error: "set_persona requires a persona string" });
31828
+ try {
31829
+ const client = await getClient();
31830
+ const resp = await client.upsertUserCard({
31831
+ userId: "__bot_persona__",
31832
+ cardJson: JSON.stringify({ card: persona, updatedAt: Date.now() })
31833
+ });
31834
+ return jsonResult2({ ok: resp.ok });
31835
+ } catch (error2) {
31836
+ logger.warn?.(`set_persona failed: ${formatError(error2)}`);
31837
+ return jsonResult2({ ok: false, error: formatError(error2) });
31838
+ }
31839
+ }
31840
+ };
31841
+ }
31842
+ function createGetPersonaTool(getClient, logger = console) {
31843
+ return {
31844
+ name: "get_persona",
31845
+ label: "Get Persona",
31846
+ description: "Read your current persona. Returns the full prose description of how you should behave.",
31847
+ parameters: { type: "object", additionalProperties: false, properties: {} },
31848
+ execute: async () => {
31849
+ try {
31850
+ const client = await getClient();
31851
+ const resp = await client.getUserCard({ userId: "__bot_persona__" });
31852
+ return jsonResult2({ persona: resp.cardJson || null });
31853
+ } catch (error2) {
31854
+ logger.warn?.(`get_persona failed: ${formatError(error2)}`);
31855
+ return jsonResult2({ error: formatError(error2) });
31856
+ }
31857
+ }
31858
+ };
31859
+ }
31787
31860
 
31788
31861
  // src/memory-tools.ts
31789
31862
  var MEMORY_SEARCH_SCHEMA = {
@@ -35605,6 +35678,14 @@ function register(api) {
35605
35678
  api.registerTool?.(() => createGetRuleTool(logger), { names: ["get_rule"] });
35606
35679
  api.registerTool?.(() => createListRulesTool(logger), { names: ["list_rules"] });
35607
35680
  api.registerTool?.(() => createDeleteRuleTool(logger), { names: ["delete_rule"] });
35681
+ api.registerTool?.(() => {
35682
+ const getClient = runtimeOrNull.getClient;
35683
+ return createSetPersonaTool(getClient, logger);
35684
+ }, { names: ["set_persona"] });
35685
+ api.registerTool?.(() => {
35686
+ const getClient = runtimeOrNull.getClient;
35687
+ return createGetPersonaTool(getClient, logger);
35688
+ }, { names: ["get_persona"] });
35608
35689
  }
35609
35690
  if (isLightweight || isDiscovery) {
35610
35691
  if (!isLightweight) {
@@ -29,10 +29,13 @@ function buildToolGuidance(availableTools) {
29
29
  const hasGetCard = availableTools.has("get_user_card");
30
30
  const hasListCards = availableTools.has("list_user_cards");
31
31
  if (hasGetCard || hasListCards) {
32
- lines.push("**Identity/Entity questions — MANDATORY card lookup:**", "BEFORE answering any question about a person, pet, place, or named thing:", hasGetCard ? "- `get_user_card(user_id)` — MANDATORY lookup for a specific entity." : "", hasListCards ? "- `list_user_cards()` — MANDATORY roster check. Call if unsure whether a card exists." : "", "Cards are the canonical record. You MUST call these tools. Do NOT answer from", "memory, context, or training data without checking the card first.", "Only use memory_search if the card is empty or missing.", "", "**Autonomous card maintenance:**", hasGetCard ? "- When you learn something new about ANY speaker (relationships, jobs, life events, preferences, beliefs), silently call `update_user_card` to keep their card current. You are building a picture of the user's world everyone they mention matters. Don't wait to be asked. Update cards proactively." : "", "");
32
+ lines.push("**Identity/Entity questions — MANDATORY card lookup:**", "BEFORE answering any question about a person, pet, place, or named thing:", hasGetCard ? "- `get_user_card(user_id)` — MANDATORY lookup for a specific entity." : "", hasListCards ? "- `list_user_cards()` — MANDATORY roster check. Call if unsure whether a card exists." : "", "Cards are the canonical record. You MUST call these tools. Do NOT answer from", "memory, context, or training data without checking the card first.", "Only use memory_search if the card is empty or missing.", "", "**Autonomous card maintenance:**", hasGetCard ? "- When ANY speaker is mentioned with new or changed information (status, relationships, jobs, life events, feelings), call `update_user_card` BEFORE responding. Update the card first, then reply. Do NOT wait to be asked. Build the world picture proactively. Every person the user mentions matters." : "", hasGetCard ? "- If a card for the speaker doesn't exist yet, CREATE one with `update_user_card`. Better to have a stub card than no card at all." : "", "");
33
33
  }
34
34
  lines.push("Call `memory_search` once per user question for prior turns, remembered", "facts, earliest interactions, and channel history. Do not answer memory", "questions from prior transcript claims — perform a search every time.", "After receiving results, use them directly; do not re-call in the same turn.", ...(availableTools.has("memory_get")
35
- ? ["After a `memory_search` hit, call `memory_get` when exact wording or more context is needed."]
35
+ ? [
36
+ "After a `memory_search` hit, call `memory_get` when exact wording or more context is needed.",
37
+ "IMPORTANT: If a search snippet is cluttered with metadata, do NOT claim nothing was found. Call `memory_get` on the hit's path to read the full record first. The data is there — expand before giving up."
38
+ ]
36
39
  : []), "");
37
40
  // ── Summaries / recall (when available) ──
38
41
  const hasDescribe = availableTools.has("memory_describe");
@@ -213,4 +213,38 @@ export declare function createListUserCardsTool(getClient: ClientGetter, logger?
213
213
  };
214
214
  execute: (_toolCallId: string, _rawParams: unknown) => Promise<ToolResult<ListUserCardsDetails>>;
215
215
  };
216
+ export declare function createSetPersonaTool(getClient: ClientGetter, logger?: LoggerLike): {
217
+ name: string;
218
+ label: string;
219
+ description: string;
220
+ parameters: {
221
+ readonly type: "object";
222
+ readonly additionalProperties: false;
223
+ readonly properties: {
224
+ readonly persona: {
225
+ readonly type: "string";
226
+ readonly description: "Prose description of how you should behave.";
227
+ };
228
+ };
229
+ readonly required: readonly ["persona"];
230
+ };
231
+ execute: (_toolCallId: string, rawParams: unknown) => Promise<ToolResult<{
232
+ ok: boolean;
233
+ error?: string;
234
+ }>>;
235
+ };
236
+ export declare function createGetPersonaTool(getClient: ClientGetter, logger?: LoggerLike): {
237
+ name: string;
238
+ label: string;
239
+ description: string;
240
+ parameters: {
241
+ readonly type: "object";
242
+ readonly additionalProperties: false;
243
+ readonly properties: {};
244
+ };
245
+ execute: () => Promise<ToolResult<{
246
+ persona?: string | null;
247
+ error?: string;
248
+ }>>;
249
+ };
216
250
  export {};
@@ -601,3 +601,59 @@ export function createListUserCardsTool(getClient, logger = console) {
601
601
  },
602
602
  };
603
603
  }
604
+ // ── Persona tools — identity of the bot itself ──
605
+ export function createSetPersonaTool(getClient, logger = console) {
606
+ return {
607
+ name: "set_persona",
608
+ label: "Set Persona",
609
+ description: "Define who YOU are — your personality, tone, boundaries, and behavior. " +
610
+ "Write in prose like you're describing yourself. This is injected as " +
611
+ "<bot_persona> at the start of every session. Update it when your persona " +
612
+ "changes. The LLM will embody this persona in all interactions.",
613
+ parameters: {
614
+ type: "object",
615
+ additionalProperties: false,
616
+ properties: {
617
+ persona: { type: "string", description: "Prose description of how you should behave." },
618
+ },
619
+ required: ["persona"],
620
+ },
621
+ execute: async (_toolCallId, rawParams) => {
622
+ const params = rawParams;
623
+ const persona = typeof params?.persona === "string" ? params.persona.trim() : "";
624
+ if (!persona)
625
+ return jsonResult({ ok: false, error: "set_persona requires a persona string" });
626
+ try {
627
+ const client = await getClient();
628
+ const resp = await client.upsertUserCard({
629
+ userId: "__bot_persona__",
630
+ cardJson: JSON.stringify({ card: persona, updatedAt: Date.now() }),
631
+ });
632
+ return jsonResult({ ok: resp.ok });
633
+ }
634
+ catch (error) {
635
+ logger.warn?.(`set_persona failed: ${formatError(error)}`);
636
+ return jsonResult({ ok: false, error: formatError(error) });
637
+ }
638
+ },
639
+ };
640
+ }
641
+ export function createGetPersonaTool(getClient, logger = console) {
642
+ return {
643
+ name: "get_persona",
644
+ label: "Get Persona",
645
+ description: "Read your current persona. Returns the full prose description of how you should behave.",
646
+ parameters: { type: "object", additionalProperties: false, properties: {} },
647
+ execute: async () => {
648
+ try {
649
+ const client = await getClient();
650
+ const resp = await client.getUserCard({ userId: "__bot_persona__" });
651
+ return jsonResult({ persona: resp.cardJson || null });
652
+ }
653
+ catch (error) {
654
+ logger.warn?.(`get_persona failed: ${formatError(error)}`);
655
+ return jsonResult({ error: formatError(error) });
656
+ }
657
+ },
658
+ };
659
+ }
@@ -2,7 +2,7 @@
2
2
  "id": "libravdb-memory",
3
3
  "name": "LibraVDB Memory",
4
4
  "description": "Cognitive memory engine — causal graph reasoning, predictive context, identity tracking, and hybrid vector recall with back-door adjustment scoring",
5
- "version": "1.10.9",
5
+ "version": "1.10.13",
6
6
  "kind": [
7
7
  "memory",
8
8
  "context-engine"
@@ -22,7 +22,9 @@
22
22
  "set_rule",
23
23
  "get_rule",
24
24
  "list_rules",
25
- "delete_rule"
25
+ "delete_rule",
26
+ "set_persona",
27
+ "get_persona"
26
28
  ]
27
29
  },
28
30
  "activation": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xdarkicex/openclaw-memory-libravdb",
3
- "version": "1.10.9",
3
+ "version": "1.10.13",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",