@joshuaswarren/openclaw-engram 8.3.57 → 8.3.59
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 +279 -54
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +20 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -377,6 +377,8 @@ function parseConfig(raw) {
|
|
|
377
377
|
proactiveExtractionEnabled: cfg.proactiveExtractionEnabled === true,
|
|
378
378
|
contextCompressionActionsEnabled: cfg.contextCompressionActionsEnabled === true,
|
|
379
379
|
compressionGuidelineLearningEnabled: cfg.compressionGuidelineLearningEnabled === true,
|
|
380
|
+
compressionGuidelineSemanticRefinementEnabled: cfg.compressionGuidelineSemanticRefinementEnabled === true,
|
|
381
|
+
compressionGuidelineSemanticTimeoutMs: typeof cfg.compressionGuidelineSemanticTimeoutMs === "number" ? Math.max(1, Math.floor(cfg.compressionGuidelineSemanticTimeoutMs)) : 2500,
|
|
380
382
|
maxProactiveQuestionsPerExtraction: typeof cfg.maxProactiveQuestionsPerExtraction === "number" ? Math.max(0, Math.floor(cfg.maxProactiveQuestionsPerExtraction)) : 2,
|
|
381
383
|
maxCompressionTokensPerHour: typeof cfg.maxCompressionTokensPerHour === "number" ? Math.max(0, Math.floor(cfg.maxCompressionTokensPerHour)) : 1500,
|
|
382
384
|
// v8.0 phase 1
|
|
@@ -9470,6 +9472,207 @@ function buildRecallQueryPolicy(prompt, sessionKey, cfg) {
|
|
|
9470
9472
|
};
|
|
9471
9473
|
}
|
|
9472
9474
|
|
|
9475
|
+
// src/compression-optimizer.ts
|
|
9476
|
+
var MAX_DELTA = 0.15;
|
|
9477
|
+
var SPARSE_SAMPLE = 5;
|
|
9478
|
+
function clamp(value, min, max) {
|
|
9479
|
+
return Math.min(max, Math.max(min, value));
|
|
9480
|
+
}
|
|
9481
|
+
function parseRecallQuality(reason) {
|
|
9482
|
+
if (!reason) return "unknown";
|
|
9483
|
+
const text = reason.toLowerCase();
|
|
9484
|
+
if (/(recall[_\s-]?good|quality[:=]\s*(good|high)|improv(ed|e)|resolved)/i.test(text)) {
|
|
9485
|
+
return "good";
|
|
9486
|
+
}
|
|
9487
|
+
if (/(recall[_\s-]?poor|quality[:=]\s*(poor|low)|degrad(ed|e)|miss(ed|ing)|irrelevant)/i.test(text)) {
|
|
9488
|
+
return "poor";
|
|
9489
|
+
}
|
|
9490
|
+
return "unknown";
|
|
9491
|
+
}
|
|
9492
|
+
function nextGuidelineVersion(previousState) {
|
|
9493
|
+
if (!previousState) return 1;
|
|
9494
|
+
return Math.max(1, previousState.guidelineVersion + 1);
|
|
9495
|
+
}
|
|
9496
|
+
function nextOptimizerVersion(previousState) {
|
|
9497
|
+
if (!previousState) return 1;
|
|
9498
|
+
return Math.max(1, previousState.version + 1);
|
|
9499
|
+
}
|
|
9500
|
+
function roundDelta(value) {
|
|
9501
|
+
return Math.round(value * 1e3) / 1e3;
|
|
9502
|
+
}
|
|
9503
|
+
function confidenceForDelta(delta) {
|
|
9504
|
+
const magnitude = Math.abs(delta);
|
|
9505
|
+
return magnitude >= 0.09 ? "high" : magnitude >= 0.04 ? "medium" : "low";
|
|
9506
|
+
}
|
|
9507
|
+
function directionForDelta(delta) {
|
|
9508
|
+
return delta > 0 ? "increase" : delta < 0 ? "decrease" : "hold";
|
|
9509
|
+
}
|
|
9510
|
+
function computeCompressionGuidelineCandidate(events, options = {}) {
|
|
9511
|
+
const generatedAt = options.generatedAtIso ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
9512
|
+
const previousState = options.previousState ?? null;
|
|
9513
|
+
const totalCounts = {
|
|
9514
|
+
total: events.length,
|
|
9515
|
+
applied: 0,
|
|
9516
|
+
skipped: 0,
|
|
9517
|
+
failed: 0
|
|
9518
|
+
};
|
|
9519
|
+
const actionMap = /* @__PURE__ */ new Map();
|
|
9520
|
+
let windowFrom = events[0]?.timestamp ?? generatedAt;
|
|
9521
|
+
let windowTo = events[0]?.timestamp ?? generatedAt;
|
|
9522
|
+
for (const event of events) {
|
|
9523
|
+
if (event.timestamp < windowFrom) windowFrom = event.timestamp;
|
|
9524
|
+
if (event.timestamp > windowTo) windowTo = event.timestamp;
|
|
9525
|
+
totalCounts[event.outcome] += 1;
|
|
9526
|
+
let summary = actionMap.get(event.action);
|
|
9527
|
+
if (!summary) {
|
|
9528
|
+
summary = {
|
|
9529
|
+
action: event.action,
|
|
9530
|
+
total: 0,
|
|
9531
|
+
outcomes: { applied: 0, skipped: 0, failed: 0 },
|
|
9532
|
+
quality: { good: 0, poor: 0, unknown: 0 }
|
|
9533
|
+
};
|
|
9534
|
+
actionMap.set(event.action, summary);
|
|
9535
|
+
}
|
|
9536
|
+
summary.total += 1;
|
|
9537
|
+
summary.outcomes[event.outcome] += 1;
|
|
9538
|
+
const quality = parseRecallQuality(event.reason);
|
|
9539
|
+
summary.quality[quality] += 1;
|
|
9540
|
+
}
|
|
9541
|
+
const actionSummaries = [...actionMap.values()].sort((a, b) => {
|
|
9542
|
+
if (b.total !== a.total) return b.total - a.total;
|
|
9543
|
+
return a.action.localeCompare(b.action);
|
|
9544
|
+
});
|
|
9545
|
+
const ruleUpdates = actionSummaries.map((summary) => {
|
|
9546
|
+
const notes = [];
|
|
9547
|
+
if (summary.total < SPARSE_SAMPLE) {
|
|
9548
|
+
notes.push("Sparse sample size; holding baseline policy.");
|
|
9549
|
+
return {
|
|
9550
|
+
action: summary.action,
|
|
9551
|
+
delta: 0,
|
|
9552
|
+
direction: "hold",
|
|
9553
|
+
confidence: "low",
|
|
9554
|
+
notes
|
|
9555
|
+
};
|
|
9556
|
+
}
|
|
9557
|
+
const successRate = summary.outcomes.applied / summary.total;
|
|
9558
|
+
const failureRate = summary.outcomes.failed / summary.total;
|
|
9559
|
+
const qualitySeen = summary.quality.good + summary.quality.poor;
|
|
9560
|
+
const qualitySignal = qualitySeen > 0 ? (summary.quality.good - summary.quality.poor) / qualitySeen : 0;
|
|
9561
|
+
const rawDelta = clamp((successRate - failureRate) * 0.12 + qualitySignal * 0.06, -MAX_DELTA, MAX_DELTA);
|
|
9562
|
+
const delta = roundDelta(rawDelta);
|
|
9563
|
+
const direction = directionForDelta(delta);
|
|
9564
|
+
if (direction === "decrease" && summary.outcomes.failed > summary.outcomes.applied) {
|
|
9565
|
+
notes.push("Failures exceed applied outcomes; conservative down-adjustment.");
|
|
9566
|
+
} else if (direction === "increase" && summary.quality.good > summary.quality.poor) {
|
|
9567
|
+
notes.push("Good recall quality markers support this action.");
|
|
9568
|
+
} else if (direction === "decrease" && summary.quality.poor > summary.quality.good) {
|
|
9569
|
+
notes.push("Poor recall quality markers exceed good markers.");
|
|
9570
|
+
} else {
|
|
9571
|
+
notes.push("Outcomes are stable; keep bounded adjustments.");
|
|
9572
|
+
}
|
|
9573
|
+
const confidence = confidenceForDelta(delta);
|
|
9574
|
+
return {
|
|
9575
|
+
action: summary.action,
|
|
9576
|
+
delta,
|
|
9577
|
+
direction,
|
|
9578
|
+
confidence,
|
|
9579
|
+
notes
|
|
9580
|
+
};
|
|
9581
|
+
});
|
|
9582
|
+
return {
|
|
9583
|
+
generatedAt,
|
|
9584
|
+
sourceWindow: {
|
|
9585
|
+
from: events.length > 0 ? windowFrom : generatedAt,
|
|
9586
|
+
to: events.length > 0 ? windowTo : generatedAt
|
|
9587
|
+
},
|
|
9588
|
+
eventCounts: totalCounts,
|
|
9589
|
+
actionSummaries,
|
|
9590
|
+
ruleUpdates,
|
|
9591
|
+
guidelineVersion: nextGuidelineVersion(previousState),
|
|
9592
|
+
optimizerVersion: nextOptimizerVersion(previousState)
|
|
9593
|
+
};
|
|
9594
|
+
}
|
|
9595
|
+
async function refineCompressionGuidelineCandidateSemantically(baseline, options) {
|
|
9596
|
+
if (!options.enabled) return baseline;
|
|
9597
|
+
if (typeof options.runRefinement !== "function") return baseline;
|
|
9598
|
+
const timeoutMs = Math.max(1, Math.floor(options.timeoutMs));
|
|
9599
|
+
let timeoutId = null;
|
|
9600
|
+
const timeout = new Promise((resolve) => {
|
|
9601
|
+
timeoutId = setTimeout(() => resolve(null), timeoutMs);
|
|
9602
|
+
});
|
|
9603
|
+
const refinementPromise = options.runRefinement(baseline).catch(() => null);
|
|
9604
|
+
let refinement = null;
|
|
9605
|
+
try {
|
|
9606
|
+
refinement = await Promise.race([refinementPromise, timeout]);
|
|
9607
|
+
} catch {
|
|
9608
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
9609
|
+
return baseline;
|
|
9610
|
+
}
|
|
9611
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
9612
|
+
if (!refinement || !Array.isArray(refinement.updates) || refinement.updates.length === 0) {
|
|
9613
|
+
return baseline;
|
|
9614
|
+
}
|
|
9615
|
+
const updatesByAction = /* @__PURE__ */ new Map();
|
|
9616
|
+
for (const update of refinement.updates) {
|
|
9617
|
+
if (!update || typeof update.action !== "string") continue;
|
|
9618
|
+
updatesByAction.set(update.action, update);
|
|
9619
|
+
}
|
|
9620
|
+
let changed = false;
|
|
9621
|
+
const ruleUpdates = baseline.ruleUpdates.map((rule) => {
|
|
9622
|
+
const patch = updatesByAction.get(rule.action);
|
|
9623
|
+
if (!patch) return rule;
|
|
9624
|
+
const nextDelta = typeof patch.delta === "number" && Number.isFinite(patch.delta) ? roundDelta(clamp(patch.delta, -MAX_DELTA, MAX_DELTA)) : rule.delta;
|
|
9625
|
+
const nextConfidence = patch.confidence ?? confidenceForDelta(nextDelta);
|
|
9626
|
+
const nextDirection = directionForDelta(nextDelta);
|
|
9627
|
+
const nextNotes = typeof patch.note === "string" && patch.note.trim().length > 0 ? [patch.note.trim()] : rule.notes;
|
|
9628
|
+
if (nextDelta !== rule.delta || nextDirection !== rule.direction || nextConfidence !== rule.confidence || nextNotes.join("\n") !== rule.notes.join("\n")) {
|
|
9629
|
+
changed = true;
|
|
9630
|
+
}
|
|
9631
|
+
return {
|
|
9632
|
+
...rule,
|
|
9633
|
+
delta: nextDelta,
|
|
9634
|
+
direction: nextDirection,
|
|
9635
|
+
confidence: nextConfidence,
|
|
9636
|
+
notes: nextNotes
|
|
9637
|
+
};
|
|
9638
|
+
});
|
|
9639
|
+
if (!changed) return baseline;
|
|
9640
|
+
return {
|
|
9641
|
+
...baseline,
|
|
9642
|
+
ruleUpdates
|
|
9643
|
+
};
|
|
9644
|
+
}
|
|
9645
|
+
function renderCompressionGuidelinesMarkdown(candidate) {
|
|
9646
|
+
const actionLines = candidate.actionSummaries.length === 0 ? ["- (none)"] : candidate.actionSummaries.map((item) => `- ${item.action}: ${item.total}`);
|
|
9647
|
+
const outcomeLines = [
|
|
9648
|
+
`- applied: ${candidate.eventCounts.applied}`,
|
|
9649
|
+
`- skipped: ${candidate.eventCounts.skipped}`,
|
|
9650
|
+
`- failed: ${candidate.eventCounts.failed}`
|
|
9651
|
+
];
|
|
9652
|
+
const updateLines = candidate.ruleUpdates.length === 0 ? ["- No telemetry events available yet. Keep defaults conservative and gather action data first."] : candidate.ruleUpdates.map((update) => {
|
|
9653
|
+
const sign = update.delta > 0 ? "+" : "";
|
|
9654
|
+
return `- ${update.action}: ${update.direction} (${sign}${update.delta.toFixed(3)}, confidence=${update.confidence}) \u2014 ${update.notes.join(" ")}`;
|
|
9655
|
+
});
|
|
9656
|
+
return [
|
|
9657
|
+
"# Compression Guidelines",
|
|
9658
|
+
"",
|
|
9659
|
+
`Generated: ${candidate.generatedAt}`,
|
|
9660
|
+
`Source events analyzed: ${candidate.eventCounts.total}`,
|
|
9661
|
+
`Source window: ${candidate.sourceWindow.from} -> ${candidate.sourceWindow.to}`,
|
|
9662
|
+
`Guideline version: ${candidate.guidelineVersion}`,
|
|
9663
|
+
"",
|
|
9664
|
+
"## Action Distribution",
|
|
9665
|
+
...actionLines,
|
|
9666
|
+
"",
|
|
9667
|
+
"## Outcome Distribution",
|
|
9668
|
+
...outcomeLines,
|
|
9669
|
+
"",
|
|
9670
|
+
"## Suggested Guidelines",
|
|
9671
|
+
...updateLines,
|
|
9672
|
+
""
|
|
9673
|
+
].join("\n");
|
|
9674
|
+
}
|
|
9675
|
+
|
|
9473
9676
|
// src/boxes.ts
|
|
9474
9677
|
import { mkdir as mkdir11, writeFile as writeFile11, readFile as readFile12, readdir as readdir6 } from "fs/promises";
|
|
9475
9678
|
import path14 from "path";
|
|
@@ -12211,59 +12414,6 @@ function deriveTopicsFromExtraction(result) {
|
|
|
12211
12414
|
}
|
|
12212
12415
|
return [...topics].slice(0, 16);
|
|
12213
12416
|
}
|
|
12214
|
-
function buildCompressionGuidelinesMarkdown(events, generatedAtIso = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
12215
|
-
const byAction = /* @__PURE__ */ new Map();
|
|
12216
|
-
const byOutcome = /* @__PURE__ */ new Map();
|
|
12217
|
-
for (const event of events) {
|
|
12218
|
-
byAction.set(event.action, (byAction.get(event.action) ?? 0) + 1);
|
|
12219
|
-
byOutcome.set(event.outcome, (byOutcome.get(event.outcome) ?? 0) + 1);
|
|
12220
|
-
}
|
|
12221
|
-
const actionLines = byAction.size === 0 ? ["- (none)"] : [...byAction.entries()].sort((a, b) => b[1] - a[1]).map(([action, count]) => `- ${action}: ${count}`);
|
|
12222
|
-
const outcomeLines = byOutcome.size === 0 ? ["- (none)"] : [...byOutcome.entries()].sort((a, b) => b[1] - a[1]).map(([outcome, count]) => `- ${outcome}: ${count}`);
|
|
12223
|
-
const failed = byOutcome.get("failed") ?? 0;
|
|
12224
|
-
const skipped = byOutcome.get("skipped") ?? 0;
|
|
12225
|
-
const applied = byOutcome.get("applied") ?? 0;
|
|
12226
|
-
const topAction = [...byAction.entries()].sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
12227
|
-
const suggested = [];
|
|
12228
|
-
if (events.length === 0) {
|
|
12229
|
-
suggested.push(
|
|
12230
|
-
"- No telemetry events available yet. Keep defaults conservative and gather action data first."
|
|
12231
|
-
);
|
|
12232
|
-
} else {
|
|
12233
|
-
if (typeof topAction === "string") {
|
|
12234
|
-
suggested.push(`- Prefer \`${topAction}\` when handling similar future compression decisions.`);
|
|
12235
|
-
}
|
|
12236
|
-
if (failed > 0) {
|
|
12237
|
-
suggested.push(
|
|
12238
|
-
"- Failure events detected. Favor smaller, reversible compression steps and keep fail-open behavior."
|
|
12239
|
-
);
|
|
12240
|
-
}
|
|
12241
|
-
if (skipped > applied) {
|
|
12242
|
-
suggested.push(
|
|
12243
|
-
"- Skipped actions outnumber applied actions. Revisit gating/thresholds before tightening policies."
|
|
12244
|
-
);
|
|
12245
|
-
}
|
|
12246
|
-
if (failed === 0 && skipped <= applied) {
|
|
12247
|
-
suggested.push("- Current action outcomes are stable. Keep policy conservative and continue monitoring.");
|
|
12248
|
-
}
|
|
12249
|
-
}
|
|
12250
|
-
return [
|
|
12251
|
-
"# Compression Guidelines",
|
|
12252
|
-
"",
|
|
12253
|
-
`Generated: ${generatedAtIso}`,
|
|
12254
|
-
`Source events analyzed: ${events.length}`,
|
|
12255
|
-
"",
|
|
12256
|
-
"## Action Distribution",
|
|
12257
|
-
...actionLines,
|
|
12258
|
-
"",
|
|
12259
|
-
"## Outcome Distribution",
|
|
12260
|
-
...outcomeLines,
|
|
12261
|
-
"",
|
|
12262
|
-
"## Suggested Guidelines",
|
|
12263
|
-
...suggested,
|
|
12264
|
-
""
|
|
12265
|
-
].join("\n");
|
|
12266
|
-
}
|
|
12267
12417
|
function filterRecallCandidates(candidates, options) {
|
|
12268
12418
|
const scopedByNamespace = options.namespacesEnabled ? candidates.filter((r) => options.recallNamespaces.includes(options.resolveNamespace(r.path))) : candidates;
|
|
12269
12419
|
return scopedByNamespace.filter((r) => !isArtifactMemoryPath(r.path)).slice(0, Math.max(0, options.limit));
|
|
@@ -15016,14 +15166,89 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
|
|
|
15016
15166
|
async runCompressionGuidelineLearningPass() {
|
|
15017
15167
|
if (!this.config.compressionGuidelineLearningEnabled) return;
|
|
15018
15168
|
try {
|
|
15169
|
+
const previousState = await this.storage.readCompressionGuidelineOptimizerState();
|
|
15019
15170
|
const events = await this.storage.readMemoryActionEvents(500);
|
|
15020
|
-
const
|
|
15171
|
+
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
15172
|
+
const candidate = computeCompressionGuidelineCandidate(events, {
|
|
15173
|
+
generatedAtIso: generatedAt,
|
|
15174
|
+
previousState
|
|
15175
|
+
});
|
|
15176
|
+
const refinedCandidate = await refineCompressionGuidelineCandidateSemantically(candidate, {
|
|
15177
|
+
enabled: this.config.compressionGuidelineSemanticRefinementEnabled,
|
|
15178
|
+
timeoutMs: this.config.compressionGuidelineSemanticTimeoutMs,
|
|
15179
|
+
runRefinement: async (baseline) => {
|
|
15180
|
+
const prompt = [
|
|
15181
|
+
"You refine compression policy suggestions conservatively.",
|
|
15182
|
+
"Return JSON only in this shape:",
|
|
15183
|
+
'{"updates":[{"action":"summarize_node","delta":0.02,"confidence":"medium","note":"..."}]}',
|
|
15184
|
+
"Constraints:",
|
|
15185
|
+
"- Keep updates sparse and conservative.",
|
|
15186
|
+
"- delta must stay between -0.15 and 0.15.",
|
|
15187
|
+
"- Only include actions present in the input.",
|
|
15188
|
+
"Input candidate:",
|
|
15189
|
+
JSON.stringify(baseline)
|
|
15190
|
+
].join("\n");
|
|
15191
|
+
const response = await this.localLlm.chatCompletion(
|
|
15192
|
+
[
|
|
15193
|
+
{ role: "system", content: "Respond with strict JSON only. No markdown." },
|
|
15194
|
+
{ role: "user", content: prompt }
|
|
15195
|
+
],
|
|
15196
|
+
{
|
|
15197
|
+
temperature: 0.1,
|
|
15198
|
+
maxTokens: 400,
|
|
15199
|
+
timeoutMs: this.config.compressionGuidelineSemanticTimeoutMs,
|
|
15200
|
+
operation: "compression_guideline_semantic_refinement"
|
|
15201
|
+
}
|
|
15202
|
+
);
|
|
15203
|
+
return this.parseCompressionSemanticRefinement(response?.content ?? "");
|
|
15204
|
+
}
|
|
15205
|
+
});
|
|
15206
|
+
const content = renderCompressionGuidelinesMarkdown(refinedCandidate);
|
|
15021
15207
|
await this.storage.writeCompressionGuidelines(content);
|
|
15208
|
+
await this.storage.writeCompressionGuidelineOptimizerState({
|
|
15209
|
+
version: refinedCandidate.optimizerVersion,
|
|
15210
|
+
updatedAt: refinedCandidate.generatedAt,
|
|
15211
|
+
sourceWindow: refinedCandidate.sourceWindow,
|
|
15212
|
+
eventCounts: refinedCandidate.eventCounts,
|
|
15213
|
+
guidelineVersion: refinedCandidate.guidelineVersion
|
|
15214
|
+
});
|
|
15022
15215
|
log.info(`compression guideline learning updated (${events.length} events)`);
|
|
15023
15216
|
} catch (err) {
|
|
15024
15217
|
log.warn(`compression guideline learning failed (ignored): ${err}`);
|
|
15025
15218
|
}
|
|
15026
15219
|
}
|
|
15220
|
+
parseCompressionSemanticRefinement(raw) {
|
|
15221
|
+
if (typeof raw !== "string" || raw.trim().length === 0) return null;
|
|
15222
|
+
const trimmed = raw.trim();
|
|
15223
|
+
const start = trimmed.indexOf("{");
|
|
15224
|
+
const end = trimmed.lastIndexOf("}");
|
|
15225
|
+
if (start === -1 || end === -1 || end <= start) return null;
|
|
15226
|
+
try {
|
|
15227
|
+
const parsed = JSON.parse(trimmed.slice(start, end + 1));
|
|
15228
|
+
if (!Array.isArray(parsed?.updates)) return null;
|
|
15229
|
+
const validActions = /* @__PURE__ */ new Set([
|
|
15230
|
+
"store_episode",
|
|
15231
|
+
"store_note",
|
|
15232
|
+
"update_note",
|
|
15233
|
+
"create_artifact",
|
|
15234
|
+
"summarize_node",
|
|
15235
|
+
"discard",
|
|
15236
|
+
"link_graph"
|
|
15237
|
+
]);
|
|
15238
|
+
const updates = parsed.updates.filter((item) => item && typeof item.action === "string" && validActions.has(item.action)).map((item) => {
|
|
15239
|
+
const confidence = item.confidence === "low" || item.confidence === "medium" || item.confidence === "high" ? item.confidence : void 0;
|
|
15240
|
+
return {
|
|
15241
|
+
action: item.action,
|
|
15242
|
+
delta: typeof item.delta === "number" && Number.isFinite(item.delta) ? item.delta : void 0,
|
|
15243
|
+
confidence,
|
|
15244
|
+
note: typeof item.note === "string" ? item.note : void 0
|
|
15245
|
+
};
|
|
15246
|
+
});
|
|
15247
|
+
return { updates };
|
|
15248
|
+
} catch {
|
|
15249
|
+
return null;
|
|
15250
|
+
}
|
|
15251
|
+
}
|
|
15027
15252
|
async runLifecyclePolicyPass(allMemories) {
|
|
15028
15253
|
const now = /* @__PURE__ */ new Date();
|
|
15029
15254
|
const nowIso = now.toISOString();
|