@joshuaswarren/openclaw-engram 7.2.3 → 7.2.4
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 +60 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3921,8 +3921,8 @@ ${stderr}`.trim();
|
|
|
3921
3921
|
}
|
|
3922
3922
|
}
|
|
3923
3923
|
async ensureCollection(memoryDir) {
|
|
3924
|
-
if (this.available === false && !this.daemonAvailable) return
|
|
3925
|
-
if (this.available === false) return
|
|
3924
|
+
if (this.available === false && !this.daemonAvailable) return "unknown";
|
|
3925
|
+
if (this.available === false) return "skipped";
|
|
3926
3926
|
try {
|
|
3927
3927
|
const { stdout } = await runQmd(
|
|
3928
3928
|
["collection", "list"],
|
|
@@ -3934,14 +3934,18 @@ ${stderr}`.trim();
|
|
|
3934
3934
|
"m"
|
|
3935
3935
|
);
|
|
3936
3936
|
if (collectionRegex.test(stdout)) {
|
|
3937
|
-
return
|
|
3937
|
+
return "present";
|
|
3938
3938
|
}
|
|
3939
|
-
} catch {
|
|
3939
|
+
} catch (err) {
|
|
3940
|
+
log.debug(
|
|
3941
|
+
`QMD collection check unavailable for "${this.collection}" (will not disable features): ${err instanceof Error ? err.message : String(err)}`
|
|
3942
|
+
);
|
|
3943
|
+
return "unknown";
|
|
3940
3944
|
}
|
|
3941
3945
|
log.info(
|
|
3942
3946
|
`QMD collection "${this.collection}" not found. Add it to ~/.config/qmd/index.yml pointing at ${memoryDir}`
|
|
3943
3947
|
);
|
|
3944
|
-
return
|
|
3948
|
+
return "missing";
|
|
3945
3949
|
}
|
|
3946
3950
|
};
|
|
3947
3951
|
|
|
@@ -8220,6 +8224,9 @@ var Orchestrator = class _Orchestrator {
|
|
|
8220
8224
|
lastQmdEmbedAtMs = 0;
|
|
8221
8225
|
conversationIndexLastUpdateAtMs = /* @__PURE__ */ new Map();
|
|
8222
8226
|
lastFileHygieneRunAtMs = 0;
|
|
8227
|
+
lastRecallFailureLogAtMs = 0;
|
|
8228
|
+
lastRecallFailureAtMs = 0;
|
|
8229
|
+
suppressedRecallFailures = 0;
|
|
8223
8230
|
// Initialization gate: recall() awaits this before proceeding
|
|
8224
8231
|
initPromise = null;
|
|
8225
8232
|
resolveInit = null;
|
|
@@ -8309,7 +8316,17 @@ var Orchestrator = class _Orchestrator {
|
|
|
8309
8316
|
if (available) {
|
|
8310
8317
|
const mode = this.qmd.isDaemonMode() ? "daemon" : "subprocess";
|
|
8311
8318
|
log.info(`QMD: available (mode: ${mode}) ${this.qmd.debugStatus()}`);
|
|
8312
|
-
await this.qmd.ensureCollection(this.config.memoryDir);
|
|
8319
|
+
const collectionState = await this.qmd.ensureCollection(this.config.memoryDir);
|
|
8320
|
+
if (collectionState === "missing") {
|
|
8321
|
+
this.config.qmdEnabled = false;
|
|
8322
|
+
log.warn(
|
|
8323
|
+
"QMD collection missing for Engram memory store; disabling QMD retrieval for this runtime (fallback retrieval remains enabled)"
|
|
8324
|
+
);
|
|
8325
|
+
} else if (collectionState === "unknown") {
|
|
8326
|
+
log.warn("QMD collection check unavailable; keeping QMD retrieval enabled for fail-open behavior");
|
|
8327
|
+
} else if (collectionState === "skipped") {
|
|
8328
|
+
log.debug("QMD collection check skipped in daemon-only mode");
|
|
8329
|
+
}
|
|
8313
8330
|
} else {
|
|
8314
8331
|
log.warn(`QMD: not available ${this.qmd.debugStatus()}`);
|
|
8315
8332
|
}
|
|
@@ -8318,9 +8335,21 @@ var Orchestrator = class _Orchestrator {
|
|
|
8318
8335
|
const available = await this.conversationQmd.probe();
|
|
8319
8336
|
if (available) {
|
|
8320
8337
|
log.info(`Conversation index QMD: available ${this.conversationQmd.debugStatus()}`);
|
|
8321
|
-
await this.conversationQmd.ensureCollection(
|
|
8338
|
+
const collectionState = await this.conversationQmd.ensureCollection(
|
|
8322
8339
|
path18.join(this.config.memoryDir, "conversation-index")
|
|
8323
8340
|
);
|
|
8341
|
+
if (collectionState === "missing") {
|
|
8342
|
+
this.config.conversationIndexEnabled = false;
|
|
8343
|
+
log.warn(
|
|
8344
|
+
"Conversation index collection missing; disabling conversation semantic recall for this runtime"
|
|
8345
|
+
);
|
|
8346
|
+
} else if (collectionState === "unknown") {
|
|
8347
|
+
log.warn(
|
|
8348
|
+
"Conversation index collection check unavailable; keeping conversation semantic recall enabled for fail-open behavior"
|
|
8349
|
+
);
|
|
8350
|
+
} else if (collectionState === "skipped") {
|
|
8351
|
+
log.debug("Conversation index collection check skipped in daemon-only mode");
|
|
8352
|
+
}
|
|
8324
8353
|
} else {
|
|
8325
8354
|
log.warn(`Conversation index QMD: not available ${this.conversationQmd.debugStatus()}`);
|
|
8326
8355
|
}
|
|
@@ -8443,9 +8472,10 @@ var Orchestrator = class _Orchestrator {
|
|
|
8443
8472
|
this.config.conversationIndexRetentionDays
|
|
8444
8473
|
);
|
|
8445
8474
|
const q = this.conversationQmd ?? this.qmd;
|
|
8475
|
+
const usingPrimaryQmdClient = q === this.qmd;
|
|
8446
8476
|
const shouldEmbed = opts?.embed ?? this.config.conversationIndexEmbedOnUpdate;
|
|
8447
8477
|
let embedded = false;
|
|
8448
|
-
if (this.config.qmdEnabled && q.isAvailable()) {
|
|
8478
|
+
if ((!usingPrimaryQmdClient || this.config.qmdEnabled) && q.isAvailable()) {
|
|
8449
8479
|
await q.update();
|
|
8450
8480
|
if (shouldEmbed) {
|
|
8451
8481
|
await q.embed();
|
|
@@ -8504,17 +8534,36 @@ var Orchestrator = class _Orchestrator {
|
|
|
8504
8534
|
log.warn("recall: init gate timed out \u2014 proceeding without full init");
|
|
8505
8535
|
}
|
|
8506
8536
|
}
|
|
8507
|
-
const RECALL_TIMEOUT_MS =
|
|
8537
|
+
const RECALL_TIMEOUT_MS = 75e3;
|
|
8508
8538
|
return Promise.race([
|
|
8509
8539
|
this.recallInternal(prompt, sessionKey),
|
|
8510
8540
|
new Promise(
|
|
8511
8541
|
(_, reject) => setTimeout(() => reject(new Error("recall timeout")), RECALL_TIMEOUT_MS)
|
|
8512
8542
|
)
|
|
8513
8543
|
]).catch((err) => {
|
|
8514
|
-
|
|
8544
|
+
this.logRecallFailure(err);
|
|
8515
8545
|
return "";
|
|
8516
8546
|
});
|
|
8517
8547
|
}
|
|
8548
|
+
logRecallFailure(err) {
|
|
8549
|
+
const now = Date.now();
|
|
8550
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
8551
|
+
const LOG_WINDOW_MS = 6e4;
|
|
8552
|
+
const idleSinceLastFailureMs = now - this.lastRecallFailureAtMs;
|
|
8553
|
+
this.lastRecallFailureAtMs = now;
|
|
8554
|
+
if (idleSinceLastFailureMs >= LOG_WINDOW_MS) {
|
|
8555
|
+
this.suppressedRecallFailures = 0;
|
|
8556
|
+
}
|
|
8557
|
+
if (now - this.lastRecallFailureLogAtMs >= LOG_WINDOW_MS) {
|
|
8558
|
+
const suffix = this.suppressedRecallFailures > 0 ? ` (suppressed ${this.suppressedRecallFailures} similar failures in last minute)` : "";
|
|
8559
|
+
log.warn(`recall timed out or failed: ${errorMsg}${suffix}`);
|
|
8560
|
+
this.lastRecallFailureLogAtMs = now;
|
|
8561
|
+
this.suppressedRecallFailures = 0;
|
|
8562
|
+
return;
|
|
8563
|
+
}
|
|
8564
|
+
this.suppressedRecallFailures += 1;
|
|
8565
|
+
log.debug(`recall timed out or failed (suppressed): ${errorMsg}`);
|
|
8566
|
+
}
|
|
8518
8567
|
async recallInternal(prompt, sessionKey) {
|
|
8519
8568
|
const recallStart = Date.now();
|
|
8520
8569
|
const timings = {};
|
|
@@ -8791,7 +8840,7 @@ ${formatted}`);
|
|
|
8791
8840
|
}
|
|
8792
8841
|
timings.summaries = `${Date.now() - summariesT0}ms`;
|
|
8793
8842
|
const convT0 = Date.now();
|
|
8794
|
-
if (this.config.conversationIndexEnabled && this.
|
|
8843
|
+
if (this.config.conversationIndexEnabled && this.conversationQmd && this.conversationQmd.isAvailable()) {
|
|
8795
8844
|
const startedAtMs = Date.now();
|
|
8796
8845
|
const timeoutMs = Math.max(200, this.config.conversationRecallTimeoutMs);
|
|
8797
8846
|
const topK = Math.max(1, this.config.conversationRecallTopK);
|