@xdarkicex/openclaw-memory-libravdb 1.10.4 → 1.10.5

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.
@@ -22,3 +22,4 @@ export declare function resolveIdentity(params: {
22
22
  * 3. Fall back to resolved userId (existing identity system)
23
23
  */
24
24
  export declare function resolveTenantKey(cfg: PluginConfig, agentId?: string): string;
25
+ export declare function resolveReadTenants(cfg: PluginConfig, agentId?: string): string[] | null;
package/dist/identity.js CHANGED
@@ -129,9 +129,11 @@ export function resolveIdentity(params) {
129
129
  export function resolveTenantKey(cfg, agentId) {
130
130
  // Per-agent override (highest priority).
131
131
  if (agentId && cfg.tenantIdByAgent) {
132
- const byAgent = cfg.tenantIdByAgent[agentId]?.trim();
133
- if (byAgent)
134
- return byAgent;
132
+ const entry = cfg.tenantIdByAgent[agentId];
133
+ if (typeof entry === "string")
134
+ return entry.trim();
135
+ if (entry && typeof entry === "object")
136
+ return entry.primary.trim();
135
137
  }
136
138
  const explicit = cfg.tenantId?.trim();
137
139
  if (explicit)
@@ -144,3 +146,16 @@ export function resolveTenantKey(cfg, agentId) {
144
146
  identityPath: cfg.identityPath,
145
147
  }).userId;
146
148
  }
149
+ // resolveReadTenants returns all tenant keys an agent can read from
150
+ // (primary + readAccess). Empty if single-tenant. Used for search fan-out.
151
+ export function resolveReadTenants(cfg, agentId) {
152
+ if (!agentId || !cfg.tenantIdByAgent)
153
+ return null;
154
+ const entry = cfg.tenantIdByAgent[agentId];
155
+ if (!entry || typeof entry === "string")
156
+ return null; // string = primary only, no fan-out
157
+ if (entry.readAccess && entry.readAccess.length > 0) {
158
+ return [entry.primary.trim(), ...entry.readAccess.map((t) => t.trim())];
159
+ }
160
+ return null;
161
+ }
package/dist/index.js CHANGED
@@ -16902,8 +16902,9 @@ function resolveIdentity(params) {
16902
16902
  }
16903
16903
  function resolveTenantKey(cfg, agentId) {
16904
16904
  if (agentId && cfg.tenantIdByAgent) {
16905
- const byAgent = cfg.tenantIdByAgent[agentId]?.trim();
16906
- if (byAgent) return byAgent;
16905
+ const entry = cfg.tenantIdByAgent[agentId];
16906
+ if (typeof entry === "string") return entry.trim();
16907
+ if (entry && typeof entry === "object") return entry.primary.trim();
16907
16908
  }
16908
16909
  const explicit = cfg.tenantId?.trim();
16909
16910
  if (explicit) return explicit;
@@ -16914,6 +16915,15 @@ function resolveTenantKey(cfg, agentId) {
16914
16915
  identityPath: cfg.identityPath
16915
16916
  }).userId;
16916
16917
  }
16918
+ function resolveReadTenants(cfg, agentId) {
16919
+ if (!agentId || !cfg.tenantIdByAgent) return null;
16920
+ const entry = cfg.tenantIdByAgent[agentId];
16921
+ if (!entry || typeof entry === "string") return null;
16922
+ if (entry.readAccess && entry.readAccess.length > 0) {
16923
+ return [entry.primary.trim(), ...entry.readAccess.map((t) => t.trim())];
16924
+ }
16925
+ return null;
16926
+ }
16917
16927
 
16918
16928
  // src/index.ts
16919
16929
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
@@ -35013,6 +35023,7 @@ var LibravDBClient = class {
35013
35023
  nonceHex;
35014
35024
  closed = false;
35015
35025
  tenantKey;
35026
+ readTenants = [];
35016
35027
  constructor(options = {}) {
35017
35028
  this.secret = options.secret ?? loadSecretFromEnv();
35018
35029
  const rawEndpoint = resolveClientEndpoint(options.endpoint);
@@ -35103,6 +35114,11 @@ var LibravDBClient = class {
35103
35114
  setTenantKey(key) {
35104
35115
  this.tenantKey = key;
35105
35116
  }
35117
+ /** Set additional tenants to search across. Only used by searchTextCollections.
35118
+ * Empty by default — zero overhead for single-tenant setups. */
35119
+ setReadTenants(tenants) {
35120
+ this.readTenants = tenants;
35121
+ }
35106
35122
  // ── Session lifecycle ────────────────────────────────────────────
35107
35123
  async health(req = {}) {
35108
35124
  this.guardOpen();
@@ -35152,7 +35168,27 @@ var LibravDBClient = class {
35152
35168
  }
35153
35169
  async searchTextCollections(req) {
35154
35170
  this.guardOpen();
35155
- return this.client.searchTextCollections(req);
35171
+ if (this.readTenants.length === 0) {
35172
+ return this.client.searchTextCollections(req);
35173
+ }
35174
+ const savedKey = this.tenantKey;
35175
+ const allResults = [];
35176
+ const seen = /* @__PURE__ */ new Set();
35177
+ for (const t of this.readTenants) {
35178
+ this.tenantKey = t;
35179
+ try {
35180
+ const resp = await this.client.searchTextCollections(req);
35181
+ for (const r of resp.results ?? []) {
35182
+ if (!seen.has(r.id)) {
35183
+ seen.add(r.id);
35184
+ allResults.push(r);
35185
+ }
35186
+ }
35187
+ } catch {
35188
+ }
35189
+ }
35190
+ this.tenantKey = savedKey;
35191
+ return { results: allResults };
35156
35192
  }
35157
35193
  async listCollection(req) {
35158
35194
  this.guardOpen();
@@ -35673,9 +35709,11 @@ function register(api) {
35673
35709
  if (runtimeOrNull) {
35674
35710
  const agentId = c?.agentId;
35675
35711
  const tenantKey = resolveTenantKey(cfg, agentId);
35712
+ const readTenants = resolveReadTenants(cfg, agentId);
35676
35713
  try {
35677
35714
  const client = await runtimeOrNull.getClient();
35678
35715
  client.setTenantKey(tenantKey);
35716
+ client.setReadTenants(readTenants ?? []);
35679
35717
  } catch {
35680
35718
  }
35681
35719
  }
@@ -36,12 +36,16 @@ export declare class LibravDBClient {
36
36
  private nonceHex;
37
37
  private closed;
38
38
  private tenantKey;
39
+ private readTenants;
39
40
  constructor(options?: LibravDBClientOptions);
40
41
  bootstrapHandshake(): Promise<void>;
41
42
  private guardOpen;
42
43
  /** Update the tenant key for subsequent gRPC calls. Thread-safe —
43
44
  * the interceptor reads this.tenantKey on every request. */
44
45
  setTenantKey(key: string): void;
46
+ /** Set additional tenants to search across. Only used by searchTextCollections.
47
+ * Empty by default — zero overhead for single-tenant setups. */
48
+ setReadTenants(tenants: string[]): void;
45
49
  health(req?: PartialMessage<HealthRequest>): Promise<HealthResponse>;
46
50
  status(req?: PartialMessage<MemoryStatusRequest>): Promise<MemoryStatusResponse>;
47
51
  flush(req?: PartialMessage<FlushRequest>): Promise<FlushResponse>;
@@ -150,6 +150,7 @@ export class LibravDBClient {
150
150
  nonceHex;
151
151
  closed = false;
152
152
  tenantKey;
153
+ readTenants = [];
153
154
  constructor(options = {}) {
154
155
  this.secret = options.secret ?? loadSecretFromEnv();
155
156
  const rawEndpoint = resolveClientEndpoint(options.endpoint);
@@ -237,6 +238,11 @@ export class LibravDBClient {
237
238
  setTenantKey(key) {
238
239
  this.tenantKey = key;
239
240
  }
241
+ /** Set additional tenants to search across. Only used by searchTextCollections.
242
+ * Empty by default — zero overhead for single-tenant setups. */
243
+ setReadTenants(tenants) {
244
+ this.readTenants = tenants;
245
+ }
240
246
  // ── Session lifecycle ────────────────────────────────────────────
241
247
  async health(req = {}) {
242
248
  this.guardOpen();
@@ -286,7 +292,29 @@ export class LibravDBClient {
286
292
  }
287
293
  async searchTextCollections(req) {
288
294
  this.guardOpen();
289
- return this.client.searchTextCollections(req);
295
+ if (this.readTenants.length === 0) {
296
+ return this.client.searchTextCollections(req);
297
+ }
298
+ // Multi-tenant fan-out: search across all read tenants, merge results.
299
+ // Temporarily swap tenantKey per call, restore after.
300
+ const savedKey = this.tenantKey;
301
+ const allResults = [];
302
+ const seen = new Set();
303
+ for (const t of this.readTenants) {
304
+ this.tenantKey = t;
305
+ try {
306
+ const resp = await this.client.searchTextCollections(req);
307
+ for (const r of resp.results ?? []) {
308
+ if (!seen.has(r.id)) {
309
+ seen.add(r.id);
310
+ allResults.push(r);
311
+ }
312
+ }
313
+ }
314
+ catch { /* skip failed tenant reads */ }
315
+ }
316
+ this.tenantKey = savedKey;
317
+ return { results: allResults };
290
318
  }
291
319
  async listCollection(req) {
292
320
  this.guardOpen();
package/dist/types.d.ts CHANGED
@@ -7,9 +7,13 @@ export interface PluginConfig {
7
7
  * the plugin falls back to the auto-derived userId. Set different values per
8
8
  * agent to isolate memory storage. */
9
9
  tenantId?: string;
10
- /** Per-agent tenant overrides. Maps agentId → tenantId. Agents not in this
11
- * map fall through to tenantId userId. Opt-in. */
12
- tenantIdByAgent?: Record<string, string>;
10
+ /** Per-agent tenant overrides. Maps agentId → tenantId (string) or
11
+ * { primary: string, readAccess?: string[] } (object). Agents not listed
12
+ * fall through to tenantId → userId. Opt-in. */
13
+ tenantIdByAgent?: Record<string, string | {
14
+ primary: string;
15
+ readAccess?: string[];
16
+ }>;
13
17
  /** Maximum number of hard constraint rules. Default 20. */
14
18
  maxRules?: number;
15
19
  /** Stable identity for cross-session durable memory. When set, all sessions
@@ -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.4",
5
+ "version": "1.10.5",
6
6
  "kind": [
7
7
  "memory",
8
8
  "context-engine"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xdarkicex/openclaw-memory-libravdb",
3
- "version": "1.10.4",
3
+ "version": "1.10.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",