@lazyingart/agintiflow 0.20.246 → 0.20.247

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.246",
3
+ "version": "0.20.247",
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",
@@ -51,6 +51,25 @@ const artifactContract = deriveScsTaskContract({
51
51
  taskProfile: "chatops",
52
52
  });
53
53
  assert.equal(artifactContract.requiresExternalEvidence, true, "real chat artifact work lost its evidence gate");
54
+ const retainedReportContract = deriveScsTaskContract({
55
+ goal: [
56
+ "The completed evidence is already saved in tmp/reliability-evidence-pass.md and must remain read-only.",
57
+ "Read only missing bounded ranges of tmp/reliability-evidence-pass.md.",
58
+ "Rewrite agent-reliability-evidence-review.md as a concise decision document.",
59
+ "Rebuild sources.json so it contains only cited sources.",
60
+ ].join("\n"),
61
+ taskProfile: "research",
62
+ });
63
+ assert.deepEqual(
64
+ retainedReportContract.exactOutputPaths,
65
+ ["agent-reliability-evidence-review.md", "sources.json"],
66
+ "report continuation confused an existing saved input with rewrite/rebuild outputs"
67
+ );
68
+ assert.deepEqual(
69
+ retainedReportContract.exactInputPaths,
70
+ ["tmp/reliability-evidence-pass.md"],
71
+ "report continuation lost the read-only evidence input"
72
+ );
54
73
  assert.ok(artifactContract.requiredEvidence.some((item) => item.category === "artifact"));
55
74
  const scopedArtifactRootContract = deriveScsTaskContract({
56
75
  goal:
@@ -355,11 +374,60 @@ function noisyFullReadPair(index, generation) {
355
374
  ];
356
375
  }
357
376
 
377
+ function boundedOutputReadPair(index, generation) {
378
+ const id = `output-${generation}-${index}`;
379
+ return [
380
+ {
381
+ role: "assistant",
382
+ content: "",
383
+ reasoning_content: "Inspect the existing mutable output.",
384
+ tool_calls: [
385
+ {
386
+ id,
387
+ type: "function",
388
+ function: {
389
+ name: "read_file",
390
+ arguments: JSON.stringify({
391
+ path: "agent-reliability-evidence-review.md",
392
+ startLine: 1 + (index - 1) * 40,
393
+ lineLimit: 40,
394
+ }),
395
+ },
396
+ },
397
+ ],
398
+ },
399
+ {
400
+ role: "tool",
401
+ tool_call_id: id,
402
+ content: JSON.stringify({
403
+ ok: true,
404
+ toolName: "read_file",
405
+ path: "agent-reliability-evidence-review.md",
406
+ startLine: 1 + (index - 1) * 40,
407
+ lineLimit: 40,
408
+ lineCount: 240,
409
+ bytes: 24000,
410
+ sha256: `${generation}${String(index).padStart(2, "0")}`.repeat(24).slice(0, 64),
411
+ contentTruncated: false,
412
+ content: `MUTABLE-OUTPUT-${generation}-${index}\n${"old output content ".repeat(170)}`,
413
+ }),
414
+ },
415
+ ];
416
+ }
417
+
358
418
  const twiceCompactedState = {
359
419
  ...compactionState,
420
+ meta: {
421
+ scs: {
422
+ taskContract: {
423
+ exactOutputPaths: ["agent-reliability-evidence-review.md", "sources.json"],
424
+ },
425
+ },
426
+ },
360
427
  messages: [
361
428
  ...deepSeekRuntimeMessages,
362
429
  ...Array.from({ length: 14 }, (_, index) => noisyFullReadPair(index + 1, 2)).flat(),
430
+ ...Array.from({ length: 6 }, (_, index) => boundedOutputReadPair(index + 1, 2)).flat(),
363
431
  ],
364
432
  };
365
433
  const twiceCompacted = buildContextBudgetCompactionMessages(
@@ -381,9 +449,11 @@ assert.equal(
381
449
 
382
450
  const thriceCompactedState = {
383
451
  ...compactionState,
452
+ meta: twiceCompactedState.meta,
384
453
  messages: [
385
454
  ...twiceCompacted,
386
455
  ...Array.from({ length: 14 }, (_, index) => noisyFullReadPair(index + 1, 3)).flat(),
456
+ ...Array.from({ length: 6 }, (_, index) => boundedOutputReadPair(index + 1, 3)).flat(),
387
457
  ],
388
458
  };
389
459
  const thriceCompacted = buildContextBudgetCompactionMessages(
@@ -995,7 +995,7 @@ function compactRetainedToolPayload(toolName, payload = {}, args = {}) {
995
995
  result.contentTruncatedByLines = payload.contentTruncatedByLines === true;
996
996
  if (payload.sha256) result.sha256 = compactSingleLine(payload.sha256, 96);
997
997
  const content = String(payload.content || payload.contentPreview || "");
998
- if (content) result.content = compactMultiline(content, 4200);
998
+ if (content) result.content = compactMultiline(content, 3000);
999
999
  if (Array.isArray(payload.pathEvidence)) {
1000
1000
  result.pathEvidence = compactPathItems(payload.pathEvidence, 12, ["path", "source"]);
1001
1001
  }
@@ -1018,7 +1018,22 @@ function compactRetainedToolPayload(toolName, payload = {}, args = {}) {
1018
1018
  return redactValue(result);
1019
1019
  }
1020
1020
 
1021
- function retainedToolRecordPriority(record = {}) {
1021
+ function retainedPathMatchesOutput(sourcePath = "", outputPaths = []) {
1022
+ const normalize = (value = "") =>
1023
+ String(value || "")
1024
+ .replace(/\\/g, "/")
1025
+ .replace(/^\.\//, "")
1026
+ .replace(/\/{2,}/g, "/")
1027
+ .replace(/\/$/, "");
1028
+ const source = normalize(sourcePath);
1029
+ if (!source) return false;
1030
+ return outputPaths.some((candidate) => {
1031
+ const output = normalize(candidate);
1032
+ return output && (source === output || source.endsWith(`/${output}`) || output.endsWith(`/${source}`));
1033
+ });
1034
+ }
1035
+
1036
+ function retainedToolRecordPriority(record = {}, outputPaths = []) {
1022
1037
  const name = String(record.name || "");
1023
1038
  const args = record.args || {};
1024
1039
  const payload = record.payload || {};
@@ -1032,11 +1047,13 @@ function retainedToolRecordPriority(record = {}) {
1032
1047
  } else if (name === "read_file") {
1033
1048
  const range = retainedReadRange(payload, args);
1034
1049
  priority = range.lineLimit > 0 ? 750 : 600;
1050
+ const sourcePath = String(payload.path || args.path || "").trim();
1051
+ if (retainedPathMatchesOutput(sourcePath, outputPaths)) priority -= 220;
1035
1052
  } else if (["search_files", "list_files"].includes(name)) priority = 400;
1036
1053
  return priority + Math.min(0.999, Math.max(0, Number(record.ordinal) || 0) / 100000);
1037
1054
  }
1038
1055
 
1039
- function retainedToolStateMessages(messages = [], limit = 12) {
1056
+ function retainedToolStateMessages(messages = [], limit = 12, outputPaths = []) {
1040
1057
  const callsById = new Map();
1041
1058
  const recordsByKey = new Map();
1042
1059
  let ordinal = 0;
@@ -1086,7 +1103,7 @@ function retainedToolStateMessages(messages = [], limit = 12) {
1086
1103
  const selected = [...records]
1087
1104
  .sort(
1088
1105
  (left, right) =>
1089
- retainedToolRecordPriority(right) - retainedToolRecordPriority(left) ||
1106
+ retainedToolRecordPriority(right, outputPaths) - retainedToolRecordPriority(left, outputPaths) ||
1090
1107
  right.ordinal - left.ordinal
1091
1108
  )
1092
1109
  .slice(0, Math.max(1, Number(limit) || 12))
@@ -1118,8 +1135,8 @@ function retainedToolStateMessages(messages = [], limit = 12) {
1118
1135
  });
1119
1136
  }
1120
1137
 
1121
- function retainedToolStateTextMessages(messages = [], limit = 12) {
1122
- const nativeMessages = retainedToolStateMessages(messages, limit);
1138
+ function retainedToolStateTextMessages(messages = [], limit = 12, outputPaths = []) {
1139
+ const nativeMessages = retainedToolStateMessages(messages, limit, outputPaths);
1123
1140
  const retained = [];
1124
1141
  for (let index = 0; index < nativeMessages.length; index += 2) {
1125
1142
  const assistantMessage = nativeMessages[index];
@@ -1139,13 +1156,13 @@ function retainedToolStateTextMessages(messages = [], limit = 12) {
1139
1156
  return retained;
1140
1157
  }
1141
1158
 
1142
- function retainedToolPairPriority(pair = [], order = 0) {
1159
+ function retainedToolPairPriority(pair = [], order = 0, outputPaths = []) {
1143
1160
  const assistantCall = pair[0]?.tool_calls?.[0];
1144
1161
  const retained = pair.length === 1 ? parseRetainedToolEvidenceMessage(pair[0]) : null;
1145
1162
  const name = String(retained?.name || assistantCall?.function?.name || "");
1146
1163
  const args = retained?.args || safeParseToolContent(assistantCall?.function?.arguments) || {};
1147
1164
  const payload = retained?.payload || safeParseToolContent(pair[1]?.content) || {};
1148
- return retainedToolRecordPriority({ name, args, payload, ordinal: order });
1165
+ return retainedToolRecordPriority({ name, args, payload, ordinal: order }, outputPaths);
1149
1166
  }
1150
1167
 
1151
1168
  function isRuntimeCompactionRequest(content = "") {
@@ -1327,9 +1344,10 @@ function buildCompactedRuntimeMessages(state, config, snapshot, step, options =
1327
1344
  // synthetic pairs, so preserve their bounded evidence as explicit runtime
1328
1345
  // context instead of fabricating assistant reasoning.
1329
1346
  const deepSeekCompaction = normalizeProviderId(config.provider, "") === "deepseek";
1347
+ const exactOutputPaths = exactOutputPathsForState(state);
1330
1348
  const retainedToolMessages = deepSeekCompaction
1331
- ? retainedToolStateTextMessages(messages)
1332
- : retainedToolStateMessages(messages);
1349
+ ? retainedToolStateTextMessages(messages, 12, exactOutputPaths)
1350
+ : retainedToolStateMessages(messages, 12, exactOutputPaths);
1333
1351
  const snapshotSummary = {
1334
1352
  step,
1335
1353
  maxSteps: config.maxSteps,
@@ -1407,7 +1425,7 @@ function buildCompactedRuntimeMessages(state, config, snapshot, step, options =
1407
1425
  }));
1408
1426
  const boundedContent = compactTextForTokenBudget(
1409
1427
  compactedContent,
1410
- Math.max(1024, Math.floor(targetTokens * 0.52)),
1428
+ Math.max(1024, Math.floor(targetTokens * (retainedToolMessages.length ? 0.4 : 0.52))),
1411
1429
  { headFraction: 0.58 }
1412
1430
  );
1413
1431
  const baseMessages = [
@@ -1423,7 +1441,7 @@ function buildCompactedRuntimeMessages(state, config, snapshot, step, options =
1423
1441
  retainedPairs.push({
1424
1442
  pair,
1425
1443
  order: retainedPairs.length,
1426
- priority: retainedToolPairPriority(pair, retainedPairs.length),
1444
+ priority: retainedToolPairPriority(pair, retainedPairs.length, exactOutputPaths),
1427
1445
  });
1428
1446
  }
1429
1447
  const selectedPairs = [];
@@ -373,9 +373,9 @@ function inferExactOutputPaths(goal = "") {
373
373
  "gi"
374
374
  );
375
375
  const directOutputAction =
376
- /\b(save|saved|write|written|output|create|store|update|modify|edit)\b|保存|写入|寫入|输出|輸出|创建|建立|更新|修改|编辑|編輯/i;
376
+ /\b(save|write|rewrite|output|create|rebuild|replace|regenerate|generate|store|update|modify|edit)\b|保存|写入|寫入|重写|重寫|输出|輸出|创建|建立|重建|替换|替換|重新生成|生成|更新|修改|编辑|編輯/i;
377
377
  const directOutputActionGlobal =
378
- /\b(save|saved|write|written|output|create|store|update|modify|edit)\b|保存|写入|寫入|输出|輸出|创建|建立|更新|修改|编辑|編輯/gi;
378
+ /\b(save|write|rewrite|output|create|rebuild|replace|regenerate|generate|store|update|modify|edit)\b|保存|写入|寫入|重写|重寫|输出|輸出|创建|建立|重建|替换|替換|重新生成|生成|更新|修改|编辑|編輯/gi;
379
379
  const outputListHeader =
380
380
  /^(?:#+\s*)?(?:(?:required|final|expected|declared|target|pilot|deliverable)\s+)*(?:create|created files?|files? to create|outputs?|output structure|required outputs?|artifacts?|deliverables?|generated files?|writer requirements|renderer requirements|生成文件|输出结构|輸出結構|输出文件|輸出文件|创建文件|建立文件)(?:\s+(?:outputs?|artifacts?|deliverables?))?\s*[::]?\s*$/i;
381
381
  const nonOutputToolLine =
@@ -470,7 +470,7 @@ function inferExactInputPaths(goal = "") {
470
470
  const inputAction =
471
471
  /\b(use|using|read|load|fill|upload|attach|import|select|choose|reference|input|from|fix|repair|patch|correct)\b|使用|读取|讀取|加载|載入|填写|填入|上传|上傳|附加|导入|導入|选择|選擇|选取|選取|参考|參考|素材|图片|圖片|照片|提示词|提示詞|修复|修正|更正|从|從/i;
472
472
  const directOutputAction =
473
- /\b(save|saved|write|written|output|create|store|update|modify|edit)\b|保存|写入|寫入|输出|輸出|创建|建立|更新|修改|编辑|編輯/i;
473
+ /\b(save|write|rewrite|output|create|rebuild|replace|regenerate|generate|store|update|modify|edit)\b|保存|写入|寫入|重写|重寫|输出|輸出|创建|建立|重建|替换|替換|重新生成|生成|更新|修改|编辑|編輯/i;
474
474
  const pushPath = (raw = "") => {
475
475
  const cleaned = String(raw || "").trim();
476
476
  if (!cleaned || /[{}]/.test(cleaned)) return;