@joshuaswarren/openclaw-engram 9.0.59 → 9.0.61

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.
@@ -1670,9 +1670,15 @@ var StorageManager = class _StorageManager {
1670
1670
  get compressionGuidelinesPath() {
1671
1671
  return path4.join(this.stateDir, "compression-guidelines.md");
1672
1672
  }
1673
+ get compressionGuidelineDraftPath() {
1674
+ return path4.join(this.stateDir, "compression-guidelines.draft.md");
1675
+ }
1673
1676
  get compressionGuidelineStatePath() {
1674
1677
  return path4.join(this.stateDir, "compression-guideline-state.json");
1675
1678
  }
1679
+ get compressionGuidelineDraftStatePath() {
1680
+ return path4.join(this.stateDir, "compression-guideline-draft-state.json");
1681
+ }
1676
1682
  get behaviorSignalsPath() {
1677
1683
  return path4.join(this.stateDir, "behavior-signals.jsonl");
1678
1684
  }
@@ -1764,7 +1770,7 @@ ${sanitized.text}
1764
1770
  memoryId: id,
1765
1771
  eventType: "created",
1766
1772
  timestamp: fm.created,
1767
- actor: "storage.writeMemory",
1773
+ actor: options.actor ?? "storage.writeMemory",
1768
1774
  after: this.summarizeLifecycleState(fm, filePath),
1769
1775
  relatedMemoryIds: [
1770
1776
  ...options.supersedes ? [options.supersedes] : [],
@@ -1826,11 +1832,12 @@ ${sanitized.text}
1826
1832
 
1827
1833
  ${sanitized.text}
1828
1834
  `, "utf-8");
1835
+ const actor = typeof options.actor === "string" && options.actor.length > 0 ? options.actor : "storage.writeArtifact";
1829
1836
  await this.appendGeneratedMemoryLifecycleEventFailOpen("storage.writeArtifact", {
1830
1837
  memoryId: id,
1831
1838
  eventType: "created",
1832
1839
  timestamp: fm.created,
1833
- actor: "storage.writeArtifact",
1840
+ actor,
1834
1841
  after: this.summarizeLifecycleState(fm, filePath),
1835
1842
  relatedMemoryIds: options.sourceMemoryId ? [options.sourceMemoryId] : []
1836
1843
  });
@@ -2329,7 +2336,7 @@ ${sanitized.text}
2329
2336
  memoryId: id,
2330
2337
  eventType: "updated",
2331
2338
  timestamp: updated.updated,
2332
- actor: "storage.updateMemory",
2339
+ actor: options?.actor ?? "storage.updateMemory",
2333
2340
  before: this.summarizeLifecycleState(memory.frontmatter, memory.path),
2334
2341
  after: this.summarizeLifecycleState(updated, memory.path),
2335
2342
  relatedMemoryIds: [
@@ -2638,18 +2645,81 @@ ${memory.content}
2638
2645
  return null;
2639
2646
  }
2640
2647
  }
2648
+ async writeCompressionGuidelineDraft(content) {
2649
+ await this.ensureDirectories();
2650
+ await writeFile2(this.compressionGuidelineDraftPath, content, "utf-8");
2651
+ }
2652
+ async readCompressionGuidelineDraft() {
2653
+ try {
2654
+ return await readFile2(this.compressionGuidelineDraftPath, "utf-8");
2655
+ } catch {
2656
+ return null;
2657
+ }
2658
+ }
2641
2659
  async writeCompressionGuidelineOptimizerState(state) {
2642
2660
  await this.ensureDirectories();
2643
2661
  await writeFile2(this.compressionGuidelineStatePath, `${JSON.stringify(state, null, 2)}
2662
+ `, "utf-8");
2663
+ }
2664
+ async writeCompressionGuidelineDraftState(state) {
2665
+ await this.ensureDirectories();
2666
+ await writeFile2(this.compressionGuidelineDraftStatePath, `${JSON.stringify(state, null, 2)}
2644
2667
  `, "utf-8");
2645
2668
  }
2646
2669
  async readCompressionGuidelineOptimizerState() {
2670
+ return this.readCompressionGuidelineStateFile(this.compressionGuidelineStatePath);
2671
+ }
2672
+ async readCompressionGuidelineDraftState() {
2673
+ return this.readCompressionGuidelineStateFile(this.compressionGuidelineDraftStatePath);
2674
+ }
2675
+ async activateCompressionGuidelineDraft(options) {
2676
+ const [draftContent, draftState] = await Promise.all([
2677
+ this.readCompressionGuidelineDraft(),
2678
+ this.readCompressionGuidelineDraftState()
2679
+ ]);
2680
+ if (!draftContent || !draftState) return false;
2681
+ if (typeof options?.expectedContentHash === "string" && options.expectedContentHash.length > 0 && draftState.contentHash !== options.expectedContentHash) {
2682
+ return false;
2683
+ }
2684
+ if (typeof options?.expectedGuidelineVersion === "number" && Number.isFinite(options.expectedGuidelineVersion) && draftState.guidelineVersion !== options.expectedGuidelineVersion) {
2685
+ return false;
2686
+ }
2687
+ if (draftState.contentHash) {
2688
+ const contentHash = createHash("sha256").update(draftContent).digest("hex");
2689
+ if (contentHash !== draftState.contentHash) return false;
2690
+ }
2691
+ await this.writeCompressionGuidelines(draftContent);
2692
+ await this.writeCompressionGuidelineOptimizerState({
2693
+ ...draftState,
2694
+ activationState: "active"
2695
+ });
2696
+ await Promise.all([
2697
+ unlink(this.compressionGuidelineDraftPath).catch(() => void 0),
2698
+ unlink(this.compressionGuidelineDraftStatePath).catch(() => void 0)
2699
+ ]);
2700
+ return true;
2701
+ }
2702
+ async readCompressionGuidelineStateFile(filePath) {
2647
2703
  const isFiniteNonNegativeInteger = (value) => typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0;
2704
+ const isValidActionSummary = (value) => {
2705
+ if (!value || typeof value !== "object") return false;
2706
+ const summary = value;
2707
+ return typeof summary.action === "string" && isFiniteNonNegativeInteger(summary.total) && summary.outcomes !== null && typeof summary.outcomes === "object" && isFiniteNonNegativeInteger(summary.outcomes.applied) && isFiniteNonNegativeInteger(summary.outcomes.skipped) && isFiniteNonNegativeInteger(summary.outcomes.failed) && summary.quality !== null && typeof summary.quality === "object" && isFiniteNonNegativeInteger(summary.quality.good) && isFiniteNonNegativeInteger(summary.quality.poor) && isFiniteNonNegativeInteger(summary.quality.unknown);
2708
+ };
2709
+ const isValidRuleUpdate = (value) => {
2710
+ if (!value || typeof value !== "object") return false;
2711
+ const rule = value;
2712
+ return typeof rule.action === "string" && typeof rule.delta === "number" && Number.isFinite(rule.delta) && (rule.direction === "increase" || rule.direction === "decrease" || rule.direction === "hold") && (rule.confidence === "low" || rule.confidence === "medium" || rule.confidence === "high") && Array.isArray(rule.notes) && rule.notes.every((note) => typeof note === "string");
2713
+ };
2648
2714
  try {
2649
- const raw = await readFile2(this.compressionGuidelineStatePath, "utf-8");
2715
+ const raw = await readFile2(filePath, "utf-8");
2650
2716
  const parsed = JSON.parse(raw);
2651
2717
  const sourceWindow = parsed?.sourceWindow;
2652
2718
  const eventCounts = parsed?.eventCounts;
2719
+ const activationState = parsed?.activationState === "draft" || parsed?.activationState === "active" ? parsed.activationState : void 0;
2720
+ const contentHash = typeof parsed?.contentHash === "string" && parsed.contentHash.length > 0 ? parsed.contentHash : void 0;
2721
+ const actionSummaries = Array.isArray(parsed?.actionSummaries) ? parsed.actionSummaries.filter(isValidActionSummary) : void 0;
2722
+ const ruleUpdates = Array.isArray(parsed?.ruleUpdates) ? parsed.ruleUpdates.filter(isValidRuleUpdate) : void 0;
2653
2723
  if (!isFiniteNonNegativeInteger(parsed?.version) || typeof parsed?.updatedAt !== "string" || parsed.updatedAt.length === 0 || !sourceWindow || typeof sourceWindow.from !== "string" || sourceWindow.from.length === 0 || typeof sourceWindow.to !== "string" || sourceWindow.to.length === 0 || !eventCounts || !isFiniteNonNegativeInteger(eventCounts.total) || !isFiniteNonNegativeInteger(eventCounts.applied) || !isFiniteNonNegativeInteger(eventCounts.skipped) || !isFiniteNonNegativeInteger(eventCounts.failed) || !isFiniteNonNegativeInteger(parsed?.guidelineVersion)) {
2654
2724
  return null;
2655
2725
  }
@@ -2666,7 +2736,11 @@ ${memory.content}
2666
2736
  skipped: eventCounts.skipped,
2667
2737
  failed: eventCounts.failed
2668
2738
  },
2669
- guidelineVersion: parsed.guidelineVersion
2739
+ guidelineVersion: parsed.guidelineVersion,
2740
+ ...contentHash ? { contentHash } : {},
2741
+ ...activationState ? { activationState } : {},
2742
+ ...actionSummaries ? { actionSummaries } : {},
2743
+ ...ruleUpdates ? { ruleUpdates } : {}
2670
2744
  };
2671
2745
  } catch {
2672
2746
  return null;
@@ -3629,7 +3703,7 @@ ${memory.content}
3629
3703
  /**
3630
3704
  * Add links to an existing memory.
3631
3705
  */
3632
- async addLinksToMemory(memoryId, links) {
3706
+ async addLinksToMemory(memoryId, links, lifecycle) {
3633
3707
  const memories = await this.readAllMemories();
3634
3708
  const memory = memories.find((m) => m.frontmatter.id === memoryId);
3635
3709
  if (!memory) return false;
@@ -3640,17 +3714,15 @@ ${memory.content}
3640
3714
  mergedLinks.push(link);
3641
3715
  }
3642
3716
  }
3643
- const updatedFm = {
3644
- ...memory.frontmatter,
3645
- links: mergedLinks,
3646
- updated: (/* @__PURE__ */ new Date()).toISOString()
3647
- };
3648
- const fileContent = `${serializeFrontmatter(updatedFm)}
3649
-
3650
- ${memory.content}
3651
- `;
3652
3717
  try {
3653
- await writeFile2(memory.path, fileContent, "utf-8");
3718
+ await this.writeMemoryFrontmatter(
3719
+ memory,
3720
+ {
3721
+ links: mergedLinks,
3722
+ updated: (/* @__PURE__ */ new Date()).toISOString()
3723
+ },
3724
+ lifecycle
3725
+ );
3654
3726
  log.debug(`added ${links.length} links to memory ${memoryId}`);
3655
3727
  return true;
3656
3728
  } catch (err) {
@@ -3723,4 +3795,4 @@ export {
3723
3795
  serializeEntityFile,
3724
3796
  StorageManager
3725
3797
  };
3726
- //# sourceMappingURL=chunk-CWVXHH36.js.map
3798
+ //# sourceMappingURL=chunk-QKD7TZY2.js.map