@contextableai/openclaw-memory-rebac 0.5.0 → 0.5.2

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.
Files changed (2) hide show
  1. package/dist/index.js +32 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -99,9 +99,14 @@ const rebacMemoryPlugin = {
99
99
  const isHybrid = cfg.isHybrid;
100
100
  const spicedb = new SpiceDbClient(cfg.spicedb);
101
101
  const backendDefaultGroupId = defaultGroupId(cfg);
102
- const liminalDefaultGroupId = isHybrid
102
+ const liminalBaseGroupId = isHybrid
103
103
  ? (cfg.liminalConfig["defaultGroupId"] ?? "main")
104
104
  : backendDefaultGroupId;
105
+ /** Per-agent liminal group — each agent gets its own conversational memory. */
106
+ function liminalGroupId(agentId) {
107
+ const id = agentId ?? cfg.subjectId;
108
+ return `${liminalBaseGroupId}:${id}`;
109
+ }
105
110
  // Suppress transient gRPC rejections from @grpc/grpc-js during connection setup
106
111
  const grpcRejectionHandler = (reason) => {
107
112
  const msg = String(reason);
@@ -598,7 +603,7 @@ const rebacMemoryPlugin = {
598
603
  // 1. Search the liminal backend
599
604
  const liminalResults = await searchAuthorizedMemories(liminal, {
600
605
  query,
601
- groupIds: [liminalDefaultGroupId],
606
+ groupIds: [liminalGroupId(ctx.agentId)],
602
607
  limit: promoteLimit,
603
608
  });
604
609
  if (liminalResults.length === 0) {
@@ -678,7 +683,7 @@ const rebacMemoryPlugin = {
678
683
  const autoRecallLimit = 8;
679
684
  const liminalResults = await searchAuthorizedMemories(liminal, {
680
685
  query: event.prompt,
681
- groupIds: [liminalDefaultGroupId],
686
+ groupIds: [liminalGroupId(ctx?.agentId)],
682
687
  limit: autoRecallLimit,
683
688
  sessionId: state.sessionId,
684
689
  });
@@ -686,6 +691,8 @@ const rebacMemoryPlugin = {
686
691
  "You have memory tools:\n" +
687
692
  "- memory_recall: Use this BEFORE saying you don't know or remember something. Search the long-term knowledge graph for facts, preferences, people, decisions.\n" +
688
693
  "- memory_store: Save important new information to the knowledge graph.\n" +
694
+ "- memory_share: Share a specific memory with other people/agents by ID.\n" +
695
+ "- memory_unshare: Revoke view access to a memory from people/agents.\n" +
689
696
  "- memory_promote: Promote recent memories into the long-term knowledge graph.\n" +
690
697
  "</memory-tools>";
691
698
  if (liminalResults.length === 0)
@@ -725,6 +732,8 @@ const rebacMemoryPlugin = {
725
732
  "You have memory tools:\n" +
726
733
  "- memory_recall: Use this BEFORE saying you don't know or remember something. Search for facts, preferences, people, decisions.\n" +
727
734
  "- memory_store: Save important new information (preferences, decisions, facts about people).\n" +
735
+ "- memory_share: Share a specific memory with other people/agents by ID.\n" +
736
+ "- memory_unshare: Revoke view access to a memory from people/agents.\n" +
728
737
  "</memory-tools>";
729
738
  if (totalCount === 0)
730
739
  return { prependContext: toolHint };
@@ -794,10 +803,10 @@ const rebacMemoryPlugin = {
794
803
  if (isHybrid) {
795
804
  // Hybrid mode: store to liminal backend only (fire-and-forget, no SpiceDB).
796
805
  // Primary backend (Graphiti) gets data only via explicit memory_store or memory_promote.
797
- const liminalGroupId = liminalDefaultGroupId;
806
+ const agentLiminalGroup = liminalGroupId(ctx?.agentId);
798
807
  await liminal.store({
799
808
  content: episodeBody,
800
- groupId: liminalGroupId,
809
+ groupId: agentLiminalGroup,
801
810
  sourceDescription: "auto-captured conversation",
802
811
  });
803
812
  // Liminal session enrichment
@@ -828,7 +837,7 @@ const rebacMemoryPlugin = {
828
837
  if (userMsg && assistantMsg) {
829
838
  liminal.enrichSession({
830
839
  sessionId: state.sessionId,
831
- groupId: liminalGroupId,
840
+ groupId: agentLiminalGroup,
832
841
  userMsg,
833
842
  assistantMsg,
834
843
  }).catch(() => { });
@@ -947,19 +956,27 @@ const rebacMemoryPlugin = {
947
956
  const defaultState = getDefaultState();
948
957
  const backendStatus = await backend.getStatus();
949
958
  let spicedbOk = false;
959
+ const schemaPath = join(dirname(fileURLToPath(import.meta.url)), "schema.zed");
960
+ const schema = readFileSync(schemaPath, "utf-8");
950
961
  try {
951
- const existing = await spicedb.readSchema();
962
+ // Always write SpiceDB normalizes formatting so text comparison is unreliable
963
+ api.logger.info("openclaw-memory-rebac: writing SpiceDB schema");
964
+ await spicedb.writeSchema(schema);
952
965
  spicedbOk = true;
953
- if (!existing || !existing.includes("memory_fragment")) {
954
- api.logger.info("openclaw-memory-rebac: writing SpiceDB schema (first run)");
955
- const schemaPath = join(dirname(fileURLToPath(import.meta.url)), "schema.zed");
956
- const schema = readFileSync(schemaPath, "utf-8");
966
+ api.logger.info("openclaw-memory-rebac: SpiceDB schema written successfully");
967
+ }
968
+ catch (err) {
969
+ // Retry once after a short delay (SpiceDB may still be starting)
970
+ api.logger.warn(`openclaw-memory-rebac: SpiceDB schema write failed, retrying in 2s: ${err instanceof Error ? err.message : String(err)}`);
971
+ try {
972
+ await new Promise((r) => setTimeout(r, 2000));
957
973
  await spicedb.writeSchema(schema);
958
- api.logger.info("openclaw-memory-rebac: SpiceDB schema written successfully");
974
+ spicedbOk = true;
975
+ api.logger.info("openclaw-memory-rebac: SpiceDB schema written successfully (retry)");
976
+ }
977
+ catch (retryErr) {
978
+ api.logger.error(`openclaw-memory-rebac: SpiceDB schema write failed after retry: ${retryErr instanceof Error ? retryErr.message : String(retryErr)}`);
959
979
  }
960
- }
961
- catch {
962
- // Will be retried on first use
963
980
  }
964
981
  if (spicedbOk) {
965
982
  // Ensure the config-level subject is a member of the default group
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contextableai/openclaw-memory-rebac",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "OpenClaw composite memory plugin: SpiceDB ReBAC authorization with Graphiti knowledge graph (primary) and optional EverMemOS liminal memory",
5
5
  "type": "module",
6
6
  "license": "MIT",