mindkeeper-openclaw 0.2.28 → 0.2.30

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 context-vault contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.js CHANGED
@@ -678,11 +678,13 @@ function generateTemplateMessage(changedFiles, options) {
678
678
  }
679
679
 
680
680
  // ../core/src/message/llm.ts
681
- async function generateLlmMessage(diffs, provider) {
681
+ async function generateLlmMessage(diffs, provider, log) {
682
682
  if (!provider) return null;
683
683
  try {
684
684
  return await provider.generateCommitMessage(diffs);
685
- } catch {
685
+ } catch (err) {
686
+ const msg = err instanceof Error ? err.message : String(err);
687
+ log?.warn?.(`[mindkeeper] LLM commit message error: ${msg}`);
686
688
  return null;
687
689
  }
688
690
  }
@@ -698,6 +700,7 @@ var Tracker = class {
698
700
  workDir;
699
701
  gitDir;
700
702
  configOverrides;
703
+ log;
701
704
  constructor(options) {
702
705
  this.workDir = import_node_path3.default.resolve(options.workDir);
703
706
  this.gitDir = options.gitDir ? import_node_path3.default.resolve(options.gitDir) : import_node_path3.default.join(this.workDir, GITDIR_NAME);
@@ -705,6 +708,7 @@ var Tracker = class {
705
708
  this.configLoaded = options.config !== void 0;
706
709
  this.configOverrides = options.configOverrides;
707
710
  this.llmProvider = options.llmProvider;
711
+ this.log = options.log;
708
712
  this.store = new IsomorphicGitStore({
709
713
  workDir: this.workDir,
710
714
  gitDir: this.gitDir
@@ -756,8 +760,8 @@ var Tracker = class {
756
760
  }
757
761
  async diff(options) {
758
762
  const to = options.to ?? "HEAD";
759
- const fromOid = options.from === "HEAD" ? await this.resolveHead() : options.from;
760
- const toOid = to === "HEAD" ? await this.resolveHead() : to;
763
+ const fromOid = await this.resolveOid(options.from);
764
+ const toOid = await this.resolveOid(to);
761
765
  if (!fromOid || !toOid) {
762
766
  throw new Error("Could not resolve commit references");
763
767
  }
@@ -772,7 +776,11 @@ var Tracker = class {
772
776
  });
773
777
  }
774
778
  async rollback(options) {
775
- await this.store.restoreFile(options.file, options.to);
779
+ const toOid = await this.resolveOid(options.to);
780
+ if (!toOid) {
781
+ throw new Error(`Could not resolve commit: ${options.to}`);
782
+ }
783
+ await this.store.restoreFile(options.file, toOid);
776
784
  await this.store.addFiles([options.file]);
777
785
  const shortHash = options.to.slice(0, 8);
778
786
  const message = generateTemplateMessage([options.file], {
@@ -810,20 +818,47 @@ var Tracker = class {
810
818
  const filesToCommit = changed.map((e) => e.filepath);
811
819
  await this.store.addFiles(filesToCommit);
812
820
  const diffs = [];
813
- for (const file of filesToCommit) {
814
- try {
815
- const d = await this.diff({ file, from: "HEAD" });
816
- if (d.additions > 0 || d.deletions > 0) {
817
- diffs.push(d);
821
+ let headOid = null;
822
+ try {
823
+ headOid = await this.resolveHead();
824
+ } catch {
825
+ }
826
+ if (headOid) {
827
+ for (const file of filesToCommit) {
828
+ try {
829
+ const oldContent = await this.store.readFile(file, headOid) ?? "";
830
+ let newContent;
831
+ try {
832
+ newContent = await import_promises3.default.readFile(
833
+ import_node_path3.default.join(this.workDir, file),
834
+ "utf-8"
835
+ );
836
+ } catch {
837
+ newContent = "";
838
+ }
839
+ const d = computeDiff({
840
+ file,
841
+ fromVersion: headOid.slice(0, 8),
842
+ toVersion: "(staged)",
843
+ oldContent,
844
+ newContent
845
+ });
846
+ if (d.additions > 0 || d.deletions > 0) {
847
+ diffs.push(d);
848
+ }
849
+ } catch {
818
850
  }
819
- } catch {
820
851
  }
821
852
  }
822
853
  let message = null;
823
854
  if (this.config.commitMessage.mode === "llm" && diffs.length > 0) {
824
- message = await generateLlmMessage(diffs, this.llmProvider);
855
+ message = await generateLlmMessage(diffs, this.llmProvider, this.log);
825
856
  }
826
857
  if (!message) {
858
+ if (this.config.commitMessage.mode === "llm" && this.log?.warn) {
859
+ const reason = diffs.length === 0 ? "No diff available (first commit or no file changes), using template" : "LLM failed, falling back to template";
860
+ this.log.warn(`[mindkeeper] ${reason}`);
861
+ }
827
862
  message = generateTemplateMessage(filesToCommit);
828
863
  }
829
864
  const oid = await this.store.commit(message);
@@ -890,6 +925,27 @@ var Tracker = class {
890
925
  ref: "HEAD"
891
926
  });
892
927
  }
928
+ /**
929
+ * Resolves a ref (HEAD, short hash, or full oid) to a full commit oid.
930
+ * Uses expandOid for short hashes since isomorphic-git readBlob may not support them.
931
+ */
932
+ async resolveOid(ref) {
933
+ if (ref === "HEAD") {
934
+ return this.resolveHead();
935
+ }
936
+ const git2 = await import("isomorphic-git");
937
+ const fs2 = await import("node:fs");
938
+ try {
939
+ return await git2.default.expandOid({
940
+ fs: fs2.default,
941
+ dir: this.workDir,
942
+ gitdir: this.gitDir,
943
+ oid: ref
944
+ });
945
+ } catch {
946
+ return null;
947
+ }
948
+ }
893
949
  async ensureGitignore() {
894
950
  const gitignorePath = import_node_path3.default.join(this.workDir, ".gitignore");
895
951
  const entry = ".mindkeeper/";
@@ -1246,7 +1302,8 @@ function createWatcherService(api, trackerRef) {
1246
1302
  const tracker = new Tracker({
1247
1303
  workDir: workspaceDir,
1248
1304
  llmProvider: llmProvider ?? void 0,
1249
- configOverrides: api.pluginConfig
1305
+ configOverrides: api.pluginConfig,
1306
+ log
1250
1307
  });
1251
1308
  await tracker.init();
1252
1309
  trackerRef.current = tracker;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindkeeper-openclaw",
3
- "version": "0.2.28",
3
+ "version": "0.2.30",
4
4
  "description": "OpenClaw plugin for mindkeeper: auto-snapshot, diff, and rollback for agent context files",
5
5
  "keywords": [
6
6
  "openclaw",
@@ -29,14 +29,6 @@
29
29
  "scripts/postinstall-merge-config.cjs",
30
30
  "README.md"
31
31
  ],
32
- "scripts": {
33
- "build": "node build.mjs",
34
- "test": "vitest run",
35
- "typecheck": "tsc --noEmit",
36
- "clean": "rm -rf dist",
37
- "prepublishOnly": "npm run clean && npm run build",
38
- "postinstall": "node scripts/postinstall-merge-config.cjs"
39
- },
40
32
  "openclaw": {
41
33
  "extensions": [
42
34
  "./dist/index.js"
@@ -59,5 +51,12 @@
59
51
  },
60
52
  "publishConfig": {
61
53
  "access": "public"
54
+ },
55
+ "scripts": {
56
+ "build": "node build.mjs",
57
+ "test": "vitest run",
58
+ "typecheck": "tsc --noEmit",
59
+ "clean": "rm -rf dist",
60
+ "postinstall": "node scripts/postinstall-merge-config.cjs"
62
61
  }
63
- }
62
+ }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: mindkeeper
3
3
  description: Time Machine for Your AI's Brain — version control for agent context files. Use when the user asks about changes in SOUL.md, AGENTS.md, MEMORY.md, or other agent context files; when they want to undo, rollback, or compare versions; or when they need a checkpoint before risky edits.
4
- version: 1.2.6
4
+ version: 1.2.7
5
5
  homepage: https://github.com/seekcontext/mindkeeper
6
6
  repository: https://github.com/seekcontext/mindkeeper
7
7
  ---
@@ -102,6 +102,7 @@ mind_history({ file: "SOUL.md", limit: 20 })
102
102
  ### mind_diff
103
103
  Compares two versions of a file. `from` and `to` are short or full commit hashes from `mind_history`.
104
104
  - Omit `to` to compare `from` against the current version (HEAD).
105
+ - **To see what changed in the latest commit**: use `from: entries[1].oid` (the parent) and `to: entries[0].oid` or omit `to` for HEAD. Do NOT use `from: entries[0].oid` with `to: HEAD` — that compares the same commit to itself and yields an empty diff.
105
106
 
106
107
  ```
107
108
  mind_diff({ file: "SOUL.md", from: "a1b2c3d4" })