@lazyingart/agintiflow 0.20.76 → 0.20.78
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.78",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Low-cost, project-aware Web and CLI agents with DeepSeek/Venice/OpenAI routing, visible tool calls, durable sessions, scouts, AAPS, SCS, and guarded local execution.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -263,6 +263,18 @@ try {
|
|
|
263
263
|
assert(clonePolicy.allowed, "git clone should be allowed in docker-workspace allow mode");
|
|
264
264
|
assert(clonePolicy.needsNetwork, "git clone was not classified as network");
|
|
265
265
|
assert(clonePolicy.writesWorkspace, "git clone was not classified as workspace-writing");
|
|
266
|
+
const quotedDangerSearchPolicy = evaluateCommandPolicy(
|
|
267
|
+
'grep -nE "rm -rf|git reset --hard|git clean -fd|find . -delete" reports/destructive-command-policy.md',
|
|
268
|
+
dockerWorkspacePolicy
|
|
269
|
+
);
|
|
270
|
+
assert(quotedDangerSearchPolicy.allowed, "read-only grep for destructive command strings should be allowed");
|
|
271
|
+
assert(
|
|
272
|
+
quotedDangerSearchPolicy.category !== "destructive",
|
|
273
|
+
"quoted destructive strings in grep pattern should not classify as a destructive command"
|
|
274
|
+
);
|
|
275
|
+
const actualDangerAfterQuotePolicy = evaluateCommandPolicy('echo "rm -rf is text" && rm -rf reports', dockerWorkspacePolicy);
|
|
276
|
+
assert(!actualDangerAfterQuotePolicy.allowed, "actual destructive command after quoted text should still be blocked");
|
|
277
|
+
assert(actualDangerAfterQuotePolicy.category === "destructive", "actual destructive command after quoted text was not classified as destructive");
|
|
266
278
|
const unsafeCloneTarget = evaluateCommandPolicy("git clone https://github.com/lazyingart/AgInTiFlow.git ../AgInTiFlow", dockerWorkspacePolicy);
|
|
267
279
|
assert(!unsafeCloneTarget.allowed, "git clone outside the workspace should be blocked");
|
|
268
280
|
const blockedClonePolicy = evaluateCommandPolicy("git clone https://github.com/lazyingart/AgInTiFlow.git", {
|
|
@@ -293,6 +305,10 @@ try {
|
|
|
293
305
|
destructiveAdvice.destructiveApprovalCommand,
|
|
294
306
|
].join("\n");
|
|
295
307
|
assert(/dry-run|inspect-only/i.test(destructiveAdviceText), "destructive advice did not lead with dry-run or inspect-only alternatives");
|
|
308
|
+
assert(
|
|
309
|
+
/Do not include executable delete\/reset\/clean commands/.test(destructiveAdviceText),
|
|
310
|
+
"destructive advice did not prohibit destructive commands inside safe cleanup instructions"
|
|
311
|
+
);
|
|
296
312
|
assert(
|
|
297
313
|
!destructiveAdvice.suggestedCommand.includes("--allow-destructive"),
|
|
298
314
|
"default destructive advice suggested command should not enable destructive mode"
|
package/src/behavior-contract.js
CHANGED
|
@@ -70,6 +70,7 @@ export function formatBehaviorContractForPrompt({ mode = "runtime" } = {}) {
|
|
|
70
70
|
"Define or infer concrete success criteria for non-trivial work, then run focused checks or state why checks are unavailable.",
|
|
71
71
|
"Respect the permission contract: if a tool is blocked or returns permissionAdvice, stop and present the exact suggestedCommand/approval path instead of retrying variants or inventing CLI flags.",
|
|
72
72
|
"When destructive cleanup is blocked, lead with inspect-only or dry-run evidence (`git status`, `git clean -nd`, targeted file lists). Do not call delete/reset/clean commands safe unless they are clearly labeled as requiring explicit user approval.",
|
|
73
|
+
"Reports after destructive blocks must not place executable destructive commands (`rm -rf`, `git reset --hard`, `git clean -fd`, `find ... -delete`, broad `git checkout -- .`) inside safe or non-destructive cleanup sections. Omit exact destructive commands or put them only in a separate explicit-approval section.",
|
|
73
74
|
"Protect secrets aggressively: never repeat token/key/password/secret values from prompts, files, tool output, plans, final answers, reports, diffs, or artifacts. Redact the value as [REDACTED] and use dedicated key storage such as `aginti keys set` when credentials are needed.",
|
|
74
75
|
"Keep artifacts durable and discoverable with descriptive non-conflicting names; never overwrite unless the user clearly asked.",
|
|
75
76
|
"When reporting shell, language, runtime, build, or test results, name the actual environment used (host vs Docker, relevant interpreter/tool path/version when it matters). Do not claim compatibility across untested runtimes, hosts, containers, or language versions; state the caveat or run an explicit check.",
|
package/src/command-policy.js
CHANGED
|
@@ -11,6 +11,7 @@ const READ_ONLY_PATTERNS = [
|
|
|
11
11
|
/^ls(?:\s+[-\w./~*]+)*$/,
|
|
12
12
|
/^find(?:\s+[./~\w-]+)*(?:\s+-maxdepth\s+\d+)?(?:\s+-type\s+[fd])?$/,
|
|
13
13
|
/^rg(?:\s+.+)?$/,
|
|
14
|
+
/^grep(?:\s+.+)?$/,
|
|
14
15
|
/^cat(?:\s+[-\w./~*]+)+$/,
|
|
15
16
|
/^head(?:\s+.+)?$/,
|
|
16
17
|
/^tail(?:\s+.+)?$/,
|
|
@@ -151,6 +152,36 @@ function matchAny(patterns, command) {
|
|
|
151
152
|
return patterns.some((pattern) => pattern.test(command));
|
|
152
153
|
}
|
|
153
154
|
|
|
155
|
+
function stripQuotedSegments(command = "") {
|
|
156
|
+
let output = "";
|
|
157
|
+
let quote = "";
|
|
158
|
+
let escaped = false;
|
|
159
|
+
for (const char of String(command || "")) {
|
|
160
|
+
if (escaped) {
|
|
161
|
+
escaped = false;
|
|
162
|
+
if (!quote) output += " ";
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (char === "\\") {
|
|
166
|
+
escaped = true;
|
|
167
|
+
if (!quote) output += char;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (quote) {
|
|
171
|
+
if (char === quote) quote = "";
|
|
172
|
+
output += " ";
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (char === "'" || char === '"') {
|
|
176
|
+
quote = char;
|
|
177
|
+
output += " ";
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
output += char;
|
|
181
|
+
}
|
|
182
|
+
return output;
|
|
183
|
+
}
|
|
184
|
+
|
|
154
185
|
function isSafeRelativeDir(value) {
|
|
155
186
|
const normalized = String(value || "").trim();
|
|
156
187
|
if (!normalized || normalized.startsWith("/") || normalized.startsWith("~")) return false;
|
|
@@ -231,7 +262,8 @@ function classifySimpleCommand(normalized) {
|
|
|
231
262
|
const gitCloneClassification = classifyGitClone(normalized);
|
|
232
263
|
if (gitCloneClassification) return gitCloneClassification;
|
|
233
264
|
|
|
234
|
-
const
|
|
265
|
+
const unquoted = stripQuotedSegments(normalized);
|
|
266
|
+
const lowered = ` ${unquoted.toLowerCase()} `;
|
|
235
267
|
if (BLOCKED_WRITE_TOKENS.some((part) => lowered.includes(part))) {
|
|
236
268
|
return {
|
|
237
269
|
category: "destructive",
|
|
@@ -240,7 +272,7 @@ function classifySimpleCommand(normalized) {
|
|
|
240
272
|
reason: `Command contains a write-capable or destructive token: ${normalized}`,
|
|
241
273
|
};
|
|
242
274
|
}
|
|
243
|
-
if (BLOCKED_SHELL_TOKENS.some((part) =>
|
|
275
|
+
if (BLOCKED_SHELL_TOKENS.some((part) => unquoted.includes(part))) {
|
|
244
276
|
return {
|
|
245
277
|
category: "general-shell",
|
|
246
278
|
needsNetwork: true,
|
package/src/permission-advice.js
CHANGED
|
@@ -142,14 +142,14 @@ function adviceForCategory(category = "", { toolName = "", args = {}, config = {
|
|
|
142
142
|
"This command is destructive and was blocked. Do not retry variants. First offer inspect-only or dry-run cleanup evidence; destructive cleanup requires explicit user approval.",
|
|
143
143
|
options: [
|
|
144
144
|
"Inspect only: run non-destructive checks such as `git status --short`, `git clean -nd`, `find <path> -maxdepth ... -print`, or targeted file listings.",
|
|
145
|
-
"Safer cleanup plan: write a report listing exact files that would be removed
|
|
146
|
-
"Explicit destructive approval: only
|
|
145
|
+
"Safer cleanup plan: write a report listing exact files that would be removed. Do not include executable delete/reset/clean commands in the safe or non-destructive section.",
|
|
146
|
+
"Explicit destructive approval: only after the user accepts data-loss risk, provide a separate approval path such as a rerun command with --allow-destructive.",
|
|
147
147
|
],
|
|
148
148
|
suggestedCommand: resumeCommand({
|
|
149
149
|
config,
|
|
150
150
|
state,
|
|
151
151
|
sandboxMode: "docker-workspace",
|
|
152
|
-
prompt: "Continue with inspect-only or dry-run cleanup evidence. Do not delete, reset, clean, or
|
|
152
|
+
prompt: "Continue with inspect-only or dry-run cleanup evidence. Do not delete, reset, clean, overwrite, or include executable destructive cleanup commands in safe/non-destructive instructions unless the user explicitly approves destructive actions.",
|
|
153
153
|
}),
|
|
154
154
|
destructiveApprovalCommand: resumeCommand({
|
|
155
155
|
config,
|