@lazyingart/agintiflow 0.20.176 → 0.20.178
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/package.json +1 -1
- package/scripts/smoke-coding-tools.js +23 -0
- package/src/redaction.js +1 -1
- package/src/scs-evidence.js +62 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.178",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -1103,6 +1103,29 @@ try {
|
|
|
1103
1103
|
);
|
|
1104
1104
|
assert(safeEnvReferenceResult.ok, "write_file should allow safe env-var credential references in source code");
|
|
1105
1105
|
|
|
1106
|
+
const safeTokenVariableSyntaxResult = await executeWorkspaceTool(
|
|
1107
|
+
"write_file",
|
|
1108
|
+
{
|
|
1109
|
+
path: "scripts/safe-token-variable-syntax.py",
|
|
1110
|
+
content: [
|
|
1111
|
+
"def validate(tokens):",
|
|
1112
|
+
" for token in tokens:",
|
|
1113
|
+
" if not isinstance(token, dict) or \"t\" not in token:",
|
|
1114
|
+
" raise ValueError(\"token must contain t\")",
|
|
1115
|
+
" text = str(token.get(\"t\", \"\"))",
|
|
1116
|
+
" if token:",
|
|
1117
|
+
" print(text)",
|
|
1118
|
+
"",
|
|
1119
|
+
].join("\n"),
|
|
1120
|
+
mode: "create",
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
commandCwd: workspace,
|
|
1124
|
+
allowFileTools: true,
|
|
1125
|
+
}
|
|
1126
|
+
);
|
|
1127
|
+
assert(safeTokenVariableSyntaxResult.ok, "write_file should allow benign token variable syntax in source code");
|
|
1128
|
+
|
|
1106
1129
|
const redactedContentResult = await executeWorkspaceTool(
|
|
1107
1130
|
"write_file",
|
|
1108
1131
|
{
|
package/src/redaction.js
CHANGED
|
@@ -2,7 +2,7 @@ const SECRET_PATTERNS = [
|
|
|
2
2
|
/\bsk-[A-Za-z0-9_-]{16,}\b/g,
|
|
3
3
|
/\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
|
|
4
4
|
/\bgh[pousr]_[A-Za-z0-9_]{20,}\b/g,
|
|
5
|
-
/((?:api[_-]?key|token|secret|password|passwd|npm_token|_authToken|grsai|venice_api_key)\
|
|
5
|
+
/((?:api[_-]?key|token|secret|password|passwd|npm_token|_authToken|grsai|venice_api_key)[^\S\r\n]*[:=][^\S\r\n]*)[^\s"'`]+/gi,
|
|
6
6
|
/(\/\/registry\.npmjs\.org\/:_authToken=)[^\s"'`]+/gi,
|
|
7
7
|
/(Authorization:\s*Bearer\s+)[^\s"'`]+/gi,
|
|
8
8
|
];
|
package/src/scs-evidence.js
CHANGED
|
@@ -90,16 +90,60 @@ function splitInlineTerms(text = "") {
|
|
|
90
90
|
return String(text || "")
|
|
91
91
|
.split(/[、,,;;]/)
|
|
92
92
|
.map((item) => item.replace(/[。.!!??::]/g, "").trim())
|
|
93
|
-
.filter((item) => item.length >= 2 && item.length <= 40 && !/[\\/]/.test(item));
|
|
93
|
+
.filter((item) => item.length >= 2 && item.length <= 40 && !/[\\/"'“”‘’`]/.test(item));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function trimForbiddenTail(tail = "") {
|
|
97
|
+
let text = String(tail || "").trim();
|
|
98
|
+
if (!text) return "";
|
|
99
|
+
const stopPatterns = [
|
|
100
|
+
/(?:^|[,,、\s])(?:并|且)?(?:末尾|最后|最後|保存|存到|写入|寫入|输出|輸出|完成后|完成後|运行|执行|執行|用命令|检查|檢查|验证|驗證|确认|確認|保留)/,
|
|
101
|
+
/(?:^|[,\s])(?:and\s+)?(?:then|save|write|output|run|execute|check|verify|confirm|after)\b/i,
|
|
102
|
+
];
|
|
103
|
+
const stops = stopPatterns.map((pattern) => text.search(pattern)).filter((index) => index >= 0);
|
|
104
|
+
if (stops.length) text = text.slice(0, Math.min(...stops)).trim();
|
|
105
|
+
return text.replace(/[,,、;;:\s]+$/g, "").trim();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function forbiddenTails(text = "") {
|
|
109
|
+
const tails = [];
|
|
110
|
+
const source = String(text || "");
|
|
111
|
+
const patterns = [
|
|
112
|
+
/(?:不要(?:写|寫)成|不得(?:写|寫)成|禁止(?:写|寫)成)\s*([^,,。;;\n]+)/g,
|
|
113
|
+
/(?:(?:不要|不得|禁止)(?:(?:写|寫)(?!成)|包含|提到)|(?:确认|確認)[^。;;\n]{0,40}?(?:没有|沒有))\s*([^。;;\n]+)/g,
|
|
114
|
+
/\b(?:do not|don't|dont|must not|never)\s+(?:write|include|mention|contain)\s+([^.\n;]+)/gi,
|
|
115
|
+
];
|
|
116
|
+
for (const pattern of patterns) {
|
|
117
|
+
for (const match of source.matchAll(pattern)) {
|
|
118
|
+
const tail = trimForbiddenTail(match[1] || "");
|
|
119
|
+
if (tail) tails.push(tail);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return tails;
|
|
94
123
|
}
|
|
95
124
|
|
|
96
125
|
function inferExactOutputPaths(goal = "") {
|
|
97
126
|
const paths = [];
|
|
98
127
|
const lines = String(goal || "").split(/\n+/);
|
|
99
|
-
const
|
|
128
|
+
const extensionPattern = "md|txt|json|ya?ml|html|css|js|ts|tsx|jsx|py|sh|csv|tex|svg|png|jpe?g|webp|mp4|mov|pdf|docx";
|
|
129
|
+
const quotedPathPattern = new RegExp("[\"'`]([^\"'`\\n]{1,220}\\.(?:" + extensionPattern + "))[\"'`]", "gi");
|
|
130
|
+
const pathPattern = new RegExp(
|
|
131
|
+
'(?:^|[\\s::])((?:~|\\.{1,2}|/|[A-Za-z0-9_\\-\\u4e00-\\u9fff])[\\w./~\\-\\u4e00-\\u9fff]{0,220}\\.(?:' +
|
|
132
|
+
extensionPattern +
|
|
133
|
+
'))(?:$|[\\s"\'`,,。;;.!?!?])',
|
|
134
|
+
"gi"
|
|
135
|
+
);
|
|
100
136
|
for (const line of lines) {
|
|
101
|
-
if (!/\b(save|saved|write|written|output|create|store)\b
|
|
102
|
-
|
|
137
|
+
if (!/\b(save|saved|write|written|output|create|store|update|modify|edit)\b|保存|写入|寫入|输出|輸出|创建|建立|更新|修改|编辑|編輯/i.test(line)) continue;
|
|
138
|
+
quotedPathPattern.lastIndex = 0;
|
|
139
|
+
for (const match of line.matchAll(quotedPathPattern)) {
|
|
140
|
+
const raw = String(match[1] || "").trim();
|
|
141
|
+
if (!raw) continue;
|
|
142
|
+
paths.push(raw);
|
|
143
|
+
}
|
|
144
|
+
const unquotedLine = line.replace(quotedPathPattern, (match) => " ".repeat(match.length));
|
|
145
|
+
pathPattern.lastIndex = 0;
|
|
146
|
+
for (const match of unquotedLine.matchAll(pathPattern)) {
|
|
103
147
|
const raw = String(match[1] || "").trim();
|
|
104
148
|
if (!raw) continue;
|
|
105
149
|
paths.push(raw);
|
|
@@ -108,6 +152,13 @@ function inferExactOutputPaths(goal = "") {
|
|
|
108
152
|
return uniqueLimited(paths, 8);
|
|
109
153
|
}
|
|
110
154
|
|
|
155
|
+
function stripForbiddenTextClauses(text = "") {
|
|
156
|
+
return String(text || "")
|
|
157
|
+
.replace(/(?:不要(?:写|寫)成|不得(?:写|寫)成|禁止(?:写|寫)成)\s*[^,,。;;\n]+/g, "")
|
|
158
|
+
.replace(/(?:(?:不要|不得|禁止)(?:(?:写|寫)(?!成)|包含|提到)|(?:确认|確認)[^。;;\n]{0,40}?(?:没有|沒有))\s*[^。;;\n]+/g, "")
|
|
159
|
+
.replace(/\b(?:do not|don't|dont|must not|never)\s+(?:write|include|mention|contain)\s+[^.\n;]+/gi, "");
|
|
160
|
+
}
|
|
161
|
+
|
|
111
162
|
function inferRequiredTextTerms(goal = "") {
|
|
112
163
|
const terms = [];
|
|
113
164
|
const lines = String(goal || "").split(/\n+/);
|
|
@@ -115,11 +166,12 @@ function inferRequiredTextTerms(goal = "") {
|
|
|
115
166
|
const positiveSegment = String(line || "").split(
|
|
116
167
|
/(?:并)?确认没有|(?:并)?確認沒有|没有|沒有|\b(?:does not contain|do not contain|not contain|not include|without)\b/i
|
|
117
168
|
)[0];
|
|
169
|
+
const requiredSegment = stripForbiddenTextClauses(positiveSegment);
|
|
118
170
|
if (
|
|
119
|
-
/\b(must|require|required|include|contain|contains|check|verify|grep|keyword|keywords)\b/i.test(line) ||
|
|
120
|
-
|
|
171
|
+
/\b(must|require|required|include|contain|contains|check|verify|grep|keyword|keywords|preserve|keep|retain|appear)\b/i.test(line) ||
|
|
172
|
+
/必须|必須|要求|包含|保留|出现|出現|精确字符串|精確字符串|明确出现|明確出現|检查|檢查|验证|驗證|关键词|關鍵詞|自检|自檢/.test(line)
|
|
121
173
|
) {
|
|
122
|
-
terms.push(...quotedTerms(
|
|
174
|
+
terms.push(...quotedTerms(requiredSegment));
|
|
123
175
|
}
|
|
124
176
|
}
|
|
125
177
|
return uniqueLimited(terms, 24);
|
|
@@ -129,16 +181,7 @@ function inferForbiddenTextTerms(goal = "") {
|
|
|
129
181
|
const terms = [];
|
|
130
182
|
const lines = String(goal || "").split(/\n+/);
|
|
131
183
|
for (const line of lines) {
|
|
132
|
-
const
|
|
133
|
-
if (
|
|
134
|
-
/\b(?:do not|don't|dont|must not|never)\s+(?:write|include|mention|contain)\b/i.test(text) ||
|
|
135
|
-
/不要(?:写|寫|包含|提到)|不得(?:写|寫|包含|提到)|禁止(?:写|寫|包含|提到)|(?:确认|確認)(?:没有|沒有)/.test(text)
|
|
136
|
-
) {
|
|
137
|
-
const tail =
|
|
138
|
-
text.match(/(?:不要(?:写|寫|包含|提到)|不得(?:写|寫|包含|提到)|禁止(?:写|寫|包含|提到))(.+)/)?.[1] ||
|
|
139
|
-
text.match(/(?:确认|確認)(?:没有|沒有)(.+)/)?.[1] ||
|
|
140
|
-
text.match(/\b(?:do not|don't|dont|must not|never)\s+(?:write|include|mention|contain)\s+(.+)/i)?.[1] ||
|
|
141
|
-
"";
|
|
184
|
+
for (const tail of forbiddenTails(line)) {
|
|
142
185
|
terms.push(...quotedTerms(tail));
|
|
143
186
|
const unquotedTail = tail.replace(/“[^”]+”|"[^"\n]+"|'[^'\n]+'|`[^`\n]+`/g, "");
|
|
144
187
|
terms.push(...splitInlineTerms(unquotedTail).filter((item) => !/^(and|or|the|a|an|other|其他|上一集道具)$/.test(item)));
|
|
@@ -341,6 +384,8 @@ function resolveContractPath(commandCwd = process.cwd(), rawPath = "") {
|
|
|
341
384
|
const text = String(rawPath || "").trim();
|
|
342
385
|
if (!text) return "";
|
|
343
386
|
if (text.startsWith("~/")) return path.join(process.env.HOME || commandCwd, text.slice(2));
|
|
387
|
+
if (text === "/workspace") return path.resolve(commandCwd || process.cwd());
|
|
388
|
+
if (text.startsWith("/workspace/")) return path.resolve(commandCwd || process.cwd(), text.slice("/workspace/".length));
|
|
344
389
|
if (path.isAbsolute(text)) return text;
|
|
345
390
|
return path.resolve(commandCwd || process.cwd(), text);
|
|
346
391
|
}
|