@xdarkicex/openclaw-memory-libravdb 1.4.45 → 1.4.47

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 CHANGED
@@ -32281,6 +32281,14 @@ function resolveIdentity(params) {
32281
32281
  return { userId: autoId, source: "auto" };
32282
32282
  }
32283
32283
 
32284
+ // src/format-error.ts
32285
+ function formatError(error) {
32286
+ if (error instanceof Error && error.message.trim()) {
32287
+ return error.message.trim();
32288
+ }
32289
+ return String(error);
32290
+ }
32291
+
32284
32292
  // src/dream-promotion.ts
32285
32293
  import fs from "node:fs";
32286
32294
  import fsp from "node:fs/promises";
@@ -32842,12 +32850,6 @@ function createRealFsApi() {
32842
32850
  watch: (dir, onChange) => fs.watch(dir, onChange)
32843
32851
  };
32844
32852
  }
32845
- function formatError(error) {
32846
- if (error instanceof Error) {
32847
- return error.message;
32848
- }
32849
- return String(error);
32850
- }
32851
32853
  var textDecoder = new TextDecoder();
32852
32854
 
32853
32855
  // src/dream-routing.ts
@@ -33237,7 +33239,7 @@ async function runCliCommand(runtime, logger, action) {
33237
33239
  try {
33238
33240
  await runtime.shutdown();
33239
33241
  } catch (error) {
33240
- logger.warn?.(`LibraVDB CLI shutdown failed: ${formatError2(error)}`);
33242
+ logger.warn?.(`LibraVDB CLI shutdown failed: ${formatError(error)}`);
33241
33243
  }
33242
33244
  }
33243
33245
  }
@@ -33268,14 +33270,14 @@ async function runStatus(runtime, cfg, logger, opts = {}) {
33268
33270
  process.exitCode = 1;
33269
33271
  }
33270
33272
  } catch (error) {
33271
- logger.error(`LibraVDB status unavailable: ${formatError2(error)}`);
33273
+ logger.error(`LibraVDB status unavailable: ${formatError(error)}`);
33272
33274
  if (opts.json) {
33273
33275
  console.log(
33274
33276
  JSON.stringify(
33275
33277
  {
33276
33278
  status: {
33277
33279
  ok: false,
33278
- message: formatError2(error),
33280
+ message: formatError(error),
33279
33281
  gatingThreshold: cfg.ingestionGateThreshold ?? 0.35
33280
33282
  }
33281
33283
  },
@@ -33294,7 +33296,7 @@ async function runStatus(runtime, cfg, logger, opts = {}) {
33294
33296
  "Gate threshold": cfg.ingestionGateThreshold ?? 0.35,
33295
33297
  "Abstractive model": "unknown",
33296
33298
  "Embedding profile": "unknown",
33297
- Message: formatError2(error)
33299
+ Message: formatError(error)
33298
33300
  });
33299
33301
  process.exitCode = 1;
33300
33302
  }
@@ -33325,7 +33327,7 @@ async function runDeepStatusProbe(rpc, cfg) {
33325
33327
  probes.push({
33326
33328
  ok: false,
33327
33329
  collection,
33328
- error: formatError2(error)
33330
+ error: formatError(error)
33329
33331
  });
33330
33332
  }
33331
33333
  }
@@ -33372,7 +33374,7 @@ async function runIndex(runtime, _cfg, opts, logger, params = {}) {
33372
33374
  process.exitCode = 1;
33373
33375
  }
33374
33376
  } catch (error) {
33375
- logger.error(`LibraVDB index rebuild failed: ${formatError2(error)}`);
33377
+ logger.error(`LibraVDB index rebuild failed: ${formatError(error)}`);
33376
33378
  process.exitCode = 1;
33377
33379
  }
33378
33380
  }
@@ -33389,7 +33391,7 @@ async function runSearch(runtime, cfg, queryArg, opts, logger) {
33389
33391
  maxResults = normalizeCliLimit(opts?.maxResults ?? opts?.limit, "--max-results");
33390
33392
  explicitMinScore = normalizeCliScore(opts?.minScore, "--min-score");
33391
33393
  } catch (validationError) {
33392
- logger.error(formatError2(validationError));
33394
+ logger.error(formatError(validationError));
33393
33395
  process.exitCode = 1;
33394
33396
  return;
33395
33397
  }
@@ -33420,7 +33422,7 @@ async function runSearch(runtime, cfg, queryArg, opts, logger) {
33420
33422
  console.log("");
33421
33423
  }
33422
33424
  } catch (error) {
33423
- logger.error(`LibraVDB search failed: ${formatError2(error)}`);
33425
+ logger.error(`LibraVDB search failed: ${formatError(error)}`);
33424
33426
  process.exitCode = 1;
33425
33427
  }
33426
33428
  }
@@ -33446,7 +33448,7 @@ async function runFlush(runtime, opts, logger) {
33446
33448
  await rpc.call("flush_namespace", { namespace });
33447
33449
  console.log(`Deleted durable memory namespace ${namespace}.`);
33448
33450
  } catch (error) {
33449
- logger.error(`LibraVDB flush failed: ${formatError2(error)}`);
33451
+ logger.error(`LibraVDB flush failed: ${formatError(error)}`);
33450
33452
  process.exitCode = 1;
33451
33453
  }
33452
33454
  }
@@ -33467,7 +33469,7 @@ async function runExport(runtime, opts, logger) {
33467
33469
  `);
33468
33470
  }
33469
33471
  } catch (error) {
33470
- logger.error(`LibraVDB export failed: ${formatError2(error)}`);
33472
+ logger.error(`LibraVDB export failed: ${formatError(error)}`);
33471
33473
  process.exitCode = 1;
33472
33474
  }
33473
33475
  }
@@ -33476,7 +33478,7 @@ async function runJournal(runtime, opts, logger) {
33476
33478
  try {
33477
33479
  limit = normalizeCliLimit(opts?.limit, "--limit");
33478
33480
  } catch (validationError) {
33479
- logger.error(formatError2(validationError));
33481
+ logger.error(formatError(validationError));
33480
33482
  process.exitCode = 1;
33481
33483
  return;
33482
33484
  }
@@ -33491,7 +33493,7 @@ async function runJournal(runtime, opts, logger) {
33491
33493
  `);
33492
33494
  }
33493
33495
  } catch (error) {
33494
- logger.error(`LibraVDB journal lookup failed: ${formatError2(error)}`);
33496
+ logger.error(`LibraVDB journal lookup failed: ${formatError(error)}`);
33495
33497
  process.exitCode = 1;
33496
33498
  }
33497
33499
  }
@@ -33510,7 +33512,7 @@ async function runDreamPromote(runtime, opts, logger) {
33510
33512
  `Promoted ${result.promoted ?? 0} dream entr${(result.promoted ?? 0) === 1 ? "y" : "ies"}; rejected ${result.rejected ?? 0}.`
33511
33513
  );
33512
33514
  } catch (error) {
33513
- logger.error(`LibraVDB dream promotion failed: ${formatError2(error)}`);
33515
+ logger.error(`LibraVDB dream promotion failed: ${formatError(error)}`);
33514
33516
  process.exitCode = 1;
33515
33517
  }
33516
33518
  }
@@ -33523,12 +33525,6 @@ async function confirm(prompt) {
33523
33525
  rl.close();
33524
33526
  }
33525
33527
  }
33526
- function formatError2(error) {
33527
- if (error instanceof Error && error.message.trim()) {
33528
- return error.message;
33529
- }
33530
- return String(error);
33531
- }
33532
33528
  function normalizeCliLimit(limit, optionName) {
33533
33529
  if (limit === void 0) return void 0;
33534
33530
  const parsed = parseStrictNumber(limit);
@@ -34378,7 +34374,7 @@ function createBeforeResetHook(runtime, logger = console) {
34378
34374
  messageCount: Array.isArray(typedEvent.messages) ? typedEvent.messages.length : void 0
34379
34375
  });
34380
34376
  } catch (error) {
34381
- logger.warn?.(`LibraVDB before_reset hint failed: ${formatError3(error)}`);
34377
+ logger.warn?.(`LibraVDB before_reset hint failed: ${formatError(error)}`);
34382
34378
  }
34383
34379
  };
34384
34380
  }
@@ -34402,7 +34398,7 @@ function createSessionEndHook(runtime, logger = console) {
34402
34398
  nextSessionKey: typedEvent.nextSessionKey
34403
34399
  });
34404
34400
  } catch (error) {
34405
- logger.warn?.(`LibraVDB session_end hint failed: ${formatError3(error)}`);
34401
+ logger.warn?.(`LibraVDB session_end hint failed: ${formatError(error)}`);
34406
34402
  }
34407
34403
  };
34408
34404
  }
@@ -34418,827 +34414,315 @@ function asSessionEndEvent(value) {
34418
34414
  function isRecord(value) {
34419
34415
  return typeof value === "object" && value !== null;
34420
34416
  }
34421
- function formatError3(error) {
34422
- if (error instanceof Error && error.message.trim()) {
34423
- return error.message;
34424
- }
34425
- return String(error);
34426
- }
34427
34417
 
34428
34418
  // src/markdown-ingest.ts
34429
34419
  import fs2 from "node:fs";
34430
34420
  import fsp2 from "node:fs/promises";
34431
34421
  import path2 from "node:path";
34432
- var DEFAULT_DEBOUNCE_MS2 = 150;
34433
- var DEFAULT_TOKENIZER_ID = "markdown-ingest:v1";
34434
- var MARKDOWN_INGEST_VERSION = 3;
34435
- var HASH_BACKEND = "wasm-fnv1a64";
34436
- function createMarkdownIngestionHandle(cfg, getRpc, logger = console, fsApi = createRealFsApi2()) {
34437
- const adapters = [];
34438
- const genericRoots = normalizeMarkdownRoots(cfg.markdownIngestionRoots);
34439
- if (isMarkdownIngestionEnabled(cfg, genericRoots)) {
34440
- adapters.push(
34441
- new DirectoryMarkdownSourceAdapter(
34442
- "generic",
34443
- {
34444
- roots: genericRoots,
34445
- include: cfg.markdownIngestionInclude,
34446
- exclude: cfg.markdownIngestionExclude,
34447
- debounceMs: cfg.markdownIngestionDebounceMs ?? DEFAULT_DEBOUNCE_MS2
34448
- },
34449
- getRpc,
34450
- logger,
34451
- fsApi
34452
- )
34453
- );
34422
+
34423
+ // node_modules/.pnpm/@bufbuild+protobuf@1.7.2/node_modules/@bufbuild/protobuf/dist/proxy/index.js
34424
+ var proxy_exports = {};
34425
+ __reExport(proxy_exports, __toESM(require_cjs(), 1));
34426
+
34427
+ // node_modules/.pnpm/@xdarkicex+libravdb-contracts@0.0.6/node_modules/@xdarkicex/libravdb-contracts/gen/js/libravdb/ipc/v1/rpc_pb.js
34428
+ var IngestMode;
34429
+ (function(IngestMode2) {
34430
+ IngestMode2[IngestMode2["REPLACE"] = 0] = "REPLACE";
34431
+ IngestMode2[IngestMode2["APPEND"] = 1] = "APPEND";
34432
+ })(IngestMode || (IngestMode = {}));
34433
+ proxy_exports.proto3.util.setEnumType(IngestMode, "libravdb.ipc.v1.IngestMode", [
34434
+ { no: 0, name: "INGEST_MODE_REPLACE" },
34435
+ { no: 1, name: "INGEST_MODE_APPEND" }
34436
+ ]);
34437
+ var RpcRequest = class _RpcRequest extends proxy_exports.Message {
34438
+ /**
34439
+ * @generated from field: uint64 id = 1;
34440
+ */
34441
+ id = proxy_exports.protoInt64.zero;
34442
+ /**
34443
+ * @generated from field: string method = 2;
34444
+ */
34445
+ method = "";
34446
+ /**
34447
+ * @generated from field: bytes params = 3;
34448
+ */
34449
+ params = new Uint8Array(0);
34450
+ constructor(data) {
34451
+ super();
34452
+ proxy_exports.proto3.util.initPartial(data, this);
34454
34453
  }
34455
- const obsidianRoots = normalizeMarkdownRoots(cfg.markdownIngestionObsidianRoots);
34456
- if (cfg.markdownIngestionObsidianEnabled !== false && obsidianRoots.length > 0) {
34457
- adapters.push(
34458
- new DirectoryMarkdownSourceAdapter(
34459
- "obsidian",
34460
- {
34461
- roots: obsidianRoots,
34462
- include: cfg.markdownIngestionObsidianInclude,
34463
- exclude: cfg.markdownIngestionObsidianExclude,
34464
- debounceMs: cfg.markdownIngestionObsidianDebounceMs ?? cfg.markdownIngestionDebounceMs ?? DEFAULT_DEBOUNCE_MS2
34465
- },
34466
- getRpc,
34467
- logger,
34468
- fsApi
34469
- )
34470
- );
34454
+ static runtime = proxy_exports.proto3;
34455
+ static typeName = "libravdb.ipc.v1.RpcRequest";
34456
+ static fields = proxy_exports.proto3.util.newFieldList(() => [
34457
+ {
34458
+ no: 1,
34459
+ name: "id",
34460
+ kind: "scalar",
34461
+ T: 4
34462
+ /* ScalarType.UINT64 */
34463
+ },
34464
+ {
34465
+ no: 2,
34466
+ name: "method",
34467
+ kind: "scalar",
34468
+ T: 9
34469
+ /* ScalarType.STRING */
34470
+ },
34471
+ {
34472
+ no: 3,
34473
+ name: "params",
34474
+ kind: "scalar",
34475
+ T: 12
34476
+ /* ScalarType.BYTES */
34477
+ }
34478
+ ]);
34479
+ static fromBinary(bytes, options) {
34480
+ return new _RpcRequest().fromBinary(bytes, options);
34471
34481
  }
34472
- if (adapters.length === 0) {
34473
- return {
34474
- async start() {
34475
- },
34476
- async refresh() {
34477
- },
34478
- async stop() {
34479
- }
34480
- };
34482
+ static fromJson(jsonValue, options) {
34483
+ return new _RpcRequest().fromJson(jsonValue, options);
34481
34484
  }
34482
- const adapter = new CompositeMarkdownSourceAdapter(adapters);
34483
- return {
34484
- start: () => adapter.start(),
34485
- refresh: () => adapter.refresh(),
34486
- stop: () => adapter.stop()
34487
- };
34488
- }
34489
- var CompositeMarkdownSourceAdapter = class {
34490
- constructor(adapters) {
34491
- this.adapters = adapters;
34485
+ static fromJsonString(jsonString, options) {
34486
+ return new _RpcRequest().fromJsonString(jsonString, options);
34492
34487
  }
34493
- adapters;
34494
- kind = "composite";
34495
- async start() {
34496
- for (const adapter of this.adapters) {
34497
- await adapter.start();
34498
- }
34488
+ static equals(a, b) {
34489
+ return proxy_exports.proto3.util.equals(_RpcRequest, a, b);
34499
34490
  }
34500
- async refresh() {
34501
- for (const adapter of this.adapters) {
34502
- await adapter.refresh();
34503
- }
34491
+ };
34492
+ var RpcResponse = class _RpcResponse extends proxy_exports.Message {
34493
+ /**
34494
+ * @generated from field: uint64 id = 1;
34495
+ */
34496
+ id = proxy_exports.protoInt64.zero;
34497
+ /**
34498
+ * @generated from field: bytes result = 2;
34499
+ */
34500
+ result = new Uint8Array(0);
34501
+ /**
34502
+ * @generated from field: libravdb.ipc.v1.RpcError error = 3;
34503
+ */
34504
+ error;
34505
+ constructor(data) {
34506
+ super();
34507
+ proxy_exports.proto3.util.initPartial(data, this);
34504
34508
  }
34505
- async stop() {
34506
- for (const adapter of this.adapters) {
34507
- await adapter.stop();
34508
- }
34509
+ static runtime = proxy_exports.proto3;
34510
+ static typeName = "libravdb.ipc.v1.RpcResponse";
34511
+ static fields = proxy_exports.proto3.util.newFieldList(() => [
34512
+ {
34513
+ no: 1,
34514
+ name: "id",
34515
+ kind: "scalar",
34516
+ T: 4
34517
+ /* ScalarType.UINT64 */
34518
+ },
34519
+ {
34520
+ no: 2,
34521
+ name: "result",
34522
+ kind: "scalar",
34523
+ T: 12
34524
+ /* ScalarType.BYTES */
34525
+ },
34526
+ { no: 3, name: "error", kind: "message", T: RpcError }
34527
+ ]);
34528
+ static fromBinary(bytes, options) {
34529
+ return new _RpcResponse().fromBinary(bytes, options);
34530
+ }
34531
+ static fromJson(jsonValue, options) {
34532
+ return new _RpcResponse().fromJson(jsonValue, options);
34533
+ }
34534
+ static fromJsonString(jsonString, options) {
34535
+ return new _RpcResponse().fromJsonString(jsonString, options);
34536
+ }
34537
+ static equals(a, b) {
34538
+ return proxy_exports.proto3.util.equals(_RpcResponse, a, b);
34509
34539
  }
34510
34540
  };
34511
- var DirectoryMarkdownSourceAdapter = class {
34512
- kind;
34513
- roots;
34514
- includePatterns;
34515
- excludePatterns;
34516
- debounceMs;
34517
- fsApi;
34518
- getRpc;
34519
- logger;
34520
- states = /* @__PURE__ */ new Map();
34521
- fileStates = /* @__PURE__ */ new Map();
34522
- activeScans = /* @__PURE__ */ new Set();
34523
- tokenizerId;
34524
- coreDoc;
34525
- started = false;
34526
- stopping = false;
34527
- constructor(kind, config, getRpc, logger, fsApi) {
34528
- this.kind = kind;
34529
- this.roots = config.roots;
34530
- this.includePatterns = config.include?.length ? config.include : [];
34531
- this.excludePatterns = config.exclude?.length ? config.exclude : [];
34532
- this.debounceMs = config.debounceMs ?? DEFAULT_DEBOUNCE_MS2;
34533
- this.fsApi = fsApi;
34534
- this.getRpc = getRpc;
34535
- this.logger = logger;
34536
- this.tokenizerId = DEFAULT_TOKENIZER_ID;
34537
- this.coreDoc = true;
34541
+ var RpcError = class _RpcError extends proxy_exports.Message {
34542
+ /**
34543
+ * @generated from field: string message = 1;
34544
+ */
34545
+ message = "";
34546
+ /**
34547
+ * @generated from field: int32 code = 2;
34548
+ */
34549
+ code = 0;
34550
+ constructor(data) {
34551
+ super();
34552
+ proxy_exports.proto3.util.initPartial(data, this);
34538
34553
  }
34539
- async start() {
34540
- if (this.started) {
34541
- return;
34554
+ static runtime = proxy_exports.proto3;
34555
+ static typeName = "libravdb.ipc.v1.RpcError";
34556
+ static fields = proxy_exports.proto3.util.newFieldList(() => [
34557
+ {
34558
+ no: 1,
34559
+ name: "message",
34560
+ kind: "scalar",
34561
+ T: 9
34562
+ /* ScalarType.STRING */
34563
+ },
34564
+ {
34565
+ no: 2,
34566
+ name: "code",
34567
+ kind: "scalar",
34568
+ T: 5
34569
+ /* ScalarType.INT32 */
34542
34570
  }
34543
- this.started = true;
34544
- this.stopping = false;
34545
- await this.refresh();
34571
+ ]);
34572
+ static fromBinary(bytes, options) {
34573
+ return new _RpcError().fromBinary(bytes, options);
34546
34574
  }
34547
- async refresh() {
34548
- if (!this.started || this.stopping) {
34549
- return;
34550
- }
34551
- for (const root of this.roots) {
34552
- await this.scanRoot(root);
34553
- }
34575
+ static fromJson(jsonValue, options) {
34576
+ return new _RpcError().fromJson(jsonValue, options);
34554
34577
  }
34555
- async stop() {
34556
- this.stopping = true;
34557
- for (const state of this.states.values()) {
34558
- if (state.scanState.timer) {
34559
- clearTimeout(state.scanState.timer);
34560
- state.scanState.timer = null;
34561
- }
34562
- for (const watcher of state.directoryWatchers.values()) {
34563
- watcher.close();
34564
- }
34565
- state.directoryWatchers.clear();
34566
- }
34567
- if (this.activeScans.size > 0) {
34568
- await Promise.allSettled([...this.activeScans]);
34569
- }
34570
- this.states.clear();
34571
- this.fileStates.clear();
34572
- this.started = false;
34578
+ static fromJsonString(jsonString, options) {
34579
+ return new _RpcError().fromJsonString(jsonString, options);
34573
34580
  }
34574
- getRootState(root) {
34575
- const resolved = path2.resolve(root);
34576
- const existing = this.states.get(resolved);
34577
- if (existing) {
34578
- return existing;
34579
- }
34580
- const created = {
34581
- root: resolved,
34582
- scanState: {
34583
- scanning: false,
34584
- dirty: false,
34585
- timer: null
34586
- },
34587
- knownFiles: /* @__PURE__ */ new Set(),
34588
- directoryWatchers: /* @__PURE__ */ new Map()
34589
- };
34590
- this.states.set(resolved, created);
34591
- return created;
34581
+ static equals(a, b) {
34582
+ return proxy_exports.proto3.util.equals(_RpcError, a, b);
34592
34583
  }
34593
- async scanRoot(root) {
34594
- if (!this.started || this.stopping) {
34595
- return;
34596
- }
34597
- const rootState = this.getRootState(root);
34598
- if (rootState.scanState.scanning) {
34599
- rootState.scanState.dirty = true;
34600
- return;
34601
- }
34602
- rootState.scanState.scanning = true;
34603
- const scan = (async () => {
34604
- try {
34605
- const currentFiles = /* @__PURE__ */ new Set();
34606
- await this.walkDirectory(rootState, rootState.root, currentFiles);
34607
- if (!this.stopping) {
34608
- await this.pruneDeletedFiles(rootState, currentFiles);
34609
- rootState.knownFiles = currentFiles;
34610
- }
34611
- } finally {
34612
- rootState.scanState.scanning = false;
34613
- if (rootState.scanState.dirty) {
34614
- rootState.scanState.dirty = false;
34615
- if (!this.stopping) {
34616
- this.scheduleRootScan(rootState);
34617
- }
34618
- }
34619
- }
34620
- })();
34621
- this.activeScans.add(scan);
34622
- try {
34623
- await scan;
34624
- } finally {
34625
- this.activeScans.delete(scan);
34626
- }
34584
+ };
34585
+ var StringList = class _StringList extends proxy_exports.Message {
34586
+ /**
34587
+ * @generated from field: repeated string values = 1;
34588
+ */
34589
+ values = [];
34590
+ constructor(data) {
34591
+ super();
34592
+ proxy_exports.proto3.util.initPartial(data, this);
34627
34593
  }
34628
- scheduleRootScan(rootState) {
34629
- if (!this.started || this.stopping) {
34630
- return;
34631
- }
34632
- if (rootState.scanState.scanning) {
34633
- rootState.scanState.dirty = true;
34634
- return;
34635
- }
34636
- if (rootState.scanState.timer) {
34637
- return;
34638
- }
34639
- rootState.scanState.timer = setTimeout(() => {
34640
- rootState.scanState.timer = null;
34641
- void this.scanRoot(rootState.root).catch((error) => {
34642
- this.logger.warn?.(`[markdown-ingest] root scan failed for ${rootState.root}: ${formatError4(error)}`);
34643
- });
34644
- }, this.debounceMs);
34594
+ static runtime = proxy_exports.proto3;
34595
+ static typeName = "libravdb.ipc.v1.StringList";
34596
+ static fields = proxy_exports.proto3.util.newFieldList(() => [
34597
+ { no: 1, name: "values", kind: "scalar", T: 9, repeated: true }
34598
+ ]);
34599
+ static fromBinary(bytes, options) {
34600
+ return new _StringList().fromBinary(bytes, options);
34645
34601
  }
34646
- async walkDirectory(rootState, dir, currentFiles) {
34647
- await this.ensureDirectoryWatcher(rootState, dir);
34648
- let entries;
34649
- try {
34650
- entries = await this.fsApi.readdir(dir);
34651
- } catch (error) {
34652
- const message = formatError4(error);
34653
- if (!message.includes("ENOENT")) {
34654
- this.logger.warn?.(`[markdown-ingest] readdir failed for ${dir}: ${message}`);
34655
- }
34656
- return;
34657
- }
34658
- for (const entry of entries) {
34659
- if (this.stopping) {
34660
- return;
34661
- }
34662
- const child = path2.join(dir, entry.name);
34663
- if (entry.isDirectory()) {
34664
- await this.walkDirectory(rootState, child, currentFiles);
34665
- continue;
34666
- }
34667
- if (!entry.isFile() || !isMarkdownFile(entry.name)) {
34668
- continue;
34669
- }
34670
- if (!this.shouldIncludeFile(rootState.root, child)) {
34671
- continue;
34672
- }
34673
- currentFiles.add(child);
34674
- try {
34675
- await this.syncMarkdownFile(rootState, child);
34676
- } catch (error) {
34677
- if (!this.stopping) {
34678
- this.logger.warn?.(`[markdown-ingest] sync failed for ${child}: ${formatError4(error)}`);
34679
- }
34680
- }
34681
- }
34602
+ static fromJson(jsonValue, options) {
34603
+ return new _StringList().fromJson(jsonValue, options);
34682
34604
  }
34683
- async ensureDirectoryWatcher(rootState, dir) {
34684
- if (rootState.directoryWatchers.has(dir)) {
34685
- return;
34686
- }
34687
- try {
34688
- const watcher = this.fsApi.watch(dir, () => {
34689
- if (!this.stopping) {
34690
- this.scheduleRootScan(rootState);
34691
- }
34692
- });
34693
- watcher.on("error", (error) => {
34694
- this.logger.warn?.(`[markdown-ingest] watch error for ${dir}: ${formatError4(error)}`);
34695
- });
34696
- rootState.directoryWatchers.set(dir, watcher);
34697
- } catch (error) {
34698
- this.logger.warn?.(`[markdown-ingest] watch unavailable for ${dir}: ${formatError4(error)}`);
34699
- }
34605
+ static fromJsonString(jsonString, options) {
34606
+ return new _StringList().fromJsonString(jsonString, options);
34700
34607
  }
34701
- shouldIncludeFile(root, filePath) {
34702
- if (isOpenClawMemoryFile(filePath)) {
34703
- return true;
34704
- }
34705
- const relative = toPosixPath(path2.relative(root, filePath));
34706
- if (this.excludePatterns.length > 0) {
34707
- for (const pattern of this.excludePatterns) {
34708
- if (matchesGlob(relative, pattern)) {
34709
- return false;
34710
- }
34711
- }
34712
- }
34713
- if (this.includePatterns.length > 0) {
34714
- for (const pattern of this.includePatterns) {
34715
- if (matchesGlob(relative, pattern)) {
34716
- return true;
34717
- }
34718
- }
34719
- return false;
34720
- }
34721
- return true;
34608
+ static equals(a, b) {
34609
+ return proxy_exports.proto3.util.equals(_StringList, a, b);
34722
34610
  }
34723
- async pruneDeletedFiles(rootState, currentFiles) {
34724
- const removed = [];
34725
- for (const previous of rootState.knownFiles) {
34726
- if (!currentFiles.has(previous)) {
34727
- removed.push(previous);
34728
- }
34729
- }
34730
- if (removed.length === 0) {
34731
- return;
34732
- }
34733
- for (const filePath of removed) {
34734
- await this.deleteSourceDocument(filePath);
34735
- this.fileStates.delete(filePath);
34736
- }
34737
- }
34738
- async syncMarkdownFile(rootState, filePath) {
34739
- const sourceDoc = filePath;
34740
- const relativePath = toPosixPath(path2.relative(rootState.root, filePath));
34741
- const stat = await this.safeStat(filePath);
34742
- if (!stat) {
34743
- await this.deleteSourceDocument(sourceDoc);
34744
- this.fileStates.delete(sourceDoc);
34745
- return;
34746
- }
34747
- const cached = this.fileStates.get(sourceDoc);
34748
- if (cached && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs) {
34749
- return;
34750
- }
34751
- const bytes = await this.safeReadFile(filePath);
34752
- if (!bytes) {
34753
- await this.deleteSourceDocument(sourceDoc);
34754
- this.fileStates.delete(sourceDoc);
34755
- return;
34756
- }
34757
- const fileHash = hashBytes(bytes);
34758
- if (cached && cached.fileHash === fileHash) {
34759
- this.fileStates.set(sourceDoc, {
34760
- root: rootState.root,
34761
- sourceDoc,
34762
- relativePath,
34763
- fileHash,
34764
- size: stat.size,
34765
- mtimeMs: stat.mtimeMs
34766
- });
34767
- return;
34768
- }
34769
- const text = textDecoder2.decode(bytes);
34770
- if (this.kind === "obsidian" && this.includePatterns.length === 0 && !looksLikeObsidianNote(filePath, text)) {
34771
- await this.deleteSourceDocument(sourceDoc);
34772
- this.fileStates.delete(sourceDoc);
34773
- return;
34774
- }
34775
- await this.ingestMarkdownDocument(sourceDoc, text, rootState.root, relativePath, fileHash, stat.size, stat.mtimeMs);
34776
- this.fileStates.set(sourceDoc, {
34777
- root: rootState.root,
34778
- sourceDoc,
34779
- relativePath,
34780
- fileHash,
34781
- size: stat.size,
34782
- mtimeMs: stat.mtimeMs
34783
- });
34784
- }
34785
- async ingestMarkdownDocument(sourceDoc, text, sourceRoot, sourcePath, fileHash, sourceSize, sourceMtimeMs) {
34786
- const rpc = await this.getRpc();
34787
- const params = {
34788
- sourceDoc,
34789
- text,
34790
- tokenizerId: this.tokenizerId,
34791
- coreDoc: this.coreDoc,
34792
- sourceMeta: {
34793
- sourceRoot,
34794
- sourcePath,
34795
- sourceKind: this.kind,
34796
- fileHash,
34797
- sourceSize,
34798
- sourceMtimeMs: Math.trunc(sourceMtimeMs),
34799
- ingestVersion: MARKDOWN_INGEST_VERSION,
34800
- hashBackend: HASH_BACKEND
34801
- }
34802
- };
34803
- await rpc.call("ingest_markdown_document", params);
34804
- }
34805
- async deleteSourceDocument(sourceDoc) {
34806
- const rpc = await this.getRpc();
34807
- const params = { sourceDoc };
34808
- await rpc.call("delete_authored_document", params);
34809
- }
34810
- async safeStat(filePath) {
34811
- try {
34812
- return await this.fsApi.stat(filePath);
34813
- } catch {
34814
- return null;
34815
- }
34816
- }
34817
- async safeReadFile(filePath) {
34818
- try {
34819
- return await this.fsApi.readFile(filePath);
34820
- } catch {
34821
- return null;
34822
- }
34823
- }
34824
- };
34825
- function toPosixPath(value) {
34826
- return value.split(path2.sep).join("/");
34827
- }
34828
- var textDecoder2 = new TextDecoder();
34829
- function normalizeMarkdownRoots(roots) {
34830
- if (!roots?.length) {
34831
- return [];
34832
- }
34833
- const resolved = /* @__PURE__ */ new Set();
34834
- for (const root of roots) {
34835
- const trimmed = root.trim();
34836
- if (!trimmed) {
34837
- continue;
34838
- }
34839
- resolved.add(path2.resolve(trimmed));
34840
- }
34841
- return [...resolved];
34842
- }
34843
- function isMarkdownIngestionEnabled(cfg, roots) {
34844
- if (cfg.markdownIngestionEnabled === false) {
34845
- return false;
34846
- }
34847
- return roots.length > 0;
34848
- }
34849
- function createRealFsApi2() {
34850
- return {
34851
- readdir: async (dir) => fsp2.readdir(dir, { withFileTypes: true }),
34852
- readFile: async (file) => fsp2.readFile(file),
34853
- stat: async (file) => {
34854
- const stat = await fsp2.stat(file);
34855
- return { size: stat.size, mtimeMs: stat.mtimeMs };
34856
- },
34857
- watch: (dir, onChange) => fs2.watch(dir, onChange)
34858
- };
34859
- }
34860
- function isMarkdownFile(fileName) {
34861
- const lower = fileName.toLowerCase();
34862
- return lower.endsWith(".md") || lower.endsWith(".markdown");
34863
- }
34864
- function matchesGlob(value, pattern) {
34865
- const escaped = pattern.split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*");
34866
- return new RegExp(`^${escaped}$`).test(value);
34867
- }
34868
- function formatError4(error) {
34869
- if (error instanceof Error) {
34870
- return error.message;
34871
- }
34872
- return String(error);
34873
- }
34874
- function looksLikeObsidianNote(filePath, text) {
34875
- if (!text.startsWith("---\n")) {
34876
- return hasInlineObsidianTag(text);
34877
- }
34878
- const frontmatterEnd = findFrontmatterEnd(text, 4);
34879
- if (frontmatterEnd < 0) {
34880
- return hasInlineObsidianTag(text);
34881
- }
34882
- const frontmatter = text.slice(4, frontmatterEnd);
34883
- const lines = frontmatter.split("\n");
34884
- for (const line of lines) {
34885
- const trimmed = line.trimStart();
34886
- if (trimmed.startsWith("tags:") || trimmed.startsWith("tag:") || trimmed.startsWith("openclaw:") || trimmed.startsWith("memory:")) {
34887
- return true;
34888
- }
34889
- }
34890
- return hasInlineObsidianTag(text.slice(frontmatterEnd + 4));
34891
- }
34892
- function findFrontmatterEnd(text, offset) {
34893
- for (let i = offset; i < text.length - 3; i++) {
34894
- if (text.charCodeAt(i) !== 45 || text.charCodeAt(i + 1) !== 45 || text.charCodeAt(i + 2) !== 45) {
34895
- continue;
34896
- }
34897
- const next = text.charCodeAt(i + 3);
34898
- if (next === 10) {
34899
- return i;
34900
- }
34901
- if (next === 13 && text.charCodeAt(i + 4) === 10) {
34902
- return i;
34903
- }
34904
- }
34905
- return -1;
34906
- }
34907
- function hasInlineObsidianTag(text) {
34908
- let inFence = false;
34909
- const lines = text.split("\n");
34910
- for (const line of lines) {
34911
- const trimmed = line.trimStart();
34912
- if (trimmed.startsWith("```") || trimmed.startsWith("~~~")) {
34913
- inFence = !inFence;
34914
- continue;
34915
- }
34916
- if (inFence) {
34917
- continue;
34918
- }
34919
- if (trimmed.startsWith("#")) {
34920
- continue;
34921
- }
34922
- if (/(^|[^A-Za-z0-9_])#([A-Za-z][A-Za-z0-9/_-]*)\b/.test(line)) {
34923
- return true;
34924
- }
34925
- }
34926
- return false;
34927
- }
34928
- function isOpenClawMemoryFile(filePath) {
34929
- return path2.basename(filePath).toLowerCase() === "memory.md";
34930
- }
34931
-
34932
- // src/memory-provider.ts
34933
- var MEMORY_PROMPT_HEADER = [
34934
- "## Memory",
34935
- "LibraVDB persistent memory is configured. Recalled memories may appear",
34936
- "in context via the context-engine assembler when available and relevant.",
34937
- ""
34938
- ];
34939
- function buildMemoryPromptSection(_getRpc, _cfg) {
34940
- return function memoryPromptSection({
34941
- availableTools: _availableTools,
34942
- citationsMode: _citationsMode
34943
- }) {
34944
- return [...MEMORY_PROMPT_HEADER];
34945
- };
34946
- }
34947
-
34948
- // node_modules/.pnpm/@bufbuild+protobuf@1.7.2/node_modules/@bufbuild/protobuf/dist/proxy/index.js
34949
- var proxy_exports = {};
34950
- __reExport(proxy_exports, __toESM(require_cjs(), 1));
34951
-
34952
- // node_modules/.pnpm/@xdarkicex+libravdb-contracts@0.0.1/node_modules/@xdarkicex/libravdb-contracts/gen/js/libravdb/ipc/v1/rpc_pb.js
34953
- var RpcRequest = class _RpcRequest extends proxy_exports.Message {
34954
- /**
34955
- * @generated from field: uint64 id = 1;
34956
- */
34957
- id = proxy_exports.protoInt64.zero;
34958
- /**
34959
- * @generated from field: string method = 2;
34960
- */
34961
- method = "";
34962
- /**
34963
- * @generated from field: bytes params = 3;
34964
- */
34965
- params = new Uint8Array(0);
34966
- constructor(data) {
34967
- super();
34968
- proxy_exports.proto3.util.initPartial(data, this);
34611
+ };
34612
+ var SearchResult = class _SearchResult extends proxy_exports.Message {
34613
+ /**
34614
+ * @generated from field: string id = 1;
34615
+ */
34616
+ id = "";
34617
+ /**
34618
+ * @generated from field: double score = 2;
34619
+ */
34620
+ score = 0;
34621
+ /**
34622
+ * @generated from field: string text = 3;
34623
+ */
34624
+ text = "";
34625
+ /**
34626
+ * @generated from field: google.protobuf.Struct metadata = 4;
34627
+ */
34628
+ metadata;
34629
+ /**
34630
+ * @generated from field: uint64 version = 5;
34631
+ */
34632
+ version = proxy_exports.protoInt64.zero;
34633
+ constructor(data) {
34634
+ super();
34635
+ proxy_exports.proto3.util.initPartial(data, this);
34969
34636
  }
34970
34637
  static runtime = proxy_exports.proto3;
34971
- static typeName = "libravdb.ipc.v1.RpcRequest";
34638
+ static typeName = "libravdb.ipc.v1.SearchResult";
34972
34639
  static fields = proxy_exports.proto3.util.newFieldList(() => [
34973
34640
  {
34974
34641
  no: 1,
34975
34642
  name: "id",
34976
34643
  kind: "scalar",
34977
- T: 4
34978
- /* ScalarType.UINT64 */
34644
+ T: 9
34645
+ /* ScalarType.STRING */
34979
34646
  },
34980
34647
  {
34981
34648
  no: 2,
34982
- name: "method",
34649
+ name: "score",
34650
+ kind: "scalar",
34651
+ T: 1
34652
+ /* ScalarType.DOUBLE */
34653
+ },
34654
+ {
34655
+ no: 3,
34656
+ name: "text",
34983
34657
  kind: "scalar",
34984
34658
  T: 9
34985
34659
  /* ScalarType.STRING */
34986
34660
  },
34661
+ { no: 4, name: "metadata", kind: "message", T: proxy_exports.Struct },
34987
34662
  {
34988
- no: 3,
34989
- name: "params",
34663
+ no: 5,
34664
+ name: "version",
34990
34665
  kind: "scalar",
34991
- T: 12
34992
- /* ScalarType.BYTES */
34666
+ T: 4
34667
+ /* ScalarType.UINT64 */
34993
34668
  }
34994
34669
  ]);
34995
34670
  static fromBinary(bytes, options) {
34996
- return new _RpcRequest().fromBinary(bytes, options);
34671
+ return new _SearchResult().fromBinary(bytes, options);
34997
34672
  }
34998
34673
  static fromJson(jsonValue, options) {
34999
- return new _RpcRequest().fromJson(jsonValue, options);
34674
+ return new _SearchResult().fromJson(jsonValue, options);
35000
34675
  }
35001
34676
  static fromJsonString(jsonString, options) {
35002
- return new _RpcRequest().fromJsonString(jsonString, options);
34677
+ return new _SearchResult().fromJsonString(jsonString, options);
35003
34678
  }
35004
34679
  static equals(a, b) {
35005
- return proxy_exports.proto3.util.equals(_RpcRequest, a, b);
34680
+ return proxy_exports.proto3.util.equals(_SearchResult, a, b);
35006
34681
  }
35007
34682
  };
35008
- var RpcResponse = class _RpcResponse extends proxy_exports.Message {
34683
+ var MarkdownSourceMeta = class _MarkdownSourceMeta extends proxy_exports.Message {
35009
34684
  /**
35010
- * @generated from field: uint64 id = 1;
34685
+ * @generated from field: string source_root = 1;
35011
34686
  */
35012
- id = proxy_exports.protoInt64.zero;
34687
+ sourceRoot = "";
35013
34688
  /**
35014
- * @generated from field: bytes result = 2;
34689
+ * @generated from field: string source_path = 2;
35015
34690
  */
35016
- result = new Uint8Array(0);
34691
+ sourcePath = "";
35017
34692
  /**
35018
- * @generated from field: libravdb.ipc.v1.RpcError error = 3;
34693
+ * @generated from field: string source_kind = 3;
35019
34694
  */
35020
- error;
34695
+ sourceKind = "";
34696
+ /**
34697
+ * @generated from field: string file_hash = 4;
34698
+ */
34699
+ fileHash = "";
34700
+ /**
34701
+ * @generated from field: int64 source_size = 5;
34702
+ */
34703
+ sourceSize = proxy_exports.protoInt64.zero;
34704
+ /**
34705
+ * @generated from field: int64 source_mtime_ms = 6;
34706
+ */
34707
+ sourceMtimeMs = proxy_exports.protoInt64.zero;
34708
+ /**
34709
+ * @generated from field: int32 ingest_version = 7;
34710
+ */
34711
+ ingestVersion = 0;
34712
+ /**
34713
+ * @generated from field: string hash_backend = 8;
34714
+ */
34715
+ hashBackend = "";
35021
34716
  constructor(data) {
35022
34717
  super();
35023
34718
  proxy_exports.proto3.util.initPartial(data, this);
35024
34719
  }
35025
34720
  static runtime = proxy_exports.proto3;
35026
- static typeName = "libravdb.ipc.v1.RpcResponse";
34721
+ static typeName = "libravdb.ipc.v1.MarkdownSourceMeta";
35027
34722
  static fields = proxy_exports.proto3.util.newFieldList(() => [
35028
34723
  {
35029
34724
  no: 1,
35030
- name: "id",
35031
- kind: "scalar",
35032
- T: 4
35033
- /* ScalarType.UINT64 */
35034
- },
35035
- {
35036
- no: 2,
35037
- name: "result",
35038
- kind: "scalar",
35039
- T: 12
35040
- /* ScalarType.BYTES */
35041
- },
35042
- { no: 3, name: "error", kind: "message", T: RpcError }
35043
- ]);
35044
- static fromBinary(bytes, options) {
35045
- return new _RpcResponse().fromBinary(bytes, options);
35046
- }
35047
- static fromJson(jsonValue, options) {
35048
- return new _RpcResponse().fromJson(jsonValue, options);
35049
- }
35050
- static fromJsonString(jsonString, options) {
35051
- return new _RpcResponse().fromJsonString(jsonString, options);
35052
- }
35053
- static equals(a, b) {
35054
- return proxy_exports.proto3.util.equals(_RpcResponse, a, b);
35055
- }
35056
- };
35057
- var RpcError = class _RpcError extends proxy_exports.Message {
35058
- /**
35059
- * @generated from field: string message = 1;
35060
- */
35061
- message = "";
35062
- /**
35063
- * @generated from field: int32 code = 2;
35064
- */
35065
- code = 0;
35066
- constructor(data) {
35067
- super();
35068
- proxy_exports.proto3.util.initPartial(data, this);
35069
- }
35070
- static runtime = proxy_exports.proto3;
35071
- static typeName = "libravdb.ipc.v1.RpcError";
35072
- static fields = proxy_exports.proto3.util.newFieldList(() => [
35073
- {
35074
- no: 1,
35075
- name: "message",
35076
- kind: "scalar",
35077
- T: 9
35078
- /* ScalarType.STRING */
35079
- },
35080
- {
35081
- no: 2,
35082
- name: "code",
35083
- kind: "scalar",
35084
- T: 5
35085
- /* ScalarType.INT32 */
35086
- }
35087
- ]);
35088
- static fromBinary(bytes, options) {
35089
- return new _RpcError().fromBinary(bytes, options);
35090
- }
35091
- static fromJson(jsonValue, options) {
35092
- return new _RpcError().fromJson(jsonValue, options);
35093
- }
35094
- static fromJsonString(jsonString, options) {
35095
- return new _RpcError().fromJsonString(jsonString, options);
35096
- }
35097
- static equals(a, b) {
35098
- return proxy_exports.proto3.util.equals(_RpcError, a, b);
35099
- }
35100
- };
35101
- var StringList = class _StringList extends proxy_exports.Message {
35102
- /**
35103
- * @generated from field: repeated string values = 1;
35104
- */
35105
- values = [];
35106
- constructor(data) {
35107
- super();
35108
- proxy_exports.proto3.util.initPartial(data, this);
35109
- }
35110
- static runtime = proxy_exports.proto3;
35111
- static typeName = "libravdb.ipc.v1.StringList";
35112
- static fields = proxy_exports.proto3.util.newFieldList(() => [
35113
- { no: 1, name: "values", kind: "scalar", T: 9, repeated: true }
35114
- ]);
35115
- static fromBinary(bytes, options) {
35116
- return new _StringList().fromBinary(bytes, options);
35117
- }
35118
- static fromJson(jsonValue, options) {
35119
- return new _StringList().fromJson(jsonValue, options);
35120
- }
35121
- static fromJsonString(jsonString, options) {
35122
- return new _StringList().fromJsonString(jsonString, options);
35123
- }
35124
- static equals(a, b) {
35125
- return proxy_exports.proto3.util.equals(_StringList, a, b);
35126
- }
35127
- };
35128
- var SearchResult = class _SearchResult extends proxy_exports.Message {
35129
- /**
35130
- * @generated from field: string id = 1;
35131
- */
35132
- id = "";
35133
- /**
35134
- * @generated from field: double score = 2;
35135
- */
35136
- score = 0;
35137
- /**
35138
- * @generated from field: string text = 3;
35139
- */
35140
- text = "";
35141
- /**
35142
- * @generated from field: google.protobuf.Struct metadata = 4;
35143
- */
35144
- metadata;
35145
- /**
35146
- * @generated from field: uint64 version = 5;
35147
- */
35148
- version = proxy_exports.protoInt64.zero;
35149
- constructor(data) {
35150
- super();
35151
- proxy_exports.proto3.util.initPartial(data, this);
35152
- }
35153
- static runtime = proxy_exports.proto3;
35154
- static typeName = "libravdb.ipc.v1.SearchResult";
35155
- static fields = proxy_exports.proto3.util.newFieldList(() => [
35156
- {
35157
- no: 1,
35158
- name: "id",
35159
- kind: "scalar",
35160
- T: 9
35161
- /* ScalarType.STRING */
35162
- },
35163
- {
35164
- no: 2,
35165
- name: "score",
35166
- kind: "scalar",
35167
- T: 1
35168
- /* ScalarType.DOUBLE */
35169
- },
35170
- {
35171
- no: 3,
35172
- name: "text",
35173
- kind: "scalar",
35174
- T: 9
35175
- /* ScalarType.STRING */
35176
- },
35177
- { no: 4, name: "metadata", kind: "message", T: proxy_exports.Struct },
35178
- {
35179
- no: 5,
35180
- name: "version",
35181
- kind: "scalar",
35182
- T: 4
35183
- /* ScalarType.UINT64 */
35184
- }
35185
- ]);
35186
- static fromBinary(bytes, options) {
35187
- return new _SearchResult().fromBinary(bytes, options);
35188
- }
35189
- static fromJson(jsonValue, options) {
35190
- return new _SearchResult().fromJson(jsonValue, options);
35191
- }
35192
- static fromJsonString(jsonString, options) {
35193
- return new _SearchResult().fromJsonString(jsonString, options);
35194
- }
35195
- static equals(a, b) {
35196
- return proxy_exports.proto3.util.equals(_SearchResult, a, b);
35197
- }
35198
- };
35199
- var MarkdownSourceMeta = class _MarkdownSourceMeta extends proxy_exports.Message {
35200
- /**
35201
- * @generated from field: string source_root = 1;
35202
- */
35203
- sourceRoot = "";
35204
- /**
35205
- * @generated from field: string source_path = 2;
35206
- */
35207
- sourcePath = "";
35208
- /**
35209
- * @generated from field: string source_kind = 3;
35210
- */
35211
- sourceKind = "";
35212
- /**
35213
- * @generated from field: string file_hash = 4;
35214
- */
35215
- fileHash = "";
35216
- /**
35217
- * @generated from field: int64 source_size = 5;
35218
- */
35219
- sourceSize = proxy_exports.protoInt64.zero;
35220
- /**
35221
- * @generated from field: int64 source_mtime_ms = 6;
35222
- */
35223
- sourceMtimeMs = proxy_exports.protoInt64.zero;
35224
- /**
35225
- * @generated from field: int32 ingest_version = 7;
35226
- */
35227
- ingestVersion = 0;
35228
- /**
35229
- * @generated from field: string hash_backend = 8;
35230
- */
35231
- hashBackend = "";
35232
- constructor(data) {
35233
- super();
35234
- proxy_exports.proto3.util.initPartial(data, this);
35235
- }
35236
- static runtime = proxy_exports.proto3;
35237
- static typeName = "libravdb.ipc.v1.MarkdownSourceMeta";
35238
- static fields = proxy_exports.proto3.util.newFieldList(() => [
35239
- {
35240
- no: 1,
35241
- name: "source_root",
34725
+ name: "source_root",
35242
34726
  kind: "scalar",
35243
34727
  T: 9
35244
34728
  /* ScalarType.STRING */
@@ -36528,6 +36012,12 @@ var IngestMarkdownDocumentRequest = class _IngestMarkdownDocumentRequest extends
36528
36012
  * @generated from field: libravdb.ipc.v1.MarkdownSourceMeta source_meta = 5;
36529
36013
  */
36530
36014
  sourceMeta;
36015
+ /**
36016
+ * default INGEST_MODE_REPLACE if absent
36017
+ *
36018
+ * @generated from field: libravdb.ipc.v1.IngestMode mode = 6;
36019
+ */
36020
+ mode = IngestMode.REPLACE;
36531
36021
  constructor(data) {
36532
36022
  super();
36533
36023
  proxy_exports.proto3.util.initPartial(data, this);
@@ -36563,7 +36053,8 @@ var IngestMarkdownDocumentRequest = class _IngestMarkdownDocumentRequest extends
36563
36053
  T: 8
36564
36054
  /* ScalarType.BOOL */
36565
36055
  },
36566
- { no: 5, name: "source_meta", kind: "message", T: MarkdownSourceMeta }
36056
+ { no: 5, name: "source_meta", kind: "message", T: MarkdownSourceMeta },
36057
+ { no: 6, name: "mode", kind: "enum", T: proxy_exports.proto3.getEnumType(IngestMode) }
36567
36058
  ]);
36568
36059
  static fromBinary(bytes, options) {
36569
36060
  return new _IngestMarkdownDocumentRequest().fromBinary(bytes, options);
@@ -38608,132 +38099,781 @@ var RankCandidatesRequest = class _RankCandidatesRequest extends proxy_exports.M
38608
38099
  static equals(a, b) {
38609
38100
  return proxy_exports.proto3.util.equals(_RankCandidatesRequest, a, b);
38610
38101
  }
38611
- };
38612
- var RankCandidatesResponse = class _RankCandidatesResponse extends proxy_exports.Message {
38613
- /**
38614
- * @generated from field: repeated libravdb.ipc.v1.RankCandidate ranked = 1;
38615
- */
38616
- ranked = [];
38617
- constructor(data) {
38618
- super();
38619
- proxy_exports.proto3.util.initPartial(data, this);
38102
+ };
38103
+ var RankCandidatesResponse = class _RankCandidatesResponse extends proxy_exports.Message {
38104
+ /**
38105
+ * @generated from field: repeated libravdb.ipc.v1.RankCandidate ranked = 1;
38106
+ */
38107
+ ranked = [];
38108
+ constructor(data) {
38109
+ super();
38110
+ proxy_exports.proto3.util.initPartial(data, this);
38111
+ }
38112
+ static runtime = proxy_exports.proto3;
38113
+ static typeName = "libravdb.ipc.v1.RankCandidatesResponse";
38114
+ static fields = proxy_exports.proto3.util.newFieldList(() => [
38115
+ { no: 1, name: "ranked", kind: "message", T: RankCandidate, repeated: true }
38116
+ ]);
38117
+ static fromBinary(bytes, options) {
38118
+ return new _RankCandidatesResponse().fromBinary(bytes, options);
38119
+ }
38120
+ static fromJson(jsonValue, options) {
38121
+ return new _RankCandidatesResponse().fromJson(jsonValue, options);
38122
+ }
38123
+ static fromJsonString(jsonString, options) {
38124
+ return new _RankCandidatesResponse().fromJsonString(jsonString, options);
38125
+ }
38126
+ static equals(a, b) {
38127
+ return proxy_exports.proto3.util.equals(_RankCandidatesResponse, a, b);
38128
+ }
38129
+ };
38130
+ var RebuildIndexRequest = class _RebuildIndexRequest extends proxy_exports.Message {
38131
+ /**
38132
+ * @generated from field: string namespace = 1;
38133
+ */
38134
+ namespace = "";
38135
+ /**
38136
+ * @generated from field: repeated string collections = 2;
38137
+ */
38138
+ collections = [];
38139
+ constructor(data) {
38140
+ super();
38141
+ proxy_exports.proto3.util.initPartial(data, this);
38142
+ }
38143
+ static runtime = proxy_exports.proto3;
38144
+ static typeName = "libravdb.ipc.v1.RebuildIndexRequest";
38145
+ static fields = proxy_exports.proto3.util.newFieldList(() => [
38146
+ {
38147
+ no: 1,
38148
+ name: "namespace",
38149
+ kind: "scalar",
38150
+ T: 9
38151
+ /* ScalarType.STRING */
38152
+ },
38153
+ { no: 2, name: "collections", kind: "scalar", T: 9, repeated: true }
38154
+ ]);
38155
+ static fromBinary(bytes, options) {
38156
+ return new _RebuildIndexRequest().fromBinary(bytes, options);
38157
+ }
38158
+ static fromJson(jsonValue, options) {
38159
+ return new _RebuildIndexRequest().fromJson(jsonValue, options);
38160
+ }
38161
+ static fromJsonString(jsonString, options) {
38162
+ return new _RebuildIndexRequest().fromJsonString(jsonString, options);
38163
+ }
38164
+ static equals(a, b) {
38165
+ return proxy_exports.proto3.util.equals(_RebuildIndexRequest, a, b);
38166
+ }
38167
+ };
38168
+ var RebuildIndexResponse = class _RebuildIndexResponse extends proxy_exports.Message {
38169
+ /**
38170
+ * @generated from field: int32 collections_processed = 1;
38171
+ */
38172
+ collectionsProcessed = 0;
38173
+ /**
38174
+ * @generated from field: int32 records_reindexed = 2;
38175
+ */
38176
+ recordsReindexed = 0;
38177
+ /**
38178
+ * @generated from field: int32 collections_recreated = 3;
38179
+ */
38180
+ collectionsRecreated = 0;
38181
+ /**
38182
+ * @generated from field: repeated string errors = 4;
38183
+ */
38184
+ errors = [];
38185
+ constructor(data) {
38186
+ super();
38187
+ proxy_exports.proto3.util.initPartial(data, this);
38188
+ }
38189
+ static runtime = proxy_exports.proto3;
38190
+ static typeName = "libravdb.ipc.v1.RebuildIndexResponse";
38191
+ static fields = proxy_exports.proto3.util.newFieldList(() => [
38192
+ {
38193
+ no: 1,
38194
+ name: "collections_processed",
38195
+ kind: "scalar",
38196
+ T: 5
38197
+ /* ScalarType.INT32 */
38198
+ },
38199
+ {
38200
+ no: 2,
38201
+ name: "records_reindexed",
38202
+ kind: "scalar",
38203
+ T: 5
38204
+ /* ScalarType.INT32 */
38205
+ },
38206
+ {
38207
+ no: 3,
38208
+ name: "collections_recreated",
38209
+ kind: "scalar",
38210
+ T: 5
38211
+ /* ScalarType.INT32 */
38212
+ },
38213
+ { no: 4, name: "errors", kind: "scalar", T: 9, repeated: true }
38214
+ ]);
38215
+ static fromBinary(bytes, options) {
38216
+ return new _RebuildIndexResponse().fromBinary(bytes, options);
38217
+ }
38218
+ static fromJson(jsonValue, options) {
38219
+ return new _RebuildIndexResponse().fromJson(jsonValue, options);
38220
+ }
38221
+ static fromJsonString(jsonString, options) {
38222
+ return new _RebuildIndexResponse().fromJsonString(jsonString, options);
38223
+ }
38224
+ static equals(a, b) {
38225
+ return proxy_exports.proto3.util.equals(_RebuildIndexResponse, a, b);
38226
+ }
38227
+ };
38228
+
38229
+ // src/ingest-queue.ts
38230
+ var DEFAULT_OPTIONS = {
38231
+ chunkTokens: 8192,
38232
+ retryBaseDelayMs: 500,
38233
+ maxRetries: 4
38234
+ };
38235
+ var IngestQueue = class {
38236
+ queue = [];
38237
+ rpcCall;
38238
+ logger;
38239
+ options;
38240
+ running = false;
38241
+ constructor(rpcCall, logger, options = {}) {
38242
+ this.rpcCall = rpcCall;
38243
+ this.logger = logger;
38244
+ this.options = { ...DEFAULT_OPTIONS, ...options };
38245
+ }
38246
+ async enqueueIngest(sourceDoc, text, baseParams) {
38247
+ if (this.options.chunkTokens === Infinity) {
38248
+ return this.ingestWithRetry({
38249
+ ...baseParams,
38250
+ sourceDoc,
38251
+ text,
38252
+ mode: IngestMode.REPLACE
38253
+ });
38254
+ }
38255
+ const chunks = splitIntoChunks(text, this.options.chunkTokens);
38256
+ if (chunks.length === 1) {
38257
+ return this.ingestWithRetry({
38258
+ ...baseParams,
38259
+ sourceDoc,
38260
+ text: chunks[0].text,
38261
+ mode: IngestMode.REPLACE
38262
+ });
38263
+ }
38264
+ for (let i = 0; i < chunks.length; i++) {
38265
+ const isLast = i === chunks.length - 1;
38266
+ const chunkParams = {
38267
+ ...baseParams,
38268
+ sourceDoc,
38269
+ text: chunks[i].text,
38270
+ mode: isLast ? IngestMode.REPLACE : IngestMode.APPEND
38271
+ };
38272
+ await this.ingestWithRetry(chunkParams);
38273
+ }
38274
+ }
38275
+ async ingestWithRetry(params) {
38276
+ await withRetry(
38277
+ () => this.rpcCall("ingest_markdown_document", params),
38278
+ this.options.maxRetries,
38279
+ this.options.retryBaseDelayMs,
38280
+ this.logger,
38281
+ `ingest_markdown_document(${params.sourceDoc})`
38282
+ );
38283
+ }
38284
+ async enqueueDelete(sourceDoc) {
38285
+ await withRetry(
38286
+ () => this.rpcCall("delete_authored_document", { sourceDoc }),
38287
+ this.options.maxRetries,
38288
+ this.options.retryBaseDelayMs,
38289
+ this.logger,
38290
+ `delete_authored_document(${sourceDoc})`
38291
+ );
38292
+ }
38293
+ };
38294
+ function splitIntoChunks(text, maxTokens) {
38295
+ const maxChars = maxTokens * 4;
38296
+ if (text.length <= maxChars) {
38297
+ return [{ text, ordinal: 0 }];
38298
+ }
38299
+ const chunks = [];
38300
+ let offset = 0;
38301
+ let ordinal = 0;
38302
+ while (offset < text.length) {
38303
+ let end = Math.min(offset + maxChars, text.length);
38304
+ const probeLimit = Math.min(256, end - offset);
38305
+ let hardCut = end;
38306
+ for (let i = 0; i < probeLimit; i++) {
38307
+ const pos = end - i;
38308
+ const ch = text.charAt(pos);
38309
+ if (ch === "\n" && text.charAt(pos + 1) === "\n") {
38310
+ hardCut = pos + 2;
38311
+ break;
38312
+ }
38313
+ }
38314
+ if (hardCut === end) {
38315
+ for (let i = 0; i < probeLimit; i++) {
38316
+ const pos = end - i;
38317
+ if (text.charAt(pos) === "\n") {
38318
+ hardCut = pos + 1;
38319
+ break;
38320
+ }
38321
+ }
38322
+ }
38323
+ if (hardCut === end) {
38324
+ for (let i = 0; i < probeLimit; i++) {
38325
+ const pos = end - i;
38326
+ if (text.charAt(pos) === " ") {
38327
+ hardCut = pos;
38328
+ break;
38329
+ }
38330
+ }
38331
+ }
38332
+ chunks.push({ text: text.slice(offset, hardCut), ordinal });
38333
+ ordinal++;
38334
+ offset = hardCut;
38335
+ }
38336
+ return chunks;
38337
+ }
38338
+ async function withRetry(fn, maxRetries, baseDelayMs, logger, label) {
38339
+ let lastError;
38340
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
38341
+ try {
38342
+ return await fn();
38343
+ } catch (err) {
38344
+ lastError = err;
38345
+ if (attempt < maxRetries) {
38346
+ const cap = baseDelayMs * Math.pow(2, attempt);
38347
+ const delay = Math.random() * cap;
38348
+ logger.warn?.(`[ingest-queue] ${label} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${Math.round(delay)}ms: ${err}`);
38349
+ await sleep(delay);
38350
+ }
38351
+ }
38352
+ }
38353
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
38354
+ }
38355
+ function sleep(ms) {
38356
+ return new Promise((resolve) => setTimeout(resolve, ms));
38357
+ }
38358
+
38359
+ // src/markdown-ingest.ts
38360
+ var DEFAULT_DEBOUNCE_MS2 = 150;
38361
+ var DEFAULT_TOKENIZER_ID = "markdown-ingest:v1";
38362
+ var MARKDOWN_INGEST_VERSION = 3;
38363
+ var HASH_BACKEND = "wasm-fnv1a64";
38364
+ function createMarkdownIngestionHandle(cfg, getRpc, logger = console, fsApi = createRealFsApi2()) {
38365
+ const adapters = [];
38366
+ const genericRoots = normalizeMarkdownRoots(cfg.markdownIngestionRoots);
38367
+ if (isMarkdownIngestionEnabled(cfg, genericRoots)) {
38368
+ adapters.push(
38369
+ new DirectoryMarkdownSourceAdapter(
38370
+ "generic",
38371
+ {
38372
+ roots: genericRoots,
38373
+ include: cfg.markdownIngestionInclude,
38374
+ exclude: cfg.markdownIngestionExclude,
38375
+ debounceMs: cfg.markdownIngestionDebounceMs ?? DEFAULT_DEBOUNCE_MS2
38376
+ },
38377
+ getRpc,
38378
+ logger,
38379
+ fsApi
38380
+ )
38381
+ );
38382
+ }
38383
+ const obsidianRoots = normalizeMarkdownRoots(cfg.markdownIngestionObsidianRoots);
38384
+ if (cfg.markdownIngestionObsidianEnabled !== false && obsidianRoots.length > 0) {
38385
+ adapters.push(
38386
+ new DirectoryMarkdownSourceAdapter(
38387
+ "obsidian",
38388
+ {
38389
+ roots: obsidianRoots,
38390
+ include: cfg.markdownIngestionObsidianInclude,
38391
+ exclude: cfg.markdownIngestionObsidianExclude,
38392
+ debounceMs: cfg.markdownIngestionObsidianDebounceMs ?? cfg.markdownIngestionDebounceMs ?? DEFAULT_DEBOUNCE_MS2
38393
+ },
38394
+ getRpc,
38395
+ logger,
38396
+ fsApi
38397
+ )
38398
+ );
38399
+ }
38400
+ if (adapters.length === 0) {
38401
+ return {
38402
+ async start() {
38403
+ },
38404
+ async refresh() {
38405
+ },
38406
+ async stop() {
38407
+ }
38408
+ };
38409
+ }
38410
+ const adapter = new CompositeMarkdownSourceAdapter(adapters);
38411
+ return {
38412
+ start: () => adapter.start(),
38413
+ refresh: () => adapter.refresh(),
38414
+ stop: () => adapter.stop()
38415
+ };
38416
+ }
38417
+ var CompositeMarkdownSourceAdapter = class {
38418
+ constructor(adapters) {
38419
+ this.adapters = adapters;
38420
+ }
38421
+ adapters;
38422
+ kind = "composite";
38423
+ async start() {
38424
+ for (const adapter of this.adapters) {
38425
+ await adapter.start();
38426
+ }
38427
+ }
38428
+ async refresh() {
38429
+ for (const adapter of this.adapters) {
38430
+ await adapter.refresh();
38431
+ }
38432
+ }
38433
+ async stop() {
38434
+ for (const adapter of this.adapters) {
38435
+ await adapter.stop();
38436
+ }
38437
+ }
38438
+ };
38439
+ var DirectoryMarkdownSourceAdapter = class {
38440
+ kind;
38441
+ roots;
38442
+ includePatterns;
38443
+ excludePatterns;
38444
+ debounceMs;
38445
+ fsApi;
38446
+ getRpc;
38447
+ logger;
38448
+ states = /* @__PURE__ */ new Map();
38449
+ fileStates = /* @__PURE__ */ new Map();
38450
+ activeScans = /* @__PURE__ */ new Set();
38451
+ tokenizerId;
38452
+ coreDoc;
38453
+ started = false;
38454
+ ingestQueue = null;
38455
+ stopping = false;
38456
+ constructor(kind, config, getRpc, logger, fsApi) {
38457
+ this.kind = kind;
38458
+ this.roots = config.roots;
38459
+ this.includePatterns = config.include?.length ? config.include : [];
38460
+ this.excludePatterns = config.exclude?.length ? config.exclude : [];
38461
+ this.debounceMs = config.debounceMs ?? DEFAULT_DEBOUNCE_MS2;
38462
+ this.fsApi = fsApi;
38463
+ this.getRpc = getRpc;
38464
+ this.logger = logger;
38465
+ this.tokenizerId = DEFAULT_TOKENIZER_ID;
38466
+ this.coreDoc = true;
38467
+ }
38468
+ async start() {
38469
+ if (this.started) {
38470
+ return;
38471
+ }
38472
+ this.started = true;
38473
+ this.stopping = false;
38474
+ await this.refresh();
38475
+ }
38476
+ async refresh() {
38477
+ if (!this.started || this.stopping) {
38478
+ return;
38479
+ }
38480
+ for (const root of this.roots) {
38481
+ await this.scanRoot(root);
38482
+ }
38483
+ }
38484
+ async stop() {
38485
+ this.stopping = true;
38486
+ for (const state of this.states.values()) {
38487
+ if (state.scanState.timer) {
38488
+ clearTimeout(state.scanState.timer);
38489
+ state.scanState.timer = null;
38490
+ }
38491
+ for (const watcher of state.directoryWatchers.values()) {
38492
+ watcher.close();
38493
+ }
38494
+ state.directoryWatchers.clear();
38495
+ }
38496
+ if (this.activeScans.size > 0) {
38497
+ await Promise.allSettled([...this.activeScans]);
38498
+ }
38499
+ this.states.clear();
38500
+ this.fileStates.clear();
38501
+ this.started = false;
38502
+ }
38503
+ getRootState(root) {
38504
+ const resolved = path2.resolve(root);
38505
+ const existing = this.states.get(resolved);
38506
+ if (existing) {
38507
+ return existing;
38508
+ }
38509
+ const created = {
38510
+ root: resolved,
38511
+ scanState: {
38512
+ scanning: false,
38513
+ dirty: false,
38514
+ timer: null
38515
+ },
38516
+ knownFiles: /* @__PURE__ */ new Set(),
38517
+ directoryWatchers: /* @__PURE__ */ new Map()
38518
+ };
38519
+ this.states.set(resolved, created);
38520
+ return created;
38521
+ }
38522
+ async scanRoot(root) {
38523
+ if (!this.started || this.stopping) {
38524
+ return;
38525
+ }
38526
+ const rootState = this.getRootState(root);
38527
+ if (rootState.scanState.scanning) {
38528
+ rootState.scanState.dirty = true;
38529
+ return;
38530
+ }
38531
+ rootState.scanState.scanning = true;
38532
+ const scan = (async () => {
38533
+ try {
38534
+ const currentFiles = /* @__PURE__ */ new Set();
38535
+ await this.walkDirectory(rootState, rootState.root, currentFiles);
38536
+ if (!this.stopping) {
38537
+ await this.pruneDeletedFiles(rootState, currentFiles);
38538
+ rootState.knownFiles = currentFiles;
38539
+ }
38540
+ } finally {
38541
+ rootState.scanState.scanning = false;
38542
+ if (rootState.scanState.dirty) {
38543
+ rootState.scanState.dirty = false;
38544
+ if (!this.stopping) {
38545
+ this.scheduleRootScan(rootState);
38546
+ }
38547
+ }
38548
+ }
38549
+ })();
38550
+ this.activeScans.add(scan);
38551
+ try {
38552
+ await scan;
38553
+ } finally {
38554
+ this.activeScans.delete(scan);
38555
+ }
38556
+ }
38557
+ scheduleRootScan(rootState) {
38558
+ if (!this.started || this.stopping) {
38559
+ return;
38560
+ }
38561
+ if (rootState.scanState.scanning) {
38562
+ rootState.scanState.dirty = true;
38563
+ return;
38564
+ }
38565
+ if (rootState.scanState.timer) {
38566
+ return;
38567
+ }
38568
+ rootState.scanState.timer = setTimeout(() => {
38569
+ rootState.scanState.timer = null;
38570
+ void this.scanRoot(rootState.root).catch((error) => {
38571
+ this.logger.warn?.(`[markdown-ingest] root scan failed for ${rootState.root}: ${formatError(error)}`);
38572
+ });
38573
+ }, this.debounceMs);
38574
+ }
38575
+ async walkDirectory(rootState, dir, currentFiles) {
38576
+ await this.ensureDirectoryWatcher(rootState, dir);
38577
+ let entries;
38578
+ try {
38579
+ entries = await this.fsApi.readdir(dir);
38580
+ } catch (error) {
38581
+ const message = formatError(error);
38582
+ if (!message.includes("ENOENT")) {
38583
+ this.logger.warn?.(`[markdown-ingest] readdir failed for ${dir}: ${message}`);
38584
+ }
38585
+ return;
38586
+ }
38587
+ for (const entry of entries) {
38588
+ if (this.stopping) {
38589
+ return;
38590
+ }
38591
+ const child = path2.join(dir, entry.name);
38592
+ if (entry.isDirectory()) {
38593
+ await this.walkDirectory(rootState, child, currentFiles);
38594
+ continue;
38595
+ }
38596
+ if (!entry.isFile() || !isMarkdownFile(entry.name)) {
38597
+ continue;
38598
+ }
38599
+ if (!this.shouldIncludeFile(rootState.root, child)) {
38600
+ continue;
38601
+ }
38602
+ currentFiles.add(child);
38603
+ try {
38604
+ await this.syncMarkdownFile(rootState, child);
38605
+ } catch (error) {
38606
+ if (!this.stopping) {
38607
+ this.logger.warn?.(`[markdown-ingest] sync failed for ${child}: ${formatError(error)}`);
38608
+ }
38609
+ }
38610
+ }
38611
+ }
38612
+ async ensureDirectoryWatcher(rootState, dir) {
38613
+ if (rootState.directoryWatchers.has(dir)) {
38614
+ return;
38615
+ }
38616
+ try {
38617
+ const watcher = this.fsApi.watch(dir, () => {
38618
+ if (!this.stopping) {
38619
+ this.scheduleRootScan(rootState);
38620
+ }
38621
+ });
38622
+ watcher.on("error", (error) => {
38623
+ this.logger.warn?.(`[markdown-ingest] watch error for ${dir}: ${formatError(error)}`);
38624
+ });
38625
+ rootState.directoryWatchers.set(dir, watcher);
38626
+ } catch (error) {
38627
+ this.logger.warn?.(`[markdown-ingest] watch unavailable for ${dir}: ${formatError(error)}`);
38628
+ }
38629
+ }
38630
+ shouldIncludeFile(root, filePath) {
38631
+ if (isOpenClawMemoryFile(filePath)) {
38632
+ return true;
38633
+ }
38634
+ const relative = toPosixPath(path2.relative(root, filePath));
38635
+ if (this.excludePatterns.length > 0) {
38636
+ for (const pattern of this.excludePatterns) {
38637
+ if (matchesGlob(relative, pattern)) {
38638
+ return false;
38639
+ }
38640
+ }
38641
+ }
38642
+ if (this.includePatterns.length > 0) {
38643
+ for (const pattern of this.includePatterns) {
38644
+ if (matchesGlob(relative, pattern)) {
38645
+ return true;
38646
+ }
38647
+ }
38648
+ return false;
38649
+ }
38650
+ return true;
38651
+ }
38652
+ async pruneDeletedFiles(rootState, currentFiles) {
38653
+ const removed = [];
38654
+ for (const previous of rootState.knownFiles) {
38655
+ if (!currentFiles.has(previous)) {
38656
+ removed.push(previous);
38657
+ }
38658
+ }
38659
+ if (removed.length === 0) {
38660
+ return;
38661
+ }
38662
+ for (const filePath of removed) {
38663
+ await this.deleteSourceDocument(filePath);
38664
+ this.fileStates.delete(filePath);
38665
+ }
38666
+ }
38667
+ async syncMarkdownFile(rootState, filePath) {
38668
+ const sourceDoc = filePath;
38669
+ const relativePath = toPosixPath(path2.relative(rootState.root, filePath));
38670
+ const stat = await this.safeStat(filePath);
38671
+ if (!stat) {
38672
+ await this.deleteSourceDocument(sourceDoc);
38673
+ this.fileStates.delete(sourceDoc);
38674
+ return;
38675
+ }
38676
+ const cached = this.fileStates.get(sourceDoc);
38677
+ if (cached && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs) {
38678
+ return;
38679
+ }
38680
+ const bytes = await this.safeReadFile(filePath);
38681
+ if (!bytes) {
38682
+ await this.deleteSourceDocument(sourceDoc);
38683
+ this.fileStates.delete(sourceDoc);
38684
+ return;
38685
+ }
38686
+ const fileHash = hashBytes(bytes);
38687
+ if (cached && cached.fileHash === fileHash) {
38688
+ this.fileStates.set(sourceDoc, {
38689
+ root: rootState.root,
38690
+ sourceDoc,
38691
+ relativePath,
38692
+ fileHash,
38693
+ size: stat.size,
38694
+ mtimeMs: stat.mtimeMs
38695
+ });
38696
+ return;
38697
+ }
38698
+ const text = textDecoder2.decode(bytes);
38699
+ if (this.kind === "obsidian" && this.includePatterns.length === 0 && !looksLikeObsidianNote(filePath, text)) {
38700
+ await this.deleteSourceDocument(sourceDoc);
38701
+ this.fileStates.delete(sourceDoc);
38702
+ return;
38703
+ }
38704
+ await this.ingestMarkdownDocument(sourceDoc, text, rootState.root, relativePath, fileHash, stat.size, stat.mtimeMs);
38705
+ this.fileStates.set(sourceDoc, {
38706
+ root: rootState.root,
38707
+ sourceDoc,
38708
+ relativePath,
38709
+ fileHash,
38710
+ size: stat.size,
38711
+ mtimeMs: stat.mtimeMs
38712
+ });
38713
+ }
38714
+ async ingestMarkdownDocument(sourceDoc, text, sourceRoot, sourcePath, fileHash, sourceSize, sourceMtimeMs) {
38715
+ const queue = await this.getIngestQueue();
38716
+ await queue.enqueueIngest(
38717
+ sourceDoc,
38718
+ text,
38719
+ {
38720
+ tokenizerId: this.tokenizerId,
38721
+ coreDoc: this.coreDoc,
38722
+ sourceMeta: {
38723
+ sourceRoot,
38724
+ sourcePath,
38725
+ sourceKind: this.kind,
38726
+ fileHash,
38727
+ sourceSize,
38728
+ sourceMtimeMs: Math.trunc(sourceMtimeMs),
38729
+ ingestVersion: MARKDOWN_INGEST_VERSION,
38730
+ hashBackend: HASH_BACKEND
38731
+ }
38732
+ }
38733
+ );
38620
38734
  }
38621
- static runtime = proxy_exports.proto3;
38622
- static typeName = "libravdb.ipc.v1.RankCandidatesResponse";
38623
- static fields = proxy_exports.proto3.util.newFieldList(() => [
38624
- { no: 1, name: "ranked", kind: "message", T: RankCandidate, repeated: true }
38625
- ]);
38626
- static fromBinary(bytes, options) {
38627
- return new _RankCandidatesResponse().fromBinary(bytes, options);
38735
+ async deleteSourceDocument(sourceDoc) {
38736
+ const queue = await this.getIngestQueue();
38737
+ await queue.enqueueDelete(sourceDoc);
38628
38738
  }
38629
- static fromJson(jsonValue, options) {
38630
- return new _RankCandidatesResponse().fromJson(jsonValue, options);
38739
+ async getIngestQueue() {
38740
+ if (!this.ingestQueue) {
38741
+ const rpc = await this.getRpc();
38742
+ this.ingestQueue = new IngestQueue(rpc.call.bind(rpc), this.logger);
38743
+ }
38744
+ return this.ingestQueue;
38631
38745
  }
38632
- static fromJsonString(jsonString, options) {
38633
- return new _RankCandidatesResponse().fromJsonString(jsonString, options);
38746
+ async safeStat(filePath) {
38747
+ try {
38748
+ return await this.fsApi.stat(filePath);
38749
+ } catch {
38750
+ return null;
38751
+ }
38634
38752
  }
38635
- static equals(a, b) {
38636
- return proxy_exports.proto3.util.equals(_RankCandidatesResponse, a, b);
38753
+ async safeReadFile(filePath) {
38754
+ try {
38755
+ return await this.fsApi.readFile(filePath);
38756
+ } catch {
38757
+ return null;
38758
+ }
38637
38759
  }
38638
38760
  };
38639
- var RebuildIndexRequest = class _RebuildIndexRequest extends proxy_exports.Message {
38640
- /**
38641
- * @generated from field: string namespace = 1;
38642
- */
38643
- namespace = "";
38644
- /**
38645
- * @generated from field: repeated string collections = 2;
38646
- */
38647
- collections = [];
38648
- constructor(data) {
38649
- super();
38650
- proxy_exports.proto3.util.initPartial(data, this);
38651
- }
38652
- static runtime = proxy_exports.proto3;
38653
- static typeName = "libravdb.ipc.v1.RebuildIndexRequest";
38654
- static fields = proxy_exports.proto3.util.newFieldList(() => [
38655
- {
38656
- no: 1,
38657
- name: "namespace",
38658
- kind: "scalar",
38659
- T: 9
38660
- /* ScalarType.STRING */
38661
- },
38662
- { no: 2, name: "collections", kind: "scalar", T: 9, repeated: true }
38663
- ]);
38664
- static fromBinary(bytes, options) {
38665
- return new _RebuildIndexRequest().fromBinary(bytes, options);
38666
- }
38667
- static fromJson(jsonValue, options) {
38668
- return new _RebuildIndexRequest().fromJson(jsonValue, options);
38669
- }
38670
- static fromJsonString(jsonString, options) {
38671
- return new _RebuildIndexRequest().fromJsonString(jsonString, options);
38761
+ function toPosixPath(value) {
38762
+ return value.split(path2.sep).join("/");
38763
+ }
38764
+ var textDecoder2 = new TextDecoder();
38765
+ function normalizeMarkdownRoots(roots) {
38766
+ if (!roots?.length) {
38767
+ return [];
38672
38768
  }
38673
- static equals(a, b) {
38674
- return proxy_exports.proto3.util.equals(_RebuildIndexRequest, a, b);
38769
+ const resolved = /* @__PURE__ */ new Set();
38770
+ for (const root of roots) {
38771
+ const trimmed = root.trim();
38772
+ if (!trimmed) {
38773
+ continue;
38774
+ }
38775
+ resolved.add(path2.resolve(trimmed));
38675
38776
  }
38676
- };
38677
- var RebuildIndexResponse = class _RebuildIndexResponse extends proxy_exports.Message {
38678
- /**
38679
- * @generated from field: int32 collections_processed = 1;
38680
- */
38681
- collectionsProcessed = 0;
38682
- /**
38683
- * @generated from field: int32 records_reindexed = 2;
38684
- */
38685
- recordsReindexed = 0;
38686
- /**
38687
- * @generated from field: int32 collections_recreated = 3;
38688
- */
38689
- collectionsRecreated = 0;
38690
- /**
38691
- * @generated from field: repeated string errors = 4;
38692
- */
38693
- errors = [];
38694
- constructor(data) {
38695
- super();
38696
- proxy_exports.proto3.util.initPartial(data, this);
38777
+ return [...resolved];
38778
+ }
38779
+ function isMarkdownIngestionEnabled(cfg, roots) {
38780
+ if (cfg.markdownIngestionEnabled === false) {
38781
+ return false;
38697
38782
  }
38698
- static runtime = proxy_exports.proto3;
38699
- static typeName = "libravdb.ipc.v1.RebuildIndexResponse";
38700
- static fields = proxy_exports.proto3.util.newFieldList(() => [
38701
- {
38702
- no: 1,
38703
- name: "collections_processed",
38704
- kind: "scalar",
38705
- T: 5
38706
- /* ScalarType.INT32 */
38707
- },
38708
- {
38709
- no: 2,
38710
- name: "records_reindexed",
38711
- kind: "scalar",
38712
- T: 5
38713
- /* ScalarType.INT32 */
38714
- },
38715
- {
38716
- no: 3,
38717
- name: "collections_recreated",
38718
- kind: "scalar",
38719
- T: 5
38720
- /* ScalarType.INT32 */
38783
+ return roots.length > 0;
38784
+ }
38785
+ function createRealFsApi2() {
38786
+ return {
38787
+ readdir: async (dir) => fsp2.readdir(dir, { withFileTypes: true }),
38788
+ readFile: async (file) => fsp2.readFile(file),
38789
+ stat: async (file) => {
38790
+ const stat = await fsp2.stat(file);
38791
+ return { size: stat.size, mtimeMs: stat.mtimeMs };
38721
38792
  },
38722
- { no: 4, name: "errors", kind: "scalar", T: 9, repeated: true }
38723
- ]);
38724
- static fromBinary(bytes, options) {
38725
- return new _RebuildIndexResponse().fromBinary(bytes, options);
38793
+ watch: (dir, onChange) => fs2.watch(dir, onChange)
38794
+ };
38795
+ }
38796
+ function isMarkdownFile(fileName) {
38797
+ const lower = fileName.toLowerCase();
38798
+ return lower.endsWith(".md") || lower.endsWith(".markdown");
38799
+ }
38800
+ function matchesGlob(value, pattern) {
38801
+ const escaped = pattern.split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*");
38802
+ return new RegExp(`^${escaped}$`).test(value);
38803
+ }
38804
+ function looksLikeObsidianNote(filePath, text) {
38805
+ if (!text.startsWith("---\n")) {
38806
+ return hasInlineObsidianTag(text);
38726
38807
  }
38727
- static fromJson(jsonValue, options) {
38728
- return new _RebuildIndexResponse().fromJson(jsonValue, options);
38808
+ const frontmatterEnd = findFrontmatterEnd(text, 4);
38809
+ if (frontmatterEnd < 0) {
38810
+ return hasInlineObsidianTag(text);
38729
38811
  }
38730
- static fromJsonString(jsonString, options) {
38731
- return new _RebuildIndexResponse().fromJsonString(jsonString, options);
38812
+ const frontmatter = text.slice(4, frontmatterEnd);
38813
+ const lines = frontmatter.split("\n");
38814
+ for (const line of lines) {
38815
+ const trimmed = line.trimStart();
38816
+ if (trimmed.startsWith("tags:") || trimmed.startsWith("tag:") || trimmed.startsWith("openclaw:") || trimmed.startsWith("memory:")) {
38817
+ return true;
38818
+ }
38732
38819
  }
38733
- static equals(a, b) {
38734
- return proxy_exports.proto3.util.equals(_RebuildIndexResponse, a, b);
38820
+ return hasInlineObsidianTag(text.slice(frontmatterEnd + 4));
38821
+ }
38822
+ function findFrontmatterEnd(text, offset) {
38823
+ for (let i = offset; i < text.length - 3; i++) {
38824
+ if (text.charCodeAt(i) !== 45 || text.charCodeAt(i + 1) !== 45 || text.charCodeAt(i + 2) !== 45) {
38825
+ continue;
38826
+ }
38827
+ const next = text.charCodeAt(i + 3);
38828
+ if (next === 10) {
38829
+ return i;
38830
+ }
38831
+ if (next === 13 && text.charCodeAt(i + 4) === 10) {
38832
+ return i;
38833
+ }
38735
38834
  }
38736
- };
38835
+ return -1;
38836
+ }
38837
+ function hasInlineObsidianTag(text) {
38838
+ let inFence = false;
38839
+ const lines = text.split("\n");
38840
+ for (const line of lines) {
38841
+ const trimmed = line.trimStart();
38842
+ if (trimmed.startsWith("```") || trimmed.startsWith("~~~")) {
38843
+ inFence = !inFence;
38844
+ continue;
38845
+ }
38846
+ if (inFence) {
38847
+ continue;
38848
+ }
38849
+ if (trimmed.startsWith("#")) {
38850
+ continue;
38851
+ }
38852
+ if (/(^|[^A-Za-z0-9_])#([A-Za-z][A-Za-z0-9/_-]*)\b/.test(line)) {
38853
+ return true;
38854
+ }
38855
+ }
38856
+ return false;
38857
+ }
38858
+ function isOpenClawMemoryFile(filePath) {
38859
+ return path2.basename(filePath).toLowerCase() === "memory.md";
38860
+ }
38861
+
38862
+ // src/memory-provider.ts
38863
+ var MEMORY_PROMPT_HEADER = [
38864
+ "## Memory",
38865
+ "LibraVDB persistent memory is configured. Recalled memories may appear",
38866
+ "in context via the context-engine assembler when available and relevant.",
38867
+ ""
38868
+ ];
38869
+ function buildMemoryPromptSection(_getRpc, _cfg) {
38870
+ return function memoryPromptSection({
38871
+ availableTools: _availableTools,
38872
+ citationsMode: _citationsMode
38873
+ }) {
38874
+ return [...MEMORY_PROMPT_HEADER];
38875
+ };
38876
+ }
38737
38877
 
38738
38878
  // src/rpc-protobuf-codecs.ts
38739
38879
  function encodeMessage(schema, init) {
@@ -39324,7 +39464,7 @@ var SidecarSupervisor = class {
39324
39464
  this.logger.info?.(
39325
39465
  `[libravdb] Daemon not ready, retrying connection (attempt ${attempt + 1}/${STARTUP_CONNECT_MAX_RETRIES})...`
39326
39466
  );
39327
- await sleep(delayMs);
39467
+ await sleep2(delayMs);
39328
39468
  }
39329
39469
  }
39330
39470
  }
@@ -39506,7 +39646,7 @@ function isConfiguredEndpoint(value) {
39506
39646
  const port = Number(address.slice(separator + 1));
39507
39647
  return host.length > 0 && Number.isInteger(port) && port > 0 && port <= 65535;
39508
39648
  }
39509
- function sleep(delayMs) {
39649
+ function sleep2(delayMs) {
39510
39650
  return new Promise((resolve) => setTimeout(resolve, delayMs));
39511
39651
  }
39512
39652
 
@@ -39552,7 +39692,7 @@ function createPluginRuntime(cfg, logger = console) {
39552
39692
  timeoutMs: cfg.rpcTimeoutMs ?? DEFAULT_RPC_TIMEOUT_MS
39553
39693
  });
39554
39694
  } catch (error) {
39555
- logger.warn?.(`LibraVDB: failed to initialize gRPC kernel client: ${formatError5(error)}`);
39695
+ logger.warn?.(`LibraVDB: failed to initialize gRPC kernel client: ${formatError(error)}`);
39556
39696
  }
39557
39697
  }
39558
39698
  return { rpc, sidecar, kernel };
@@ -39575,7 +39715,7 @@ function createPluginRuntime(cfg, logger = console) {
39575
39715
  const active = await ensureStarted();
39576
39716
  await active.rpc.call("session_lifecycle_hint", hint);
39577
39717
  } catch (error) {
39578
- logger.warn?.(`LibraVDB lifecycle hint dropped: ${formatError5(error)}`);
39718
+ logger.warn?.(`LibraVDB lifecycle hint dropped: ${formatError(error)}`);
39579
39719
  }
39580
39720
  },
39581
39721
  onShutdown(task) {
@@ -39593,7 +39733,7 @@ function createPluginRuntime(cfg, logger = console) {
39593
39733
  try {
39594
39734
  await task();
39595
39735
  } catch (error) {
39596
- logger.warn?.(`LibraVDB shutdown task failed: ${formatError5(error)}`);
39736
+ logger.warn?.(`LibraVDB shutdown task failed: ${formatError(error)}`);
39597
39737
  }
39598
39738
  }
39599
39739
  stopped = true;
@@ -39625,12 +39765,6 @@ function loadSecretFromEnv() {
39625
39765
  }
39626
39766
  return void 0;
39627
39767
  }
39628
- function formatError5(error) {
39629
- if (error instanceof Error && error.message.trim()) {
39630
- return error.message;
39631
- }
39632
- return String(error);
39633
- }
39634
39768
  function enrichStartupError(error, healthMessage) {
39635
39769
  const rawMessage = error instanceof Error ? error.message : String(error);
39636
39770
  const message = rawMessage.trim() || "LibraVDB daemon startup failed";