memory-bank-skill 5.6.2 → 5.7.1
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/cli.js +1 -1
- package/dist/plugin.js +109 -34
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import { fileURLToPath } from "url";
|
|
|
10
10
|
// package.json
|
|
11
11
|
var package_default = {
|
|
12
12
|
name: "memory-bank-skill",
|
|
13
|
-
version: "5.
|
|
13
|
+
version: "5.7.1",
|
|
14
14
|
description: "Memory Bank - \u9879\u76EE\u8BB0\u5FC6\u7CFB\u7EDF\uFF0C\u8BA9 AI \u52A9\u624B\u5728\u6BCF\u6B21\u5BF9\u8BDD\u4E2D\u90FD\u80FD\u5FEB\u901F\u7406\u89E3\u9879\u76EE\u4E0A\u4E0B\u6587",
|
|
15
15
|
type: "module",
|
|
16
16
|
main: "dist/plugin.js",
|
package/dist/plugin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// plugin/memory-bank.ts
|
|
3
|
-
import { stat, readFile } from "fs/promises";
|
|
3
|
+
import { stat, readFile, realpath } from "fs/promises";
|
|
4
4
|
import { execSync } from "child_process";
|
|
5
5
|
import path from "path";
|
|
6
6
|
var DEBUG = process.env.MEMORY_BANK_DEBUG === "1";
|
|
@@ -753,12 +753,44 @@ ${triggers.join(`
|
|
|
753
753
|
},
|
|
754
754
|
"tool.execute.before": async (input, output) => {
|
|
755
755
|
const { tool, sessionID } = input;
|
|
756
|
-
const
|
|
756
|
+
const isCaseInsensitiveFS = process.platform === "darwin" || process.platform === "win32";
|
|
757
|
+
const normalize = (p) => isCaseInsensitiveFS ? p.toLowerCase() : p;
|
|
758
|
+
let realProjectRoot = null;
|
|
759
|
+
let realMemoryBankDir = null;
|
|
760
|
+
const getRealPaths = async () => {
|
|
761
|
+
if (realProjectRoot === null) {
|
|
762
|
+
try {
|
|
763
|
+
realProjectRoot = normalize(await realpath(projectRoot));
|
|
764
|
+
} catch {
|
|
765
|
+
realProjectRoot = normalize(projectRoot);
|
|
766
|
+
}
|
|
767
|
+
try {
|
|
768
|
+
realMemoryBankDir = normalize(await realpath(path.join(projectRoot, "memory-bank")));
|
|
769
|
+
} catch {
|
|
770
|
+
realMemoryBankDir = normalize(path.join(projectRoot, "memory-bank"));
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
return { realProjectRoot, realMemoryBankDir };
|
|
774
|
+
};
|
|
775
|
+
const isMemoryBankPath = async (targetPath) => {
|
|
776
|
+
const { realProjectRoot: rootReal, realMemoryBankDir: mbReal } = await getRealPaths();
|
|
757
777
|
const absPath = path.isAbsolute(targetPath) ? targetPath : path.resolve(projectRoot, targetPath);
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
778
|
+
const lexicalNorm = normalize(absPath);
|
|
779
|
+
const lexicalMBDir = normalize(path.join(projectRoot, "memory-bank"));
|
|
780
|
+
const lexicalMatch = lexicalNorm === lexicalMBDir || lexicalNorm.startsWith(lexicalMBDir + path.sep) || lexicalNorm.startsWith(lexicalMBDir + "/");
|
|
781
|
+
let physicalMatch = false;
|
|
782
|
+
try {
|
|
783
|
+
const resolved = normalize(await realpath(absPath));
|
|
784
|
+
physicalMatch = resolved === mbReal || resolved.startsWith(mbReal + path.sep) || resolved.startsWith(mbReal + "/");
|
|
785
|
+
} catch {
|
|
786
|
+
try {
|
|
787
|
+
const parentResolved = normalize(await realpath(path.dirname(absPath)));
|
|
788
|
+
const targetName = path.basename(absPath);
|
|
789
|
+
const fullResolved = path.join(parentResolved, targetName);
|
|
790
|
+
physicalMatch = fullResolved === mbReal || fullResolved.startsWith(mbReal + path.sep) || fullResolved.startsWith(mbReal + "/");
|
|
791
|
+
} catch {}
|
|
792
|
+
}
|
|
793
|
+
return lexicalMatch || physicalMatch;
|
|
762
794
|
};
|
|
763
795
|
const isWriterAllowed = (sid) => {
|
|
764
796
|
if (writerSessionIDs.has(sid))
|
|
@@ -778,36 +810,79 @@ ${triggers.join(`
|
|
|
778
810
|
` + `\u8BF7\u4F7F\u7528 delegate_task \u8C03\u7528 memory-bank-writer agent \u6765\u66F4\u65B0 Memory Bank\u3002
|
|
779
811
|
` + `\u793A\u4F8B: delegate_task(subagent_type="memory-bank-writer", load_skills=["memory-bank-writer"], prompt="\u66F4\u65B0...")`);
|
|
780
812
|
};
|
|
781
|
-
|
|
782
|
-
const
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
blockWrite("only .md files allowed", { targetPath });
|
|
813
|
+
const extractPaths = (toolName, args) => {
|
|
814
|
+
const paths = [];
|
|
815
|
+
const pathArgs = ["filePath", "path", "filename", "file", "dest", "destination", "target"];
|
|
816
|
+
for (const arg of pathArgs) {
|
|
817
|
+
const val = args[arg];
|
|
818
|
+
if (typeof val === "string" && val.trim())
|
|
819
|
+
paths.push(val);
|
|
789
820
|
}
|
|
790
|
-
if (
|
|
791
|
-
|
|
821
|
+
if (toolName === "multiedit" && Array.isArray(args.edits)) {
|
|
822
|
+
for (const edit of args.edits) {
|
|
823
|
+
if (typeof edit === "object" && edit !== null) {
|
|
824
|
+
const e = edit;
|
|
825
|
+
if (typeof e.path === "string")
|
|
826
|
+
paths.push(e.path);
|
|
827
|
+
if (typeof e.filePath === "string")
|
|
828
|
+
paths.push(e.filePath);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
if (toolName === "apply_patch" || toolName === "patch") {
|
|
833
|
+
const patchText = args.patchText ?? args.patch ?? args.diff;
|
|
834
|
+
if (typeof patchText === "string") {
|
|
835
|
+
const gitDiffPattern = /^(?:\+\+\+|---)\s+[ab]\/(.+)$/gm;
|
|
836
|
+
let match;
|
|
837
|
+
while ((match = gitDiffPattern.exec(patchText)) !== null) {
|
|
838
|
+
if (match[1])
|
|
839
|
+
paths.push(match[1]);
|
|
840
|
+
}
|
|
841
|
+
const openCodePattern = /^\*\*\*\s+(?:Add|Update|Delete|Move to)\s+(?:File:\s*)?(.+)$/gm;
|
|
842
|
+
while ((match = openCodePattern.exec(patchText)) !== null) {
|
|
843
|
+
if (match[1])
|
|
844
|
+
paths.push(match[1].trim());
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return [...new Set(paths)];
|
|
849
|
+
};
|
|
850
|
+
const fileWriteTools = ["write", "edit", "multiedit", "apply_patch", "patch"];
|
|
851
|
+
const toolLower = tool.toLowerCase();
|
|
852
|
+
if (fileWriteTools.includes(toolLower)) {
|
|
853
|
+
const targetPaths = extractPaths(toolLower, output.args || {});
|
|
854
|
+
if (targetPaths.length === 0)
|
|
792
855
|
return;
|
|
856
|
+
for (const targetPath of targetPaths) {
|
|
857
|
+
if (!await isMemoryBankPath(targetPath))
|
|
858
|
+
continue;
|
|
859
|
+
if (!targetPath.toLowerCase().endsWith(".md")) {
|
|
860
|
+
blockWrite("only .md files allowed", { targetPath });
|
|
861
|
+
}
|
|
862
|
+
if (isWriterAllowed(sessionID)) {
|
|
863
|
+
log.debug("Writer agent write allowed", { sessionID, tool, targetPath });
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
blockWrite("not writer agent", {
|
|
867
|
+
targetPath,
|
|
868
|
+
isSubAgent: !!sessionsById.get(sessionID)?.parentID,
|
|
869
|
+
agentName: agentBySessionID.get(sessionID)
|
|
870
|
+
});
|
|
793
871
|
}
|
|
794
|
-
blockWrite("not writer agent", {
|
|
795
|
-
targetPath,
|
|
796
|
-
isSubAgent: !!sessionsById.get(sessionID)?.parentID,
|
|
797
|
-
agentName: agentBySessionID.get(sessionID)
|
|
798
|
-
});
|
|
799
872
|
}
|
|
800
873
|
if (tool.toLowerCase() === "bash") {
|
|
801
874
|
const command = output.args?.command;
|
|
802
875
|
if (!command || typeof command !== "string")
|
|
803
876
|
return;
|
|
804
|
-
|
|
877
|
+
const cmdToCheck = isCaseInsensitiveFS ? command.toLowerCase() : command;
|
|
878
|
+
const mbPattern = isCaseInsensitiveFS ? /(?:^|[^a-z0-9_.-])memory-bank(?:[\/\\]|$|\s|['"])/ : /(?:^|[^A-Za-z0-9_.-])memory-bank(?:[\/\\]|$|\s|['"])/;
|
|
879
|
+
if (!mbPattern.test(cmdToCheck))
|
|
805
880
|
return;
|
|
806
881
|
const hasShellOperators = /[;&|]|\$\(|`/.test(command);
|
|
807
882
|
if (!hasShellOperators) {
|
|
808
883
|
const readOnlyPatterns = [
|
|
809
|
-
/^\s*(ls|cat|head|tail|less|more|grep|rg|ag|find|tree|wc|file|stat)\b
|
|
810
|
-
/^\s*git\s+(status|log|diff|show|blame)\b/
|
|
884
|
+
/^\s*(ls|cat|head|tail|less|more|grep|rg|ag|find|tree|wc|file|stat)\b/i,
|
|
885
|
+
/^\s*git\s+(status|log|diff|show|blame)\b/i
|
|
811
886
|
];
|
|
812
887
|
if (readOnlyPatterns.some((p) => p.test(command)))
|
|
813
888
|
return;
|
|
@@ -817,16 +892,16 @@ ${triggers.join(`
|
|
|
817
892
|
/>>/,
|
|
818
893
|
/<</,
|
|
819
894
|
/\|/,
|
|
820
|
-
/\btee\b
|
|
821
|
-
/\bsed\s+-i
|
|
822
|
-
/\bperl\s+-[ip]
|
|
823
|
-
/\bcp\b
|
|
824
|
-
/\bmv\b
|
|
825
|
-
/\brm\b
|
|
826
|
-
/\bmkdir\b
|
|
827
|
-
/\btouch\b
|
|
828
|
-
/\bgit\s+(add|rm|mv|apply|checkout|restore|reset|clean|stash|commit)\b
|
|
829
|
-
/\bpython\b.*\bopen\b/
|
|
895
|
+
/\btee\b/i,
|
|
896
|
+
/\bsed\s+-i/i,
|
|
897
|
+
/\bperl\s+-[ip]/i,
|
|
898
|
+
/\bcp\b/i,
|
|
899
|
+
/\bmv\b/i,
|
|
900
|
+
/\brm\b/i,
|
|
901
|
+
/\bmkdir\b/i,
|
|
902
|
+
/\btouch\b/i,
|
|
903
|
+
/\bgit\s+(add|rm|mv|apply|checkout|restore|reset|clean|stash|commit)\b/i,
|
|
904
|
+
/\bpython\b.*\bopen\b/i
|
|
830
905
|
];
|
|
831
906
|
const isWriteOperation = writePatterns.some((p) => p.test(command));
|
|
832
907
|
if (!isWriteOperation)
|