@joshuaswarren/openclaw-engram 8.3.58 → 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 +129 -9
- 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
|
|
@@ -9498,6 +9500,13 @@ function nextOptimizerVersion(previousState) {
|
|
|
9498
9500
|
function roundDelta(value) {
|
|
9499
9501
|
return Math.round(value * 1e3) / 1e3;
|
|
9500
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
|
+
}
|
|
9501
9510
|
function computeCompressionGuidelineCandidate(events, options = {}) {
|
|
9502
9511
|
const generatedAt = options.generatedAtIso ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
9503
9512
|
const previousState = options.previousState ?? null;
|
|
@@ -9551,7 +9560,7 @@ function computeCompressionGuidelineCandidate(events, options = {}) {
|
|
|
9551
9560
|
const qualitySignal = qualitySeen > 0 ? (summary.quality.good - summary.quality.poor) / qualitySeen : 0;
|
|
9552
9561
|
const rawDelta = clamp((successRate - failureRate) * 0.12 + qualitySignal * 0.06, -MAX_DELTA, MAX_DELTA);
|
|
9553
9562
|
const delta = roundDelta(rawDelta);
|
|
9554
|
-
const direction = delta
|
|
9563
|
+
const direction = directionForDelta(delta);
|
|
9555
9564
|
if (direction === "decrease" && summary.outcomes.failed > summary.outcomes.applied) {
|
|
9556
9565
|
notes.push("Failures exceed applied outcomes; conservative down-adjustment.");
|
|
9557
9566
|
} else if (direction === "increase" && summary.quality.good > summary.quality.poor) {
|
|
@@ -9561,8 +9570,7 @@ function computeCompressionGuidelineCandidate(events, options = {}) {
|
|
|
9561
9570
|
} else {
|
|
9562
9571
|
notes.push("Outcomes are stable; keep bounded adjustments.");
|
|
9563
9572
|
}
|
|
9564
|
-
const
|
|
9565
|
-
const confidence = magnitude >= 0.09 ? "high" : magnitude >= 0.04 ? "medium" : "low";
|
|
9573
|
+
const confidence = confidenceForDelta(delta);
|
|
9566
9574
|
return {
|
|
9567
9575
|
action: summary.action,
|
|
9568
9576
|
delta,
|
|
@@ -9584,6 +9592,56 @@ function computeCompressionGuidelineCandidate(events, options = {}) {
|
|
|
9584
9592
|
optimizerVersion: nextOptimizerVersion(previousState)
|
|
9585
9593
|
};
|
|
9586
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
|
+
}
|
|
9587
9645
|
function renderCompressionGuidelinesMarkdown(candidate) {
|
|
9588
9646
|
const actionLines = candidate.actionSummaries.length === 0 ? ["- (none)"] : candidate.actionSummaries.map((item) => `- ${item.action}: ${item.total}`);
|
|
9589
9647
|
const outcomeLines = [
|
|
@@ -15115,20 +15173,82 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
|
|
|
15115
15173
|
generatedAtIso: generatedAt,
|
|
15116
15174
|
previousState
|
|
15117
15175
|
});
|
|
15118
|
-
const
|
|
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);
|
|
15119
15207
|
await this.storage.writeCompressionGuidelines(content);
|
|
15120
15208
|
await this.storage.writeCompressionGuidelineOptimizerState({
|
|
15121
|
-
version:
|
|
15122
|
-
updatedAt:
|
|
15123
|
-
sourceWindow:
|
|
15124
|
-
eventCounts:
|
|
15125
|
-
guidelineVersion:
|
|
15209
|
+
version: refinedCandidate.optimizerVersion,
|
|
15210
|
+
updatedAt: refinedCandidate.generatedAt,
|
|
15211
|
+
sourceWindow: refinedCandidate.sourceWindow,
|
|
15212
|
+
eventCounts: refinedCandidate.eventCounts,
|
|
15213
|
+
guidelineVersion: refinedCandidate.guidelineVersion
|
|
15126
15214
|
});
|
|
15127
15215
|
log.info(`compression guideline learning updated (${events.length} events)`);
|
|
15128
15216
|
} catch (err) {
|
|
15129
15217
|
log.warn(`compression guideline learning failed (ignored): ${err}`);
|
|
15130
15218
|
}
|
|
15131
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
|
+
}
|
|
15132
15252
|
async runLifecyclePolicyPass(allMemories) {
|
|
15133
15253
|
const now = /* @__PURE__ */ new Date();
|
|
15134
15254
|
const nowIso = now.toISOString();
|