@lazyingart/agintiflow 0.20.228 → 0.20.230
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.230",
|
|
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",
|
|
@@ -23,6 +23,7 @@ import { formatBehaviorContractForPrompt } from "../src/behavior-contract.js";
|
|
|
23
23
|
import { resolveRuntimeConfig } from "../src/config.js";
|
|
24
24
|
import { readCodebaseMap } from "../src/codebase-map.js";
|
|
25
25
|
import { classifyCommand, evaluateCommandPolicy } from "../src/command-policy.js";
|
|
26
|
+
import { checkToolUse } from "../src/guardrails.js";
|
|
26
27
|
import { shouldReviewToolResult } from "../src/scs-controller.js";
|
|
27
28
|
import {
|
|
28
29
|
engineeringGuidanceForTask,
|
|
@@ -32,7 +33,12 @@ import {
|
|
|
32
33
|
import { createPlan } from "../src/model-client.js";
|
|
33
34
|
import { selectModelRoute } from "../src/model-routing.js";
|
|
34
35
|
import { listParallelScouts, runParallelScouts, shouldRunParallelScouts } from "../src/parallel-scouts.js";
|
|
35
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
buildFailedCommandAdvice,
|
|
38
|
+
buildPermissionAdvice,
|
|
39
|
+
isOptionalGeneratedPreviewCleanup,
|
|
40
|
+
isUnrequestedCleanupCommand,
|
|
41
|
+
} from "../src/permission-advice.js";
|
|
36
42
|
import { runJsonSpecialist } from "../src/json-specialist.js";
|
|
37
43
|
import { SessionStore } from "../src/session-store.js";
|
|
38
44
|
import { getTaskProfile } from "../src/task-profiles.js";
|
|
@@ -1203,6 +1209,97 @@ try {
|
|
|
1203
1209
|
destructiveAdvice.destructiveApprovalCommand.includes("--allow-destructive"),
|
|
1204
1210
|
"destructive advice did not provide an explicit approval command"
|
|
1205
1211
|
);
|
|
1212
|
+
const optionalPreviewCleanupArgs = {
|
|
1213
|
+
command:
|
|
1214
|
+
"rm -f build/verification/page-1.png build/verification/page-2.png; git status --short",
|
|
1215
|
+
};
|
|
1216
|
+
assert(
|
|
1217
|
+
isOptionalGeneratedPreviewCleanup("run_command", optionalPreviewCleanupArgs),
|
|
1218
|
+
"bounded generated verification-preview cleanup was not recognized"
|
|
1219
|
+
);
|
|
1220
|
+
const optionalPreviewCleanupAdvice = buildPermissionAdvice({
|
|
1221
|
+
toolName: "run_command",
|
|
1222
|
+
args: optionalPreviewCleanupArgs,
|
|
1223
|
+
guard: {
|
|
1224
|
+
category: "destructive",
|
|
1225
|
+
reason: "Destructive shell commands require Allow destructive actions.",
|
|
1226
|
+
},
|
|
1227
|
+
config: dockerWorkspacePolicy,
|
|
1228
|
+
state: { sessionId: "coding-optional-preview-cleanup-smoke" },
|
|
1229
|
+
});
|
|
1230
|
+
assert(
|
|
1231
|
+
optionalPreviewCleanupAdvice.autoRecover === true,
|
|
1232
|
+
"optional generated-preview cleanup should retain evidence and recover without pausing"
|
|
1233
|
+
);
|
|
1234
|
+
assert(
|
|
1235
|
+
/leave every candidate file in place/i.test(optionalPreviewCleanupAdvice.instruction),
|
|
1236
|
+
"optional generated-preview cleanup advice did not tell the agent to retain evidence"
|
|
1237
|
+
);
|
|
1238
|
+
assert(
|
|
1239
|
+
!isOptionalGeneratedPreviewCleanup("run_command", {
|
|
1240
|
+
command: "rm -f output/final-report.pdf",
|
|
1241
|
+
}),
|
|
1242
|
+
"a requested final artifact was misclassified as optional preview cleanup"
|
|
1243
|
+
);
|
|
1244
|
+
const mixedValidationCleanupArgs = {
|
|
1245
|
+
command:
|
|
1246
|
+
"python3 validate.py; rm -f output/page-*.png scratch-notes.md; git status --short",
|
|
1247
|
+
};
|
|
1248
|
+
assert(
|
|
1249
|
+
isUnrequestedCleanupCommand(
|
|
1250
|
+
"run_command",
|
|
1251
|
+
mixedValidationCleanupArgs,
|
|
1252
|
+
{ goal: "Create and verify a clean document." },
|
|
1253
|
+
{}
|
|
1254
|
+
),
|
|
1255
|
+
"unrequested cleanup embedded after validation was not recognized as recoverable"
|
|
1256
|
+
);
|
|
1257
|
+
const mixedValidationCleanupAdvice = buildPermissionAdvice({
|
|
1258
|
+
toolName: "run_command",
|
|
1259
|
+
args: mixedValidationCleanupArgs,
|
|
1260
|
+
guard: {
|
|
1261
|
+
category: "destructive",
|
|
1262
|
+
reason: "Destructive shell commands require Allow destructive actions.",
|
|
1263
|
+
},
|
|
1264
|
+
config: { ...dockerWorkspacePolicy, goal: "Create and verify a clean document." },
|
|
1265
|
+
state: { sessionId: "coding-unrequested-cleanup-smoke" },
|
|
1266
|
+
});
|
|
1267
|
+
assert(
|
|
1268
|
+
mixedValidationCleanupAdvice.autoRecover === true,
|
|
1269
|
+
"unrequested cleanup should be skipped without pausing substantive work"
|
|
1270
|
+
);
|
|
1271
|
+
assert(
|
|
1272
|
+
!isUnrequestedCleanupCommand(
|
|
1273
|
+
"run_command",
|
|
1274
|
+
{ command: "rm -f output/obsolete.pdf" },
|
|
1275
|
+
{ goal: "Delete the obsolete PDF." },
|
|
1276
|
+
{}
|
|
1277
|
+
),
|
|
1278
|
+
"an explicitly requested deletion was incorrectly treated as optional housekeeping"
|
|
1279
|
+
);
|
|
1280
|
+
const documentPageBatchGuard = checkToolUse({
|
|
1281
|
+
toolName: "read_image",
|
|
1282
|
+
args: { imagePaths: ["build/verification/page-1.png", "build/verification/page-2.png"] },
|
|
1283
|
+
snapshot: {},
|
|
1284
|
+
config: { ...dockerWorkspacePolicy, allowFileTools: true, taskProfile: "word" },
|
|
1285
|
+
});
|
|
1286
|
+
assert(
|
|
1287
|
+
documentPageBatchGuard.allowed === false &&
|
|
1288
|
+
documentPageBatchGuard.category === "document-page-visual-batch",
|
|
1289
|
+
"Word document review did not require one visual call per rendered page"
|
|
1290
|
+
);
|
|
1291
|
+
const documentPageBatchAdvice = buildPermissionAdvice({
|
|
1292
|
+
toolName: "read_image",
|
|
1293
|
+
args: { imagePaths: ["build/verification/page-1.png", "build/verification/page-2.png"] },
|
|
1294
|
+
guard: documentPageBatchGuard,
|
|
1295
|
+
config: { ...dockerWorkspacePolicy, taskProfile: "word" },
|
|
1296
|
+
state: { sessionId: "coding-document-page-visual-batch-smoke" },
|
|
1297
|
+
});
|
|
1298
|
+
assert(
|
|
1299
|
+
documentPageBatchAdvice.autoRecover === true &&
|
|
1300
|
+
/once for each rendered page/i.test(documentPageBatchAdvice.instruction),
|
|
1301
|
+
"Word document page batching did not recover into separate visual checks"
|
|
1302
|
+
);
|
|
1206
1303
|
const failedNetworkAdvice = buildFailedCommandAdvice({
|
|
1207
1304
|
args: { command: "git clone https://github.com/lazyingart/AgInTiFlow.git" },
|
|
1208
1305
|
commandPolicy: clonePolicy,
|
|
@@ -270,8 +270,8 @@ const wordDocumentContract = deriveScsTaskContract({
|
|
|
270
270
|
});
|
|
271
271
|
assert.deepEqual(
|
|
272
272
|
wordDocumentContract.requiredEvidence.map((item) => item.category).sort(),
|
|
273
|
-
["artifact", "command", "file"],
|
|
274
|
-
"Word document production must require written files, validation, and
|
|
273
|
+
["artifact", "command", "file", "visual"],
|
|
274
|
+
"Word document production must require written files, validation, durable artifacts, and visual evidence"
|
|
275
275
|
);
|
|
276
276
|
|
|
277
277
|
const groundingRoot = fs.mkdtempSync(path.join(os.tmpdir(), "aginti-source-grounding-"));
|
package/src/guardrails.js
CHANGED
|
@@ -245,6 +245,14 @@ export function checkToolUse({ toolName, args, snapshot, config }) {
|
|
|
245
245
|
.map((item) => String(item || "").trim())
|
|
246
246
|
.filter(Boolean);
|
|
247
247
|
if (values.length === 0) return { allowed: false, reason: "At least one image path or URL is required.", category: "perception-tools" };
|
|
248
|
+
if (String(config.taskProfile || "").toLowerCase() === "word" && values.length > 1) {
|
|
249
|
+
return {
|
|
250
|
+
allowed: false,
|
|
251
|
+
reason:
|
|
252
|
+
"Word-document page review requires one rendered page per image call so clipping, orphaned headings, sparse spill pages, and other page-specific defects cannot be averaged away.",
|
|
253
|
+
category: "document-page-visual-batch",
|
|
254
|
+
};
|
|
255
|
+
}
|
|
248
256
|
if (values.length > 4) return { allowed: false, reason: "Too many images. Maximum is 4.", category: "perception-tools" };
|
|
249
257
|
for (const value of values) {
|
|
250
258
|
if (/^https?:\/\//i.test(value)) {
|
package/src/permission-advice.js
CHANGED
|
@@ -23,6 +23,67 @@ const DOCKER_WORKSPACE_PATH_FAILURE_PATTERNS = [
|
|
|
23
23
|
/cannot statx? ['"][^'"]+['"]:\s+No such file or directory/i,
|
|
24
24
|
];
|
|
25
25
|
|
|
26
|
+
function unquoteShellToken(value = "") {
|
|
27
|
+
const text = String(value || "").trim();
|
|
28
|
+
if (
|
|
29
|
+
text.length >= 2 &&
|
|
30
|
+
((text.startsWith("'") && text.endsWith("'")) ||
|
|
31
|
+
(text.startsWith('"') && text.endsWith('"')))
|
|
32
|
+
) {
|
|
33
|
+
return text.slice(1, -1);
|
|
34
|
+
}
|
|
35
|
+
return text;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isGeneratedVerificationPreviewPath(value = "") {
|
|
39
|
+
const target = unquoteShellToken(value).replace(/\\/g, "/");
|
|
40
|
+
if (
|
|
41
|
+
!target ||
|
|
42
|
+
target.startsWith("/") ||
|
|
43
|
+
target.includes("..") ||
|
|
44
|
+
/[*?\[\]{}$`]/.test(target)
|
|
45
|
+
) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return (
|
|
49
|
+
/^(?:build|artifacts)\/verification\/[A-Za-z0-9._/-]+\.(?:png|jpe?g|webp)$/i.test(target) ||
|
|
50
|
+
/^output\/preview[-_][A-Za-z0-9._-]+\.(?:png|jpe?g|webp)$/i.test(target)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function isOptionalGeneratedPreviewCleanup(toolName = "", args = {}) {
|
|
55
|
+
if (toolName !== "run_command") return false;
|
|
56
|
+
const firstSegment = String(args.command || args.text || "")
|
|
57
|
+
.trim()
|
|
58
|
+
.split(/(?:&&|;|\n)/, 1)[0]
|
|
59
|
+
.trim();
|
|
60
|
+
const match = firstSegment.match(/^rm\s+-f\s+(.+)$/);
|
|
61
|
+
if (!match) return false;
|
|
62
|
+
const targets = match[1].trim().split(/\s+/).filter(Boolean);
|
|
63
|
+
return (
|
|
64
|
+
targets.length > 0 &&
|
|
65
|
+
targets.length <= 20 &&
|
|
66
|
+
targets.every((target) => isGeneratedVerificationPreviewPath(target))
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function goalRequestsDeletion(config = {}, state = {}) {
|
|
71
|
+
const goal = String(config.goal || state.goal || state.meta?.goalContract?.current || "");
|
|
72
|
+
return /\b(?:delete|remove|clean\s+up|cleanup|purge|erase|discard|drop)\b|删除|刪除|移除|清理|清除|删掉|刪掉|削除|消去/i.test(
|
|
73
|
+
goal
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function isUnrequestedCleanupCommand(toolName = "", args = {}, config = {}, state = {}) {
|
|
78
|
+
const goal = String(config.goal || state.goal || state.meta?.goalContract?.current || "").trim();
|
|
79
|
+
if (!goal || toolName !== "run_command" || goalRequestsDeletion(config, state)) return false;
|
|
80
|
+
const command = String(args.command || args.text || "");
|
|
81
|
+
return command
|
|
82
|
+
.split(/(?:&&|;|\n)/)
|
|
83
|
+
.map((segment) => segment.trim())
|
|
84
|
+
.some((segment) => /^(?:command\s+)?rm\s+(?:-[A-Za-z]*[fr][A-Za-z]*\s+|--force\s+)/.test(segment));
|
|
85
|
+
}
|
|
86
|
+
|
|
26
87
|
function quoteShell(value = "") {
|
|
27
88
|
const text = String(value || "");
|
|
28
89
|
return `'${text.replace(/'/g, `'\\''`)}'`;
|
|
@@ -136,6 +197,22 @@ function adviceForCategory(category = "", { toolName = "", args = {}, config = {
|
|
|
136
197
|
};
|
|
137
198
|
}
|
|
138
199
|
|
|
200
|
+
if (category === "document-page-visual-batch") {
|
|
201
|
+
return {
|
|
202
|
+
...base,
|
|
203
|
+
autoRecover: true,
|
|
204
|
+
summary:
|
|
205
|
+
"The document review batched multiple rendered pages, so page-specific visual defects could be missed.",
|
|
206
|
+
instruction:
|
|
207
|
+
"Continue automatically by calling read_image once for each rendered page. Evaluate clipping, overflow, orphaned headings, sparse spill pages, table splits, margins, and hierarchy on that page before moving to the next one.",
|
|
208
|
+
options: [
|
|
209
|
+
"Review page 1 alone, repair any defect, and rebuild before reviewing later pages.",
|
|
210
|
+
"Review each remaining page in a separate read_image call.",
|
|
211
|
+
"Finish only after every page has its own accepted visual evidence.",
|
|
212
|
+
],
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
139
216
|
if (category === "workspace-write") {
|
|
140
217
|
return {
|
|
141
218
|
...base,
|
|
@@ -214,6 +291,24 @@ function adviceForCategory(category = "", { toolName = "", args = {}, config = {
|
|
|
214
291
|
}
|
|
215
292
|
|
|
216
293
|
if (category === "destructive") {
|
|
294
|
+
if (
|
|
295
|
+
isOptionalGeneratedPreviewCleanup(toolName, args) ||
|
|
296
|
+
isUnrequestedCleanupCommand(toolName, args, config, state)
|
|
297
|
+
) {
|
|
298
|
+
return {
|
|
299
|
+
...base,
|
|
300
|
+
autoRecover: true,
|
|
301
|
+
summary:
|
|
302
|
+
"Unrequested cleanup was blocked safely; generated or verification files can remain ignored and the substantive task should continue.",
|
|
303
|
+
instruction:
|
|
304
|
+
"Do not retry, rename, or seek approval for this cleanup. Leave every candidate file in place, run any remaining read-only checks in a separate call, and finish the requested task when its substantive evidence passes.",
|
|
305
|
+
options: [
|
|
306
|
+
"Retain the generated previews as private verification evidence.",
|
|
307
|
+
"Run source hashes, artifact checks, and git status separately without a delete command.",
|
|
308
|
+
"Continue to a real content or layout repair if validation still reports a defect.",
|
|
309
|
+
],
|
|
310
|
+
};
|
|
311
|
+
}
|
|
217
312
|
return {
|
|
218
313
|
...base,
|
|
219
314
|
summary:
|
package/src/scs-evidence.js
CHANGED
|
@@ -259,7 +259,7 @@ const PROFILE_REQUIREMENTS = {
|
|
|
259
259
|
design: ["artifact", "visual"],
|
|
260
260
|
image: ["artifact", "visual"],
|
|
261
261
|
slides: ["artifact"],
|
|
262
|
-
word: ["file", "command", "artifact"],
|
|
262
|
+
word: ["file", "command", "artifact", "visual"],
|
|
263
263
|
data: ["file", "command", "artifact"],
|
|
264
264
|
qa: ["command"],
|
|
265
265
|
review: ["command"],
|
package/src/task-profiles.js
CHANGED
|
@@ -276,7 +276,7 @@ export const TASK_PROFILES = {
|
|
|
276
276
|
id: "word",
|
|
277
277
|
label: "Word documents",
|
|
278
278
|
prompt:
|
|
279
|
-
"Bias toward Word/docx/document workflows while still using writing, conversion, LaTeX, or scripts when useful. Preserve source material byte-for-byte and synthesize a reader-facing document from the current
|
|
279
|
+
"Bias toward Word/docx/document workflows while still using writing, conversion, LaTeX, or scripts when useful. Preserve source material byte-for-byte and synthesize a reader-facing document from the authoritative current facts instead of concatenating notes, logs, schemas, task IDs, private paths, or delivery instructions. Reconcile conflicting or superseded source facts before drafting: values labeled corrected, replaced, earlier, old, prior, cancelled, or no longer selected identify what to discard, and those discarded literals must not appear in the final document unless the user explicitly requests history or the history is necessary to explain a live decision. Before finishing, extract the final text and search for every superseded literal found in the sources. Prefer mature editable-document tooling already available in the workspace, such as python-docx, pandoc, or LibreOffice, over hand-written OOXML; when direct OOXML is genuinely necessary, validate its package parts and openability. Keep one maintainable source of truth and a reproducible project-local build command. Verify the DOCX is structurally editable, compile the PDF, run pdftotext or an equivalent extraction check that rejects replacement characters and unexpected control glyphs, and verify PDF text bounding boxes remain inside a readable page margin. Render every PDF page to a separate image under an ignored build/verification directory. Inspect one rendered page per read_image call, never batch pages into one vision call, and repair orphaned headings, near-empty spill pages, awkward table or paragraph breaks, overlaps, clipping, excessive whitespace, weak hierarchy, and inconsistent number formatting before finishing. Retain ignored verification renders as evidence; optional cleanup must never block completion. Use clear descriptive filenames, exclude caches and generated debris from commits, inspect git status/diff before committing, and report success only after the editable source, reader-facing current-state content, visual layout, searchable text, and requested artifacts all pass.",
|
|
280
280
|
tools: ["files", "shell", "canvas", "sandbox"],
|
|
281
281
|
},
|
|
282
282
|
latex: {
|