@joshuaswarren/openclaw-engram 8.3.80 → 8.3.81
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 +212 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9137,6 +9137,7 @@ var LastRecallStore = class {
|
|
|
9137
9137
|
queryHash,
|
|
9138
9138
|
queryLen: opts.query.length,
|
|
9139
9139
|
memoryIds: opts.memoryIds,
|
|
9140
|
+
policyVersion: opts.policyVersion,
|
|
9140
9141
|
identityInjectionMode: opts.identityInjection?.mode,
|
|
9141
9142
|
identityInjectedChars: opts.identityInjection?.injectedChars,
|
|
9142
9143
|
identityInjectionTruncated: opts.identityInjection?.truncated
|
|
@@ -13166,7 +13167,7 @@ function sanitizeRuntimePolicyValues(values, options) {
|
|
|
13166
13167
|
function isRuntimeParameter(parameter) {
|
|
13167
13168
|
return parameter === "recencyWeight" || parameter === "lifecyclePromoteHeatThreshold" || parameter === "lifecycleStaleDecayThreshold" || parameter === "cronRecallInstructionHeavyTokenCap";
|
|
13168
13169
|
}
|
|
13169
|
-
async function
|
|
13170
|
+
async function readRuntimePolicySnapshot(filePath, options) {
|
|
13170
13171
|
try {
|
|
13171
13172
|
const raw = await readFile18(filePath, "utf-8");
|
|
13172
13173
|
const parsed = JSON.parse(raw);
|
|
@@ -13176,7 +13177,9 @@ async function readSnapshot(filePath) {
|
|
|
13176
13177
|
return {
|
|
13177
13178
|
version: parsed.version,
|
|
13178
13179
|
updatedAt: parsed.updatedAt,
|
|
13179
|
-
values: sanitizeRuntimePolicyValues(parsed.values
|
|
13180
|
+
values: sanitizeRuntimePolicyValues(parsed.values, {
|
|
13181
|
+
maxStaleDecayThreshold: options?.maxStaleDecayThreshold
|
|
13182
|
+
}),
|
|
13180
13183
|
sourceAdjustmentCount: parsed.sourceAdjustmentCount
|
|
13181
13184
|
};
|
|
13182
13185
|
} catch {
|
|
@@ -13201,14 +13204,16 @@ var PolicyRuntimeManager = class {
|
|
|
13201
13204
|
runtimePath;
|
|
13202
13205
|
runtimePrevPath;
|
|
13203
13206
|
async loadRuntimeValues() {
|
|
13204
|
-
const snapshot = await
|
|
13205
|
-
if (!snapshot) return null;
|
|
13206
|
-
return sanitizeRuntimePolicyValues(snapshot.values, {
|
|
13207
|
+
const snapshot = await readRuntimePolicySnapshot(this.runtimePath, {
|
|
13207
13208
|
maxStaleDecayThreshold: this.config.lifecycleArchiveDecayThreshold
|
|
13208
13209
|
});
|
|
13210
|
+
if (!snapshot) return null;
|
|
13211
|
+
return snapshot.values;
|
|
13209
13212
|
}
|
|
13210
13213
|
async rollback() {
|
|
13211
|
-
const previous = await
|
|
13214
|
+
const previous = await readRuntimePolicySnapshot(this.runtimePrevPath, {
|
|
13215
|
+
maxStaleDecayThreshold: this.config.lifecycleArchiveDecayThreshold
|
|
13216
|
+
});
|
|
13212
13217
|
if (!previous) return false;
|
|
13213
13218
|
await writeSnapshotAtomic(this.runtimePath, {
|
|
13214
13219
|
...previous,
|
|
@@ -13225,7 +13230,9 @@ var PolicyRuntimeManager = class {
|
|
|
13225
13230
|
...this.config.behaviorLoopProtectedParams,
|
|
13226
13231
|
...state.protectedParams
|
|
13227
13232
|
]);
|
|
13228
|
-
const existing = await
|
|
13233
|
+
const existing = await readRuntimePolicySnapshot(this.runtimePath, {
|
|
13234
|
+
maxStaleDecayThreshold: this.config.lifecycleArchiveDecayThreshold
|
|
13235
|
+
});
|
|
13229
13236
|
const candidate = {
|
|
13230
13237
|
recencyWeight: existing?.values.recencyWeight ?? this.config.recencyWeight,
|
|
13231
13238
|
lifecyclePromoteHeatThreshold: existing?.values.lifecyclePromoteHeatThreshold ?? this.config.lifecyclePromoteHeatThreshold,
|
|
@@ -13755,6 +13762,16 @@ var Orchestrator = class _Orchestrator {
|
|
|
13755
13762
|
effectiveCronRecallInstructionHeavyTokenCap() {
|
|
13756
13763
|
return this.runtimePolicyValues?.cronRecallInstructionHeavyTokenCap ?? this.config.cronRecallInstructionHeavyTokenCap;
|
|
13757
13764
|
}
|
|
13765
|
+
currentPolicyVersion() {
|
|
13766
|
+
const thresholds = this.effectiveLifecycleThresholds();
|
|
13767
|
+
const payload = {
|
|
13768
|
+
recencyWeight: this.effectiveRecencyWeight(),
|
|
13769
|
+
lifecyclePromoteHeatThreshold: thresholds.promoteHeatThreshold,
|
|
13770
|
+
lifecycleStaleDecayThreshold: thresholds.staleDecayThreshold,
|
|
13771
|
+
cronRecallInstructionHeavyTokenCap: this.effectiveCronRecallInstructionHeavyTokenCap()
|
|
13772
|
+
};
|
|
13773
|
+
return createHash6("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 12);
|
|
13774
|
+
}
|
|
13758
13775
|
effectiveLifecycleThresholds() {
|
|
13759
13776
|
const archiveDecayThreshold = this.config.lifecycleArchiveDecayThreshold;
|
|
13760
13777
|
const staleDecayThreshold = Math.min(
|
|
@@ -14559,6 +14576,7 @@ ${r.snippet.trim()}
|
|
|
14559
14576
|
});
|
|
14560
14577
|
const retrievalQuery = queryPolicy.retrievalQuery || prompt;
|
|
14561
14578
|
const retrievalQueryHash = createHash6("sha256").update(retrievalQuery).digest("hex");
|
|
14579
|
+
const policyVersion = this.currentPolicyVersion();
|
|
14562
14580
|
let impressionRecorded = false;
|
|
14563
14581
|
let recallSource = "none";
|
|
14564
14582
|
let recalledMemoryCount = 0;
|
|
@@ -14609,6 +14627,7 @@ ${r.snippet.trim()}
|
|
|
14609
14627
|
recalledMemoryCount,
|
|
14610
14628
|
injected: false,
|
|
14611
14629
|
contextChars: 0,
|
|
14630
|
+
policyVersion,
|
|
14612
14631
|
identityInjectionMode: identityInjectionModeUsed,
|
|
14613
14632
|
identityInjectedChars,
|
|
14614
14633
|
identityInjectionTruncated,
|
|
@@ -15180,6 +15199,7 @@ _Context: ${topQuestion.context}_`);
|
|
|
15180
15199
|
sessionKey,
|
|
15181
15200
|
query: retrievalQuery,
|
|
15182
15201
|
memoryIds: [],
|
|
15202
|
+
policyVersion,
|
|
15183
15203
|
identityInjection: {
|
|
15184
15204
|
mode: identityInjectionModeUsed,
|
|
15185
15205
|
injectedChars: identityInjectedChars,
|
|
@@ -15206,6 +15226,7 @@ _Context: ${topQuestion.context}_`);
|
|
|
15206
15226
|
recalledMemoryCount,
|
|
15207
15227
|
injected: context.length > 0,
|
|
15208
15228
|
contextChars: context.length,
|
|
15229
|
+
policyVersion,
|
|
15209
15230
|
identityInjectionMode: identityInjectionModeUsed,
|
|
15210
15231
|
identityInjectedChars,
|
|
15211
15232
|
identityInjectionTruncated,
|
|
@@ -16956,6 +16977,7 @@ ${lines.join("\n\n")}`;
|
|
|
16956
16977
|
sessionKey: options.sessionKey,
|
|
16957
16978
|
query: options.retrievalQuery,
|
|
16958
16979
|
memoryIds: unique,
|
|
16980
|
+
policyVersion: this.currentPolicyVersion(),
|
|
16959
16981
|
identityInjection: options.identityInjection
|
|
16960
16982
|
}).catch((err) => log.debug(`last recall record failed: ${err}`));
|
|
16961
16983
|
}
|
|
@@ -19810,6 +19832,7 @@ mistakes: ${res.mistakesCount} patterns`
|
|
|
19810
19832
|
// src/cli.ts
|
|
19811
19833
|
import path45 from "path";
|
|
19812
19834
|
import { access as access3, readFile as readFile31, readdir as readdir19, unlink as unlink5 } from "fs/promises";
|
|
19835
|
+
import { createHash as createHash9 } from "crypto";
|
|
19813
19836
|
|
|
19814
19837
|
// src/transfer/export-json.ts
|
|
19815
19838
|
import path31 from "path";
|
|
@@ -22099,6 +22122,171 @@ async function runTierMigrateCliCommand(orchestrator, options = {}) {
|
|
|
22099
22122
|
limit: options.limit
|
|
22100
22123
|
});
|
|
22101
22124
|
}
|
|
22125
|
+
function effectivePolicyValuesForVersion(values, config) {
|
|
22126
|
+
const candidate = {
|
|
22127
|
+
recencyWeight: values.recencyWeight ?? config.recencyWeight,
|
|
22128
|
+
lifecyclePromoteHeatThreshold: values.lifecyclePromoteHeatThreshold ?? config.lifecyclePromoteHeatThreshold,
|
|
22129
|
+
lifecycleStaleDecayThreshold: values.lifecycleStaleDecayThreshold ?? config.lifecycleStaleDecayThreshold,
|
|
22130
|
+
cronRecallInstructionHeavyTokenCap: values.cronRecallInstructionHeavyTokenCap ?? config.cronRecallInstructionHeavyTokenCap
|
|
22131
|
+
};
|
|
22132
|
+
const normalized = sanitizeRuntimePolicyValues(candidate, {
|
|
22133
|
+
maxStaleDecayThreshold: config.lifecycleArchiveDecayThreshold
|
|
22134
|
+
});
|
|
22135
|
+
return {
|
|
22136
|
+
recencyWeight: normalized.recencyWeight ?? config.recencyWeight,
|
|
22137
|
+
lifecyclePromoteHeatThreshold: normalized.lifecyclePromoteHeatThreshold ?? config.lifecyclePromoteHeatThreshold,
|
|
22138
|
+
lifecycleStaleDecayThreshold: normalized.lifecycleStaleDecayThreshold ?? config.lifecycleStaleDecayThreshold,
|
|
22139
|
+
cronRecallInstructionHeavyTokenCap: normalized.cronRecallInstructionHeavyTokenCap ?? config.cronRecallInstructionHeavyTokenCap
|
|
22140
|
+
};
|
|
22141
|
+
}
|
|
22142
|
+
function policyVersionForValues(values, config) {
|
|
22143
|
+
const normalized = effectivePolicyValuesForVersion(values, config);
|
|
22144
|
+
return createHash9("sha256").update(JSON.stringify(normalized)).digest("hex").slice(0, 12);
|
|
22145
|
+
}
|
|
22146
|
+
async function readRuntimePolicySnapshot2(config, fileName) {
|
|
22147
|
+
const filePath = path45.join(config.memoryDir, "state", fileName);
|
|
22148
|
+
const snapshot = await readRuntimePolicySnapshot(filePath, {
|
|
22149
|
+
maxStaleDecayThreshold: config.lifecycleArchiveDecayThreshold
|
|
22150
|
+
});
|
|
22151
|
+
if (!snapshot) return null;
|
|
22152
|
+
return {
|
|
22153
|
+
version: snapshot.version,
|
|
22154
|
+
updatedAt: snapshot.updatedAt,
|
|
22155
|
+
values: snapshot.values,
|
|
22156
|
+
sourceAdjustmentCount: Math.max(0, Math.floor(snapshot.sourceAdjustmentCount))
|
|
22157
|
+
};
|
|
22158
|
+
}
|
|
22159
|
+
function parseSinceDurationMs(since) {
|
|
22160
|
+
const trimmed = since.trim().toLowerCase();
|
|
22161
|
+
const match = trimmed.match(/^(\d+)\s*([mhd])$/);
|
|
22162
|
+
if (!match) {
|
|
22163
|
+
throw new Error(`invalid --since value: ${since} (expected formats like 30m, 12h, 7d)`);
|
|
22164
|
+
}
|
|
22165
|
+
const amount = Number.parseInt(match[1] ?? "0", 10);
|
|
22166
|
+
const unit = match[2];
|
|
22167
|
+
if (!Number.isFinite(amount) || amount <= 0) {
|
|
22168
|
+
throw new Error(`invalid --since value: ${since}`);
|
|
22169
|
+
}
|
|
22170
|
+
if (unit === "m") return amount * 60 * 1e3;
|
|
22171
|
+
if (unit === "h") return amount * 60 * 60 * 1e3;
|
|
22172
|
+
return amount * 24 * 60 * 60 * 1e3;
|
|
22173
|
+
}
|
|
22174
|
+
function resolvePolicySignalNamespaces(orchestrator) {
|
|
22175
|
+
const names = /* @__PURE__ */ new Set([orchestrator.config.defaultNamespace]);
|
|
22176
|
+
if (orchestrator.config.namespacesEnabled) {
|
|
22177
|
+
names.add(orchestrator.config.sharedNamespace);
|
|
22178
|
+
for (const policy of orchestrator.config.namespacePolicies) {
|
|
22179
|
+
if (policy?.name) names.add(policy.name);
|
|
22180
|
+
}
|
|
22181
|
+
}
|
|
22182
|
+
return [...names];
|
|
22183
|
+
}
|
|
22184
|
+
async function readBehaviorSignalsForNamespaces(orchestrator, limitPerNamespace) {
|
|
22185
|
+
const namespaces = resolvePolicySignalNamespaces(orchestrator);
|
|
22186
|
+
const merged = [];
|
|
22187
|
+
for (const namespace of namespaces) {
|
|
22188
|
+
const storage = await orchestrator.getStorage(namespace);
|
|
22189
|
+
const events = await storage.readBehaviorSignals(limitPerNamespace);
|
|
22190
|
+
merged.push(...events);
|
|
22191
|
+
}
|
|
22192
|
+
return merged;
|
|
22193
|
+
}
|
|
22194
|
+
function summarizeTopSignals(signals, cutoffIso, topN = 5) {
|
|
22195
|
+
const cutoffMs = cutoffIso ? Date.parse(cutoffIso) : Number.NEGATIVE_INFINITY;
|
|
22196
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
22197
|
+
for (const signal of signals) {
|
|
22198
|
+
const ts = Date.parse(signal.timestamp);
|
|
22199
|
+
if (Number.isFinite(cutoffMs) && (!Number.isFinite(ts) || ts < cutoffMs)) continue;
|
|
22200
|
+
const key = `${signal.signalType}:${signal.direction}`;
|
|
22201
|
+
const existing = grouped.get(key);
|
|
22202
|
+
if (existing) {
|
|
22203
|
+
existing.count += 1;
|
|
22204
|
+
if (signal.timestamp > existing.lastSeenAt) {
|
|
22205
|
+
existing.lastSeenAt = signal.timestamp;
|
|
22206
|
+
}
|
|
22207
|
+
} else {
|
|
22208
|
+
grouped.set(key, {
|
|
22209
|
+
signalType: signal.signalType,
|
|
22210
|
+
direction: signal.direction,
|
|
22211
|
+
count: 1,
|
|
22212
|
+
lastSeenAt: signal.timestamp
|
|
22213
|
+
});
|
|
22214
|
+
}
|
|
22215
|
+
}
|
|
22216
|
+
return [...grouped.values()].sort((a, b) => b.count - a.count || b.lastSeenAt.localeCompare(a.lastSeenAt)).slice(0, Math.max(1, topN));
|
|
22217
|
+
}
|
|
22218
|
+
async function runPolicyStatusCliCommand(orchestrator) {
|
|
22219
|
+
const now = /* @__PURE__ */ new Date();
|
|
22220
|
+
const current = await readRuntimePolicySnapshot2(orchestrator.config, "policy-runtime.json");
|
|
22221
|
+
const previous = await readRuntimePolicySnapshot2(orchestrator.config, "policy-runtime.prev.json");
|
|
22222
|
+
const signals = await readBehaviorSignalsForNamespaces(orchestrator, 1e3);
|
|
22223
|
+
const defaultWindowMs = Math.max(0, orchestrator.config.behaviorLoopLearningWindowDays) * 24 * 60 * 60 * 1e3;
|
|
22224
|
+
const cutoffIso = defaultWindowMs > 0 ? new Date(now.getTime() - defaultWindowMs).toISOString() : void 0;
|
|
22225
|
+
return {
|
|
22226
|
+
generatedAt: now.toISOString(),
|
|
22227
|
+
autoTuneEnabled: orchestrator.config.behaviorLoopAutoTuneEnabled,
|
|
22228
|
+
current: current ? {
|
|
22229
|
+
...current,
|
|
22230
|
+
policyVersion: policyVersionForValues(current.values, orchestrator.config)
|
|
22231
|
+
} : null,
|
|
22232
|
+
previous: previous ? {
|
|
22233
|
+
...previous,
|
|
22234
|
+
policyVersion: policyVersionForValues(previous.values, orchestrator.config)
|
|
22235
|
+
} : null,
|
|
22236
|
+
topContributingSignals: summarizeTopSignals(signals, cutoffIso)
|
|
22237
|
+
};
|
|
22238
|
+
}
|
|
22239
|
+
async function runPolicyDiffCliCommand(orchestrator, options = {}) {
|
|
22240
|
+
const since = options.since?.trim() || "7d";
|
|
22241
|
+
const sinceMs = parseSinceDurationMs(since);
|
|
22242
|
+
const sinceIso = new Date(Date.now() - sinceMs).toISOString();
|
|
22243
|
+
const current = await readRuntimePolicySnapshot2(orchestrator.config, "policy-runtime.json");
|
|
22244
|
+
const previous = await readRuntimePolicySnapshot2(orchestrator.config, "policy-runtime.prev.json");
|
|
22245
|
+
const currentValues = current?.values ?? {};
|
|
22246
|
+
const previousValues = previous?.values ?? {};
|
|
22247
|
+
const parameterKeys = /* @__PURE__ */ new Set([
|
|
22248
|
+
...Object.keys(currentValues),
|
|
22249
|
+
...Object.keys(previousValues)
|
|
22250
|
+
]);
|
|
22251
|
+
const deltas = [];
|
|
22252
|
+
for (const parameter of parameterKeys) {
|
|
22253
|
+
const previousRaw = previousValues[parameter];
|
|
22254
|
+
const nextRaw = currentValues[parameter];
|
|
22255
|
+
const previousValue = typeof previousRaw === "number" ? previousRaw : null;
|
|
22256
|
+
const nextValue = typeof nextRaw === "number" ? nextRaw : null;
|
|
22257
|
+
if (previousValue === nextValue) continue;
|
|
22258
|
+
deltas.push({
|
|
22259
|
+
parameter,
|
|
22260
|
+
previousValue,
|
|
22261
|
+
nextValue,
|
|
22262
|
+
delta: (nextValue ?? 0) - (previousValue ?? 0),
|
|
22263
|
+
evidenceCount: current?.sourceAdjustmentCount ?? 0
|
|
22264
|
+
});
|
|
22265
|
+
}
|
|
22266
|
+
deltas.sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta) || a.parameter.localeCompare(b.parameter));
|
|
22267
|
+
const signals = await readBehaviorSignalsForNamespaces(orchestrator, 1e3);
|
|
22268
|
+
return {
|
|
22269
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22270
|
+
since,
|
|
22271
|
+
sinceIso,
|
|
22272
|
+
currentPolicyVersion: current ? policyVersionForValues(current.values, orchestrator.config) : null,
|
|
22273
|
+
previousPolicyVersion: previous ? policyVersionForValues(previous.values, orchestrator.config) : null,
|
|
22274
|
+
deltas,
|
|
22275
|
+
topContributingSignals: summarizeTopSignals(signals, sinceIso)
|
|
22276
|
+
};
|
|
22277
|
+
}
|
|
22278
|
+
async function runPolicyRollbackCliCommand(orchestrator) {
|
|
22279
|
+
const rolledBack = await orchestrator.rollbackBehaviorRuntimePolicy();
|
|
22280
|
+
const current = await readRuntimePolicySnapshot2(orchestrator.config, "policy-runtime.json");
|
|
22281
|
+
return {
|
|
22282
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22283
|
+
rolledBack,
|
|
22284
|
+
current: current ? {
|
|
22285
|
+
...current,
|
|
22286
|
+
policyVersion: policyVersionForValues(current.values, orchestrator.config)
|
|
22287
|
+
} : null
|
|
22288
|
+
};
|
|
22289
|
+
}
|
|
22102
22290
|
function incrementCounter(target, key) {
|
|
22103
22291
|
const normalized = key && key.length > 0 ? key : "unknown";
|
|
22104
22292
|
target[normalized] = (target[normalized] ?? 0) + 1;
|
|
@@ -22818,6 +23006,23 @@ function registerCli(api, orchestrator) {
|
|
|
22818
23006
|
console.log(JSON.stringify(summary, null, 2));
|
|
22819
23007
|
console.log("OK");
|
|
22820
23008
|
});
|
|
23009
|
+
cmd.command("policy-status").description("Show runtime behavior-loop policy status and top contributing signals").action(async () => {
|
|
23010
|
+
const status = await runPolicyStatusCliCommand(orchestrator);
|
|
23011
|
+
console.log(JSON.stringify(status, null, 2));
|
|
23012
|
+
console.log("OK");
|
|
23013
|
+
});
|
|
23014
|
+
cmd.command("policy-diff").description("Show runtime policy deltas and evidence since a relative duration (default: 7d)").option("--since <window>", "Relative duration window like 30m, 12h, 7d", "7d").action(async (...args) => {
|
|
23015
|
+
const options = args[0] ?? {};
|
|
23016
|
+
const since = typeof options.since === "string" ? options.since : "7d";
|
|
23017
|
+
const report = await runPolicyDiffCliCommand(orchestrator, { since });
|
|
23018
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23019
|
+
console.log("OK");
|
|
23020
|
+
});
|
|
23021
|
+
cmd.command("policy-rollback").description("Roll back runtime behavior policy to the previous snapshot").action(async () => {
|
|
23022
|
+
const report = await runPolicyRollbackCliCommand(orchestrator);
|
|
23023
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23024
|
+
console.log("OK");
|
|
23025
|
+
});
|
|
22821
23026
|
cmd.command("action-audit").description("Show namespace-aware memory action policy outcomes").option("--namespace <name>", "Filter to a single namespace").option("--limit <n>", "Max events to read per namespace", "200").action(async (...args) => {
|
|
22822
23027
|
const options = args[0] ?? {};
|
|
22823
23028
|
const limitRaw = parseInt(String(options.limit ?? "200"), 10);
|