omnius 1.0.456 → 1.0.458
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/index.js +474 -32
- package/npm-shrinkwrap.json +5 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14315,7 +14315,7 @@ var init_file_edit = __esm({
|
|
|
14315
14315
|
path: { type: "string", description: "Absolute or relative file path" },
|
|
14316
14316
|
old_string: {
|
|
14317
14317
|
type: "string",
|
|
14318
|
-
description: "The exact string to search for and replace. Must be unique in the file (or use replace_all). Use old_string_base64 when JSON escaping is fragile."
|
|
14318
|
+
description: "The exact current string to search for and replace, copied from the most recent file_read for this file. Must be unique in the file (or use replace_all). Use old_string_base64 when JSON escaping is fragile."
|
|
14319
14319
|
},
|
|
14320
14320
|
old_string_base64: {
|
|
14321
14321
|
type: "string",
|
|
@@ -14340,14 +14340,14 @@ var init_file_edit = __esm({
|
|
|
14340
14340
|
},
|
|
14341
14341
|
expected_hash: {
|
|
14342
14342
|
type: "string",
|
|
14343
|
-
description: "
|
|
14343
|
+
description: "SHA-256 from the most recent file_read for this file. The runner refuses unverified exact replacements that omit or mismatch this hash."
|
|
14344
14344
|
},
|
|
14345
14345
|
dry_run: {
|
|
14346
14346
|
type: "boolean",
|
|
14347
14347
|
description: "Validate the edit and preview the diff without modifying disk."
|
|
14348
14348
|
}
|
|
14349
14349
|
},
|
|
14350
|
-
required: ["path"],
|
|
14350
|
+
required: ["path", "expected_hash"],
|
|
14351
14351
|
allOf: [
|
|
14352
14352
|
{ anyOf: [{ required: ["old_string"] }, { required: ["old_string_base64"] }] },
|
|
14353
14353
|
{ anyOf: [{ required: ["new_string"] }, { required: ["new_string_base64"] }] }
|
|
@@ -28570,7 +28570,7 @@ var init_batch_edit = __esm({
|
|
|
28570
28570
|
},
|
|
28571
28571
|
old_string: {
|
|
28572
28572
|
type: "string",
|
|
28573
|
-
description: "Exact string to find and replace
|
|
28573
|
+
description: "Exact current string to find and replace, copied from the most recent file_read for this file. Must be unique unless replace_all. Use old_string_base64 when JSON escaping is fragile."
|
|
28574
28574
|
},
|
|
28575
28575
|
old_string_base64: {
|
|
28576
28576
|
type: "string",
|
|
@@ -28595,10 +28595,10 @@ var init_batch_edit = __esm({
|
|
|
28595
28595
|
},
|
|
28596
28596
|
expected_hash: {
|
|
28597
28597
|
type: "string",
|
|
28598
|
-
description: "SHA-256 from the most recent file_read for this file. All edits for a file must use the same hash
|
|
28598
|
+
description: "SHA-256 from the most recent file_read for this file. All edits for a file must use the same verified hash."
|
|
28599
28599
|
}
|
|
28600
28600
|
},
|
|
28601
|
-
required: ["path"],
|
|
28601
|
+
required: ["path", "expected_hash"],
|
|
28602
28602
|
allOf: [
|
|
28603
28603
|
{ anyOf: [{ required: ["old_string"] }, { required: ["old_string_base64"] }] },
|
|
28604
28604
|
{ anyOf: [{ required: ["new_string"] }, { required: ["new_string_base64"] }] }
|
|
@@ -566824,6 +566824,7 @@ function shouldIgnore(relPath, base3, patterns) {
|
|
|
566824
566824
|
function scanWorkspace(opts) {
|
|
566825
566825
|
const root = opts.root;
|
|
566826
566826
|
const maxFiles = Math.max(1, Math.min(2e3, opts.maxFiles ?? 200));
|
|
566827
|
+
const maxDirs = Math.max(1, Math.min(5e3, opts.maxDirs ?? 1e3));
|
|
566827
566828
|
const noGitignore = opts.noGitignore === true;
|
|
566828
566829
|
const noDefaults = opts.noDefaults === true;
|
|
566829
566830
|
const patterns = [];
|
|
@@ -566834,6 +566835,7 @@ function scanWorkspace(opts) {
|
|
|
566834
566835
|
if (opts.extraIgnore)
|
|
566835
566836
|
patterns.push(...opts.extraIgnore);
|
|
566836
566837
|
const files = [];
|
|
566838
|
+
const dirs = [];
|
|
566837
566839
|
let totalBytes = 0;
|
|
566838
566840
|
let truncated = false;
|
|
566839
566841
|
let dirsVisited = 0;
|
|
@@ -566849,6 +566851,17 @@ function scanWorkspace(opts) {
|
|
|
566849
566851
|
continue;
|
|
566850
566852
|
visited.add(dir);
|
|
566851
566853
|
dirsVisited++;
|
|
566854
|
+
if (dirs.length < maxDirs) {
|
|
566855
|
+
try {
|
|
566856
|
+
const st = statSync32(dir);
|
|
566857
|
+
dirs.push({
|
|
566858
|
+
abs: dir,
|
|
566859
|
+
rel: relative8(root, dir) || ".",
|
|
566860
|
+
mtimeMs: st.mtimeMs
|
|
566861
|
+
});
|
|
566862
|
+
} catch {
|
|
566863
|
+
}
|
|
566864
|
+
}
|
|
566852
566865
|
let entries = [];
|
|
566853
566866
|
try {
|
|
566854
566867
|
entries = readdirSync30(dir);
|
|
@@ -566883,7 +566896,87 @@ function scanWorkspace(opts) {
|
|
|
566883
566896
|
}
|
|
566884
566897
|
}
|
|
566885
566898
|
files.sort((a2, b) => a2.rel.localeCompare(b.rel));
|
|
566886
|
-
|
|
566899
|
+
dirs.sort((a2, b) => a2.rel.localeCompare(b.rel));
|
|
566900
|
+
return { files, dirs, totalBytes, truncated, dirsVisited };
|
|
566901
|
+
}
|
|
566902
|
+
function humanBytes(n2) {
|
|
566903
|
+
if (n2 < 1024)
|
|
566904
|
+
return `${n2}B`;
|
|
566905
|
+
if (n2 < 1024 * 1024)
|
|
566906
|
+
return `${(n2 / 1024).toFixed(1)}KB`;
|
|
566907
|
+
return `${(n2 / 1024 / 1024).toFixed(1)}MB`;
|
|
566908
|
+
}
|
|
566909
|
+
function ensureTreeNode(root, rel) {
|
|
566910
|
+
if (!rel || rel === ".")
|
|
566911
|
+
return root;
|
|
566912
|
+
let node = root;
|
|
566913
|
+
for (const part of rel.split("/").filter(Boolean)) {
|
|
566914
|
+
let child = node.children.get(part);
|
|
566915
|
+
if (!child) {
|
|
566916
|
+
child = { name: part, children: /* @__PURE__ */ new Map(), directory: true };
|
|
566917
|
+
node.children.set(part, child);
|
|
566918
|
+
}
|
|
566919
|
+
node = child;
|
|
566920
|
+
}
|
|
566921
|
+
return node;
|
|
566922
|
+
}
|
|
566923
|
+
function renderWorkspaceTree(scan, opts = {}) {
|
|
566924
|
+
const maxLines = Math.max(10, Math.min(2e3, opts.maxLines ?? 120));
|
|
566925
|
+
const includeFileSizes = opts.includeFileSizes !== false;
|
|
566926
|
+
const root = {
|
|
566927
|
+
name: ".",
|
|
566928
|
+
children: /* @__PURE__ */ new Map(),
|
|
566929
|
+
directory: true
|
|
566930
|
+
};
|
|
566931
|
+
for (const dir of scan.dirs)
|
|
566932
|
+
ensureTreeNode(root, dir.rel).directory = true;
|
|
566933
|
+
for (const file of scan.files) {
|
|
566934
|
+
const parts = file.rel.split("/").filter(Boolean);
|
|
566935
|
+
const name10 = parts.pop();
|
|
566936
|
+
if (!name10)
|
|
566937
|
+
continue;
|
|
566938
|
+
const parent = ensureTreeNode(root, parts.join("/"));
|
|
566939
|
+
parent.children.set(name10, {
|
|
566940
|
+
name: name10,
|
|
566941
|
+
children: /* @__PURE__ */ new Map(),
|
|
566942
|
+
file,
|
|
566943
|
+
directory: false
|
|
566944
|
+
});
|
|
566945
|
+
}
|
|
566946
|
+
const lines = ["./"];
|
|
566947
|
+
let truncated = false;
|
|
566948
|
+
const walk2 = (node, depth) => {
|
|
566949
|
+
const children2 = [...node.children.values()].sort((a2, b) => {
|
|
566950
|
+
if (a2.directory !== b.directory)
|
|
566951
|
+
return a2.directory ? -1 : 1;
|
|
566952
|
+
return a2.name.localeCompare(b.name);
|
|
566953
|
+
});
|
|
566954
|
+
for (const child of children2) {
|
|
566955
|
+
if (lines.length >= maxLines) {
|
|
566956
|
+
truncated = true;
|
|
566957
|
+
return;
|
|
566958
|
+
}
|
|
566959
|
+
const indent2 = " ".repeat(depth);
|
|
566960
|
+
if (child.directory) {
|
|
566961
|
+
lines.push(`${indent2}${child.name}/`);
|
|
566962
|
+
walk2(child, depth + 1);
|
|
566963
|
+
if (truncated)
|
|
566964
|
+
return;
|
|
566965
|
+
} else {
|
|
566966
|
+
const size = includeFileSizes && child.file ? ` (${humanBytes(child.file.bytes)})` : "";
|
|
566967
|
+
lines.push(`${indent2}${child.name}${size}`);
|
|
566968
|
+
}
|
|
566969
|
+
}
|
|
566970
|
+
};
|
|
566971
|
+
walk2(root, 1);
|
|
566972
|
+
if (truncated || scan.truncated) {
|
|
566973
|
+
if (lines.length >= maxLines)
|
|
566974
|
+
lines[lines.length - 1] = "... [workspace tree truncated]";
|
|
566975
|
+
else
|
|
566976
|
+
lines.push("... [workspace tree truncated]");
|
|
566977
|
+
truncated = true;
|
|
566978
|
+
}
|
|
566979
|
+
return { text: lines.join("\n"), lineCount: lines.length, truncated };
|
|
566887
566980
|
}
|
|
566888
566981
|
var UNIVERSAL_DEFAULTS;
|
|
566889
566982
|
var init_world_state_disk_scan = __esm({
|
|
@@ -567578,9 +567671,9 @@ function regenerate(opts) {
|
|
|
567578
567671
|
lines.push(` No files found in workspace (excluding ignored paths).`);
|
|
567579
567672
|
} else {
|
|
567580
567673
|
const totalBytes = files.reduce((sum, f2) => sum + f2.bytes, 0);
|
|
567581
|
-
lines.push(` ${files.length} file(s)${truncated ? " (truncated — more exist)" : ""}, total ${
|
|
567674
|
+
lines.push(` ${files.length} file(s)${truncated ? " (truncated — more exist)" : ""}, total ${humanBytes2(totalBytes)}.`);
|
|
567582
567675
|
if (lastWriteFile) {
|
|
567583
|
-
lines.push(` Most recently modified: ${lastWriteFile.rel} (${
|
|
567676
|
+
lines.push(` Most recently modified: ${lastWriteFile.rel} (${humanBytes2(lastWriteFile.bytes)}, ${ago(nowMs - lastWriteFile.mtimeMs)}).`);
|
|
567584
567677
|
}
|
|
567585
567678
|
const topDirs = /* @__PURE__ */ new Map();
|
|
567586
567679
|
for (const f2 of files) {
|
|
@@ -567676,7 +567769,7 @@ function reconciledMark(t2) {
|
|
|
567676
567769
|
return "BLOCK";
|
|
567677
567770
|
}
|
|
567678
567771
|
}
|
|
567679
|
-
function
|
|
567772
|
+
function humanBytes2(n2) {
|
|
567680
567773
|
if (n2 < 1024)
|
|
567681
567774
|
return `${n2}B`;
|
|
567682
567775
|
if (n2 < 1024 * 1024)
|
|
@@ -573437,6 +573530,7 @@ var init_evidenceLedger = __esm({
|
|
|
573437
573530
|
this.entries.set(path12, {
|
|
573438
573531
|
...existing,
|
|
573439
573532
|
content: keepNew ? built.text : existing.content,
|
|
573533
|
+
contentHash: input.contentHash ?? existing.contentHash,
|
|
573440
573534
|
fidelity: keepNew ? built.fidelity : existing.fidelity,
|
|
573441
573535
|
ranges: mergeRanges([...existing.ranges, range]),
|
|
573442
573536
|
lastReadTurn: turn,
|
|
@@ -573447,6 +573541,7 @@ var init_evidenceLedger = __esm({
|
|
|
573447
573541
|
}
|
|
573448
573542
|
this.entries.set(path12, {
|
|
573449
573543
|
path: path12,
|
|
573544
|
+
contentHash: input.contentHash,
|
|
573450
573545
|
readVersion: fileVersion,
|
|
573451
573546
|
mtimeMs: input.mtimeMs ?? 0,
|
|
573452
573547
|
lastReadTurn: turn,
|
|
@@ -573475,7 +573570,7 @@ var init_evidenceLedger = __esm({
|
|
|
573475
573570
|
* like a manual chmod, device reconnect, or human edit), mark as stale.
|
|
573476
573571
|
* Returns true if evidence was valid, false if became stale or stat failed.
|
|
573477
573572
|
*/
|
|
573478
|
-
validateFreshness(path12) {
|
|
573573
|
+
validateFreshness(path12, statPath = path12) {
|
|
573479
573574
|
const e2 = this.entries.get(path12);
|
|
573480
573575
|
if (!e2)
|
|
573481
573576
|
return false;
|
|
@@ -573484,7 +573579,7 @@ var init_evidenceLedger = __esm({
|
|
|
573484
573579
|
if (e2.mtimeMs <= 0)
|
|
573485
573580
|
return true;
|
|
573486
573581
|
try {
|
|
573487
|
-
const st = statSync36(
|
|
573582
|
+
const st = statSync36(statPath, { throwIfNoEntry: false });
|
|
573488
573583
|
if (!st)
|
|
573489
573584
|
return true;
|
|
573490
573585
|
if (st.mtimeMs > e2.mtimeMs) {
|
|
@@ -573499,6 +573594,11 @@ var init_evidenceLedger = __esm({
|
|
|
573499
573594
|
get(path12) {
|
|
573500
573595
|
return this.entries.get(path12);
|
|
573501
573596
|
}
|
|
573597
|
+
markStale(path12) {
|
|
573598
|
+
const e2 = this.entries.get(path12);
|
|
573599
|
+
if (e2)
|
|
573600
|
+
e2.stale = true;
|
|
573601
|
+
}
|
|
573502
573602
|
size() {
|
|
573503
573603
|
return this.entries.size;
|
|
573504
573604
|
}
|
|
@@ -573521,12 +573621,12 @@ var init_evidenceLedger = __esm({
|
|
|
573521
573621
|
];
|
|
573522
573622
|
let used = lines.join("\n").length;
|
|
573523
573623
|
for (const e2 of sorted) {
|
|
573524
|
-
const header = e2.stale ? `▸ ${e2.path} @v${e2.readVersion} [STALE — changed since read; re-read needed] (${rangeLabel(e2.ranges)})` : `▸ ${e2.path} @v${e2.readVersion} [FRESH] (${rangeLabel(e2.ranges)}):`;
|
|
573624
|
+
const header = e2.stale ? `▸ ${e2.path} @v${e2.readVersion} [STALE — changed since read; re-read needed] (${rangeLabel(e2.ranges)})` : `▸ ${e2.path} @v${e2.readVersion} [FRESH${e2.contentHash ? ` sha256=${e2.contentHash}` : ""}] (${rangeLabel(e2.ranges)}):`;
|
|
573525
573625
|
const body = e2.stale ? "" : "\n" + indent(e2.content);
|
|
573526
573626
|
const chunk = `${header}${body}
|
|
573527
573627
|
`;
|
|
573528
573628
|
if (used + chunk.length > maxChars) {
|
|
573529
|
-
const stub = `▸ ${e2.path} @v${e2.readVersion} [${e2.stale ? "STALE" :
|
|
573629
|
+
const stub = `▸ ${e2.path} @v${e2.readVersion} [${e2.stale ? "STALE" : `FRESH${e2.contentHash ? ` sha256=${e2.contentHash}` : ""}`}] (${rangeLabel(e2.ranges)})
|
|
573530
573630
|
`;
|
|
573531
573631
|
if (used + stub.length <= maxChars) {
|
|
573532
573632
|
lines.push(stub);
|
|
@@ -574603,9 +574703,22 @@ ${input.error}`;
|
|
|
574603
574703
|
}
|
|
574604
574704
|
if (input.realFileMutation)
|
|
574605
574705
|
diagnoses.add("project-file-mutation");
|
|
574606
|
-
const
|
|
574607
|
-
|
|
574608
|
-
|
|
574706
|
+
const focusDecision = input.focusDecision && typeof input.focusDecision === "object" ? input.focusDecision : null;
|
|
574707
|
+
const focusDecisionKind = typeof focusDecision?.["kind"] === "string" ? focusDecision["kind"] : null;
|
|
574708
|
+
if (focusDecisionKind === "block_tool_call") {
|
|
574709
|
+
if (focusDecision?.["success"] === true || input.success) {
|
|
574710
|
+
diagnoses.add("focus-supervisor-cached-evidence");
|
|
574711
|
+
} else {
|
|
574712
|
+
diagnoses.add("focus-supervisor-block");
|
|
574713
|
+
}
|
|
574714
|
+
} else {
|
|
574715
|
+
const focusDecisionJson = previewJson(input.focusDecision ?? {});
|
|
574716
|
+
if (focusDecisionJson.includes("block_tool_call")) {
|
|
574717
|
+
if (input.success)
|
|
574718
|
+
diagnoses.add("focus-supervisor-cached-evidence");
|
|
574719
|
+
else
|
|
574720
|
+
diagnoses.add("focus-supervisor-block");
|
|
574721
|
+
}
|
|
574609
574722
|
}
|
|
574610
574723
|
const focusJson = previewJson(input.focusSupervisor ?? {});
|
|
574611
574724
|
if (focusJson.includes("block_tool_call") || focusJson.includes("requiredNextAction")) {
|
|
@@ -574736,7 +574849,8 @@ function writeContract(contractPath) {
|
|
|
574736
574849
|
"",
|
|
574737
574850
|
"- `shell-brace-whitespace`: a shell command used brace expansion containing whitespace, which can split an intended path set into unrelated shell words.",
|
|
574738
574851
|
"- `successful-command-needs-post-state-audit`: the command exited zero but its shape is risky enough that filesystem state should be inspected.",
|
|
574739
|
-
"- `focus-supervisor-block`: the tool result or supervisor state shows
|
|
574852
|
+
"- `focus-supervisor-block`: the tool result or supervisor state shows an unsuccessful blocked next action.",
|
|
574853
|
+
"- `focus-supervisor-cached-evidence`: the focus supervisor short-circuited a call successfully by reusing current cached evidence.",
|
|
574740
574854
|
"- `background-task-id-missing`: task status lookup could not find the spawned task id.",
|
|
574741
574855
|
"- `raw-discovery-dominates-context`: context-window metrics show low signal/noise around raw discovery output.",
|
|
574742
574856
|
""
|
|
@@ -575305,6 +575419,10 @@ var init_focusSupervisor = __esm({
|
|
|
575305
575419
|
this.clearSatisfiedDirective("requested edit already applied", input.turn);
|
|
575306
575420
|
return;
|
|
575307
575421
|
}
|
|
575422
|
+
if (input.success && input.noop && input.isReadLike && (this.directive?.requiredNextAction === "use_cached_evidence" || this.directive?.requiredNextAction === "read_authoritative_target")) {
|
|
575423
|
+
this.clearSatisfiedDirective(input.runtimeAuthored ? "cached authoritative evidence reused" : "authoritative evidence already available", input.turn);
|
|
575424
|
+
return;
|
|
575425
|
+
}
|
|
575308
575426
|
if (input.runtimeAuthored) {
|
|
575309
575427
|
this.lastDecision = "runtime_authored_not_satisfied";
|
|
575310
575428
|
this.lastReason = "runtime-authored control result did not execute the requested tool";
|
|
@@ -577519,7 +577637,7 @@ RECOVERY: cd to the directory containing '${file}', run a plain install with no
|
|
|
577519
577637
|
import { existsSync as _fsExistsSync, readFileSync as _fsReadFileSync, writeFileSync as _fsWriteFileSync, appendFileSync as _fsAppendFileSync, unlinkSync as _fsUnlinkSync, mkdirSync as _fsMkdirSync, statSync as _fsStatSync, readdirSync as _fsReaddirSync } from "node:fs";
|
|
577520
577638
|
import { execFile as _execFile, spawn as _spawn } from "node:child_process";
|
|
577521
577639
|
import { createHash as _createHash } from "node:crypto";
|
|
577522
|
-
import { join as _pathJoin, resolve as _pathResolve } from "node:path";
|
|
577640
|
+
import { join as _pathJoin, relative as _pathRelative, resolve as _pathResolve } from "node:path";
|
|
577523
577641
|
import { tmpdir as _osTmpdir } from "node:os";
|
|
577524
577642
|
import { homedir as _osHomedir } from "node:os";
|
|
577525
577643
|
import { z as z17 } from "zod";
|
|
@@ -578182,6 +578300,7 @@ var init_agenticRunner = __esm({
|
|
|
578182
578300
|
init_lesson_bank();
|
|
578183
578301
|
init_intervention_replay();
|
|
578184
578302
|
init_world_state_regenerator();
|
|
578303
|
+
init_world_state_disk_scan();
|
|
578185
578304
|
init_backward_pass_runner();
|
|
578186
578305
|
init_world_state_plan_reconciler();
|
|
578187
578306
|
init_process_async2();
|
|
@@ -581015,7 +581134,7 @@ ${result.error ?? ""}`;
|
|
|
581015
581134
|
if (result.success !== true)
|
|
581016
581135
|
return false;
|
|
581017
581136
|
if (toolName === "file_read") {
|
|
581018
|
-
return targetPaths.length > 0 && targetPaths.some((path12) => this._evidenceLedger.hasFresh(path12));
|
|
581137
|
+
return targetPaths.length > 0 && targetPaths.some((path12) => this._evidenceLedger.hasFresh(this._normalizeEvidencePath(path12)));
|
|
581019
581138
|
}
|
|
581020
581139
|
return toolName === "list_directory" || toolName === "find_files" || toolName === "grep_search";
|
|
581021
581140
|
}
|
|
@@ -583124,6 +583243,133 @@ ${latest.output || ""}`.trim();
|
|
|
583124
583243
|
return null;
|
|
583125
583244
|
}
|
|
583126
583245
|
}
|
|
583246
|
+
/**
|
|
583247
|
+
* Render a fresh, bounded workspace tree from disk for the active context
|
|
583248
|
+
* frame, and persist the fuller capped tree under .omnius/world-state/tree.
|
|
583249
|
+
* This is deliberately independent of tool history: it answers "what exists
|
|
583250
|
+
* where right now?" without forcing the model to list_directory for basic
|
|
583251
|
+
* orientation.
|
|
583252
|
+
*/
|
|
583253
|
+
_renderWorkspaceTreeBlock(turn) {
|
|
583254
|
+
const rawEnabled = String(process.env["OMNIUS_CONTEXT_WORKSPACE_TREE"] ?? "1").trim().toLowerCase();
|
|
583255
|
+
if (rawEnabled === "0" || rawEnabled === "false" || rawEnabled === "off") {
|
|
583256
|
+
return null;
|
|
583257
|
+
}
|
|
583258
|
+
const intEnv = (name10, fallback, min, max) => {
|
|
583259
|
+
const parsed = Number.parseInt(process.env[name10] ?? "", 10);
|
|
583260
|
+
return Number.isFinite(parsed) ? Math.max(min, Math.min(max, parsed)) : fallback;
|
|
583261
|
+
};
|
|
583262
|
+
const root = this.authoritativeWorkingDirectory();
|
|
583263
|
+
const maxFiles = intEnv("OMNIUS_CONTEXT_TREE_MAX_FILES", 1e3, 20, 2e3);
|
|
583264
|
+
const maxDirs = intEnv("OMNIUS_CONTEXT_TREE_MAX_DIRS", 1500, 20, 5e3);
|
|
583265
|
+
const contextLines = intEnv("OMNIUS_CONTEXT_TREE_LINES", 90, 20, 400);
|
|
583266
|
+
const artifactLines = intEnv("OMNIUS_CONTEXT_TREE_ARTIFACT_LINES", 1800, 100, 4e3);
|
|
583267
|
+
try {
|
|
583268
|
+
const scan = scanWorkspace({ root, maxFiles, maxDirs });
|
|
583269
|
+
const compactTree = renderWorkspaceTree(scan, { maxLines: contextLines });
|
|
583270
|
+
const fullTree = renderWorkspaceTree(scan, { maxLines: artifactLines });
|
|
583271
|
+
const totalBytes = scan.files.reduce((sum, file) => sum + file.bytes, 0);
|
|
583272
|
+
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
583273
|
+
const focusSnapshot = this._focusSupervisor?.snapshot();
|
|
583274
|
+
const recentActions = this._adversaryToolOutcomes.slice(-12).map((item) => ({
|
|
583275
|
+
turn: item.turn,
|
|
583276
|
+
tool: item.tool,
|
|
583277
|
+
success: item.succeeded,
|
|
583278
|
+
path: item.path,
|
|
583279
|
+
stateVersion: item.stateVersion,
|
|
583280
|
+
preview: item.preview.slice(0, 240)
|
|
583281
|
+
}));
|
|
583282
|
+
const recentActionLines = recentActions.slice(-6).map((item) => {
|
|
583283
|
+
const path12 = item.path ? ` path=${item.path}` : "";
|
|
583284
|
+
return `- turn=${item.turn} ${item.tool} ${item.success ? "ok" : "err"}${path12}: ${item.preview.replace(/\s+/g, " ").slice(0, 160)}`;
|
|
583285
|
+
});
|
|
583286
|
+
const treeDir = _pathJoin(this.omniusStateDir(), "world-state", "tree");
|
|
583287
|
+
const turnName = `turn-${String(turn).padStart(4, "0")}`;
|
|
583288
|
+
const latestTextPath = _pathJoin(treeDir, "latest.txt");
|
|
583289
|
+
const latestJsonPath = _pathJoin(treeDir, "latest.json");
|
|
583290
|
+
const turnTextPath = _pathJoin(treeDir, `${turnName}.txt`);
|
|
583291
|
+
const turnJsonPath = _pathJoin(treeDir, `${turnName}.json`);
|
|
583292
|
+
let artifactDisplay = latestTextPath;
|
|
583293
|
+
try {
|
|
583294
|
+
_fsMkdirSync(treeDir, { recursive: true });
|
|
583295
|
+
const header = [
|
|
583296
|
+
`WORKSPACE TREE SNAPSHOT`,
|
|
583297
|
+
`generated_at=${generatedAt}`,
|
|
583298
|
+
`turn=${turn}`,
|
|
583299
|
+
`session=${this._sessionId ?? ""}`,
|
|
583300
|
+
`root=${root}`,
|
|
583301
|
+
`files=${scan.files.length}${scan.truncated ? "+" : ""}`,
|
|
583302
|
+
`dirs=${scan.dirs.length}`,
|
|
583303
|
+
`bytes=${totalBytes}`,
|
|
583304
|
+
focusSnapshot?.directive?.requiredNextAction ? `supervisor_required_next_action=${focusSnapshot.directive.requiredNextAction}` : `supervisor_required_next_action=none`,
|
|
583305
|
+
recentActionLines.length ? `recent_actions=${recentActions.length}` : `recent_actions=0`,
|
|
583306
|
+
recentActionLines.length ? recentActionLines.join("\n") : "",
|
|
583307
|
+
""
|
|
583308
|
+
].join("\n");
|
|
583309
|
+
const text2 = `${header}${fullTree.text}
|
|
583310
|
+
`;
|
|
583311
|
+
const payload = {
|
|
583312
|
+
generatedAt,
|
|
583313
|
+
turn,
|
|
583314
|
+
sessionId: this._sessionId,
|
|
583315
|
+
root,
|
|
583316
|
+
supervisor: focusSnapshot ? {
|
|
583317
|
+
state: focusSnapshot.state,
|
|
583318
|
+
lastDecision: focusSnapshot.lastDecision,
|
|
583319
|
+
lastReason: focusSnapshot.lastReason,
|
|
583320
|
+
requiredNextAction: focusSnapshot.directive?.requiredNextAction ?? null,
|
|
583321
|
+
directiveReason: focusSnapshot.directive?.reason ?? null
|
|
583322
|
+
} : null,
|
|
583323
|
+
recentActions,
|
|
583324
|
+
stats: {
|
|
583325
|
+
files: scan.files.length,
|
|
583326
|
+
dirs: scan.dirs.length,
|
|
583327
|
+
totalBytes,
|
|
583328
|
+
truncated: scan.truncated || fullTree.truncated,
|
|
583329
|
+
dirsVisited: scan.dirsVisited
|
|
583330
|
+
},
|
|
583331
|
+
files: scan.files.map((file) => ({
|
|
583332
|
+
path: file.rel,
|
|
583333
|
+
bytes: file.bytes,
|
|
583334
|
+
mtimeMs: file.mtimeMs
|
|
583335
|
+
})),
|
|
583336
|
+
dirs: scan.dirs.map((dir) => ({
|
|
583337
|
+
path: dir.rel,
|
|
583338
|
+
mtimeMs: dir.mtimeMs
|
|
583339
|
+
}))
|
|
583340
|
+
};
|
|
583341
|
+
_fsWriteFileSync(latestTextPath, text2, "utf8");
|
|
583342
|
+
_fsWriteFileSync(turnTextPath, text2, "utf8");
|
|
583343
|
+
_fsWriteFileSync(latestJsonPath, JSON.stringify(payload, null, 2), "utf8");
|
|
583344
|
+
_fsWriteFileSync(turnJsonPath, JSON.stringify(payload, null, 2), "utf8");
|
|
583345
|
+
const rel = _pathRelative(root, latestTextPath).replace(/\\/g, "/");
|
|
583346
|
+
if (rel && !rel.startsWith(".."))
|
|
583347
|
+
artifactDisplay = rel;
|
|
583348
|
+
} catch {
|
|
583349
|
+
artifactDisplay = "(workspace tree artifact write failed; inline digest still current)";
|
|
583350
|
+
}
|
|
583351
|
+
return [
|
|
583352
|
+
"[WORKSPACE TREE — fresh per-turn disk crawl]",
|
|
583353
|
+
`generated_at=${generatedAt}`,
|
|
583354
|
+
`root=${root}`,
|
|
583355
|
+
`files=${scan.files.length}${scan.truncated ? "+" : ""} dirs=${scan.dirs.length} total_bytes=${totalBytes}`,
|
|
583356
|
+
`artifact=${artifactDisplay}`,
|
|
583357
|
+
focusSnapshot?.directive?.requiredNextAction ? `supervisor_required_next_action=${focusSnapshot.directive.requiredNextAction}` : `supervisor_required_next_action=none`,
|
|
583358
|
+
recentActionLines.length ? `recent_actions:
|
|
583359
|
+
${recentActionLines.join("\n")}` : "recent_actions=none",
|
|
583360
|
+
"Use this tree for path orientation. It includes empty directories; it does not include file contents.",
|
|
583361
|
+
compactTree.truncated || scan.truncated ? "Inline tree is truncated; read the artifact path above for the fuller capped tree before broad rediscovery." : "Inline tree is complete within the configured scan cap.",
|
|
583362
|
+
compactTree.text
|
|
583363
|
+
].join("\n");
|
|
583364
|
+
} catch (error) {
|
|
583365
|
+
return [
|
|
583366
|
+
"[WORKSPACE TREE — fresh per-turn disk crawl]",
|
|
583367
|
+
`root=${root}`,
|
|
583368
|
+
`scan_failed=${error instanceof Error ? error.message : String(error)}`,
|
|
583369
|
+
"Do not assume the tree is current; use list_directory/find_files if path orientation is required."
|
|
583370
|
+
].join("\n");
|
|
583371
|
+
}
|
|
583372
|
+
}
|
|
583127
583373
|
/**
|
|
583128
583374
|
* REG-2: Render a compact "files known to me" block from `_worldFacts`.
|
|
583129
583375
|
* Goal: tell the model what it has already touched this run so it stops
|
|
@@ -583663,6 +583909,7 @@ ${chunk.content}`, {
|
|
|
583663
583909
|
this._renderRuntimeRootBlock(),
|
|
583664
583910
|
this._taskState.goal ? `Active task: (see user message above — the goal block defers to the user message as the authoritative source)` : null
|
|
583665
583911
|
].filter(Boolean).join("\n\n");
|
|
583912
|
+
const workspaceTreeBlock = this._renderWorkspaceTreeBlock(turn);
|
|
583666
583913
|
const filesystemBlock = this._renderFilesystemStateBlock(turn);
|
|
583667
583914
|
const artifactContractBlock = this._contractRegistry.format(15);
|
|
583668
583915
|
const todoBlock = this._renderTodoStateBlock(turn);
|
|
@@ -583707,6 +583954,13 @@ ${this._lastPprMemoryLines.slice(0, 5).join("\n")}` : null;
|
|
|
583707
583954
|
createdTurn: turn,
|
|
583708
583955
|
ttlTurns: 1
|
|
583709
583956
|
}),
|
|
583957
|
+
signalFromBlock("known_files", "turn.workspace-tree", workspaceTreeBlock, {
|
|
583958
|
+
id: "workspace-tree",
|
|
583959
|
+
dedupeKey: "turn.workspace-tree",
|
|
583960
|
+
priority: 84,
|
|
583961
|
+
createdTurn: turn,
|
|
583962
|
+
ttlTurns: 1
|
|
583963
|
+
}),
|
|
583710
583964
|
signalFromBlock("known_files", "turn.artifact-contracts", artifactContractBlock, {
|
|
583711
583965
|
id: "artifact-contracts",
|
|
583712
583966
|
dedupeKey: "turn.artifact-contracts",
|
|
@@ -583795,7 +584049,7 @@ ${this._lastPprMemoryLines.slice(0, 5).join("\n")}` : null;
|
|
|
583795
584049
|
// Raised from 10k to fit the durable read-evidence content (known_files)
|
|
583796
584050
|
// that replaces the re-read loop; the per-kind budget below caps it.
|
|
583797
584051
|
maxChars: 13e3,
|
|
583798
|
-
kindCharBudget: { known_files:
|
|
584052
|
+
kindCharBudget: { known_files: 8500 },
|
|
583799
584053
|
includeDiagnostics: process.env["OMNIUS_CONTEXT_FABRIC_DIAGNOSTICS"] === "1"
|
|
583800
584054
|
});
|
|
583801
584055
|
this._lastContextFrameDiagnostics = frame.diagnostics;
|
|
@@ -583999,10 +584253,12 @@ ${blob}
|
|
|
583999
584253
|
if (p2 && content.length >= 100) {
|
|
584000
584254
|
try {
|
|
584001
584255
|
this._evidenceLedger.recordRead({
|
|
584002
|
-
path: p2,
|
|
584256
|
+
path: this._normalizeEvidencePath(p2),
|
|
584003
584257
|
content,
|
|
584258
|
+
contentHash: this._extractFileReadSha256(content) ?? void 0,
|
|
584004
584259
|
range: { start: 0, end: Number.POSITIVE_INFINITY },
|
|
584005
584260
|
fileVersion: this._worldFacts.files.get(p2)?.writeCount ?? 0,
|
|
584261
|
+
mtimeMs: this._statMtimeMsForToolPath(p2),
|
|
584006
584262
|
turn: this._taskState?.toolCallCount ?? 0
|
|
584007
584263
|
});
|
|
584008
584264
|
} catch {
|
|
@@ -587901,6 +588157,18 @@ ${memoryLines.join("\n")}`
|
|
|
587901
588157
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
587902
588158
|
});
|
|
587903
588159
|
}
|
|
588160
|
+
for (const tc of msg.toolCalls) {
|
|
588161
|
+
const patched = this._attachFreshExpectedHashesToEditArgs(tc.name, tc.arguments ?? {});
|
|
588162
|
+
if (patched.patchedCount > 0) {
|
|
588163
|
+
tc.arguments = patched.args;
|
|
588164
|
+
this.emit({
|
|
588165
|
+
type: "status",
|
|
588166
|
+
content: `Edit freshness: attached expected_hash to ${patched.patchedCount} ${tc.name} edit target${patched.patchedCount === 1 ? "" : "s"} from fresh file_read evidence`,
|
|
588167
|
+
turn,
|
|
588168
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
588169
|
+
});
|
|
588170
|
+
}
|
|
588171
|
+
}
|
|
587904
588172
|
messages2.push({
|
|
587905
588173
|
role: "assistant",
|
|
587906
588174
|
content: msg.content || null,
|
|
@@ -588640,7 +588908,8 @@ Read the current file if needed, make a different concrete edit, or move to veri
|
|
|
588640
588908
|
const readArgs = tc.arguments;
|
|
588641
588909
|
const readPath2 = String(readArgs?.["path"] ?? readArgs?.["file"] ?? "");
|
|
588642
588910
|
if (readPath2) {
|
|
588643
|
-
const
|
|
588911
|
+
const evidencePath = this._normalizeEvidencePath(readPath2);
|
|
588912
|
+
const wasFresh = evidencePath && this._evidenceLedger.validateFreshness(evidencePath, this._absoluteToolPath(readPath2));
|
|
588644
588913
|
if (!wasFresh) {
|
|
588645
588914
|
recentToolResults.delete(toolFingerprint);
|
|
588646
588915
|
dedupHitCount.delete(toolFingerprint);
|
|
@@ -588770,13 +589039,13 @@ ${cachedResult}`,
|
|
|
588770
589039
|
error: this.unknownToolError(tc.name)
|
|
588771
589040
|
};
|
|
588772
589041
|
} else {
|
|
588773
|
-
let validationError =
|
|
588774
|
-
if (tool.inputSchema) {
|
|
589042
|
+
let validationError = this._validateFreshExpectedHashesForEdit(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
|
|
589043
|
+
if (!validationError && tool.inputSchema) {
|
|
588775
589044
|
const parseResult = tool.inputSchema.safeParse(tc.arguments);
|
|
588776
589045
|
if (!parseResult.success) {
|
|
588777
589046
|
validationError = parseResult.error.issues.map((iss) => `${iss.path.join(".")}: ${iss.message}`).join("; ");
|
|
588778
589047
|
}
|
|
588779
|
-
} else if (tool.parameters && typeof tool.parameters === "object") {
|
|
589048
|
+
} else if (!validationError && tool.parameters && typeof tool.parameters === "object") {
|
|
588780
589049
|
const required = tool.parameters.required;
|
|
588781
589050
|
if (Array.isArray(required)) {
|
|
588782
589051
|
const missing = required.filter((field) => tc.arguments[field] === void 0 || tc.arguments[field] === null);
|
|
@@ -589017,7 +589286,7 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
589017
589286
|
lastWriteTurn: turn,
|
|
589018
589287
|
writeCount: nextWriteCount
|
|
589019
589288
|
});
|
|
589020
|
-
this._evidenceLedger.markMutated(p2, nextWriteCount, turn);
|
|
589289
|
+
this._evidenceLedger.markMutated(this._normalizeEvidencePath(p2), nextWriteCount, turn);
|
|
589021
589290
|
}
|
|
589022
589291
|
if (paths.length > 0) {
|
|
589023
589292
|
this._writesSinceLastTodoWrite += paths.length;
|
|
@@ -589061,11 +589330,12 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
589061
589330
|
const start3 = rOffset === void 0 && rLimit === void 0 ? 0 : Math.max(1, rOffset ?? 1);
|
|
589062
589331
|
const end = rOffset === void 0 && rLimit === void 0 ? Number.POSITIVE_INFINITY : rLimit !== void 0 ? Math.max(1, rOffset ?? 1) + Math.max(0, rLimit) - 1 : Number.POSITIVE_INFINITY;
|
|
589063
589332
|
this._evidenceLedger.recordRead({
|
|
589064
|
-
path: p2,
|
|
589333
|
+
path: this._normalizeEvidencePath(p2),
|
|
589065
589334
|
content: result.output,
|
|
589335
|
+
contentHash: typeof result.beforeHash === "string" ? result.beforeHash : void 0,
|
|
589066
589336
|
range: { start: start3, end },
|
|
589067
589337
|
fileVersion: this._worldFacts.files.get(p2)?.writeCount ?? 0,
|
|
589068
|
-
mtimeMs:
|
|
589338
|
+
mtimeMs: this._statMtimeMsForToolPath(p2),
|
|
589069
589339
|
turn
|
|
589070
589340
|
});
|
|
589071
589341
|
}
|
|
@@ -590286,6 +590556,7 @@ Evidence: ${evidencePreview}`.slice(0, 500);
|
|
|
590286
590556
|
focusSupervisor: focusAfterToolResult,
|
|
590287
590557
|
focusDecision: !focusDecision || focusDecision.kind === "pass" ? void 0 : {
|
|
590288
590558
|
kind: focusDecision.kind,
|
|
590559
|
+
success: focusDecision.kind === "block_tool_call" ? focusDecision.success : void 0,
|
|
590289
590560
|
state: focusDecision.directive.state,
|
|
590290
590561
|
reason: focusDecision.directive.reason,
|
|
590291
590562
|
requiredNextAction: focusDecision.directive.requiredNextAction
|
|
@@ -592760,13 +593031,14 @@ ${marker}` : marker);
|
|
|
592760
593031
|
const displayOutput = this.unwrapToolOutputForDisplay(output);
|
|
592761
593032
|
if (toolName === "file_read") {
|
|
592762
593033
|
const path13 = this.extractPrimaryToolPath(args);
|
|
592763
|
-
|
|
593034
|
+
const evidencePath = path13 ? this._normalizeEvidencePath(path13) : "";
|
|
593035
|
+
if (!evidencePath || !this._evidenceLedger.hasFresh(evidencePath))
|
|
592764
593036
|
return output;
|
|
592765
|
-
const entry = this._evidenceLedger.get(
|
|
593037
|
+
const entry = this._evidenceLedger.get(evidencePath);
|
|
592766
593038
|
return this.wrapToolOutputForModel(toolName, [
|
|
592767
593039
|
"[DISCOVERY COMPACTED - file_read evidence captured]",
|
|
592768
593040
|
`path=${path13}`,
|
|
592769
|
-
`captured=${this.countTextLines(displayOutput)} lines, ${displayOutput.length} chars${entry ? `, fidelity=${entry.fidelity}` : ""}`,
|
|
593041
|
+
`captured=${this.countTextLines(displayOutput)} lines, ${displayOutput.length} chars${entry ? `, fidelity=${entry.fidelity}${entry.contentHash ? `, sha256=${entry.contentHash}` : ""}` : ""}`,
|
|
592770
593042
|
'active_context="Evidence already gathered this run"',
|
|
592771
593043
|
"Use the active evidence frame. Re-read only if that frame marks this file STALE or you need a distinct range."
|
|
592772
593044
|
].join("\n"));
|
|
@@ -592912,6 +593184,175 @@ ${marker}` : marker);
|
|
|
592912
593184
|
return trimmed.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
592913
593185
|
}
|
|
592914
593186
|
}
|
|
593187
|
+
_absoluteToolPath(path12) {
|
|
593188
|
+
return _pathResolve(this.authoritativeWorkingDirectory(), path12.trim() || ".");
|
|
593189
|
+
}
|
|
593190
|
+
_normalizeEvidencePath(path12) {
|
|
593191
|
+
const trimmed = path12.trim();
|
|
593192
|
+
if (!trimmed)
|
|
593193
|
+
return "";
|
|
593194
|
+
try {
|
|
593195
|
+
const root = this.authoritativeWorkingDirectory();
|
|
593196
|
+
const abs = _pathResolve(root, trimmed);
|
|
593197
|
+
const rel = _pathRelative(root, abs).replace(/\\/g, "/");
|
|
593198
|
+
if (rel && !rel.startsWith("..") && rel !== ".")
|
|
593199
|
+
return rel;
|
|
593200
|
+
if (rel === "")
|
|
593201
|
+
return ".";
|
|
593202
|
+
return abs.replace(/\\/g, "/");
|
|
593203
|
+
} catch {
|
|
593204
|
+
return trimmed.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
593205
|
+
}
|
|
593206
|
+
}
|
|
593207
|
+
_statMtimeMsForToolPath(path12) {
|
|
593208
|
+
try {
|
|
593209
|
+
const st = _fsStatSync(this._absoluteToolPath(path12), {
|
|
593210
|
+
throwIfNoEntry: false
|
|
593211
|
+
});
|
|
593212
|
+
return st?.mtimeMs;
|
|
593213
|
+
} catch {
|
|
593214
|
+
return void 0;
|
|
593215
|
+
}
|
|
593216
|
+
}
|
|
593217
|
+
_normalizeExpectedHashValue(value2) {
|
|
593218
|
+
if (typeof value2 !== "string")
|
|
593219
|
+
return null;
|
|
593220
|
+
const raw = value2.trim();
|
|
593221
|
+
if (!raw)
|
|
593222
|
+
return null;
|
|
593223
|
+
const stripped = raw.replace(/^sha256[:=]/i, "").toLowerCase();
|
|
593224
|
+
return /^[a-f0-9]{64}$/.test(stripped) ? stripped : null;
|
|
593225
|
+
}
|
|
593226
|
+
_extractFileReadSha256(text2) {
|
|
593227
|
+
const match = text2.match(/\bsha256=([a-f0-9]{64})\b/i);
|
|
593228
|
+
return match ? match[1].toLowerCase() : null;
|
|
593229
|
+
}
|
|
593230
|
+
_rawExpectedHashValue(rec) {
|
|
593231
|
+
return rec["expected_hash"] ?? rec["expectedHash"] ?? rec["before_hash"] ?? rec["beforeHash"];
|
|
593232
|
+
}
|
|
593233
|
+
_freshReadHashForEditPath(path12) {
|
|
593234
|
+
const key = this._normalizeEvidencePath(path12);
|
|
593235
|
+
if (!key)
|
|
593236
|
+
return null;
|
|
593237
|
+
const entry = this._evidenceLedger.get(key);
|
|
593238
|
+
if (!entry || entry.stale || !entry.contentHash)
|
|
593239
|
+
return null;
|
|
593240
|
+
const statPath = this._absoluteToolPath(path12);
|
|
593241
|
+
if (!this._evidenceLedger.validateFreshness(key, statPath))
|
|
593242
|
+
return null;
|
|
593243
|
+
const fresh = this._evidenceLedger.get(key);
|
|
593244
|
+
if (!fresh || fresh.stale || !fresh.contentHash)
|
|
593245
|
+
return null;
|
|
593246
|
+
return {
|
|
593247
|
+
key,
|
|
593248
|
+
hash: fresh.contentHash,
|
|
593249
|
+
lastReadTurn: fresh.lastReadTurn
|
|
593250
|
+
};
|
|
593251
|
+
}
|
|
593252
|
+
_attachFreshExpectedHashesToEditArgs(toolName, args) {
|
|
593253
|
+
if (process.env["OMNIUS_ALLOW_UNVERIFIED_OLD_STRING_EDIT"] === "1") {
|
|
593254
|
+
return { args, patchedCount: 0 };
|
|
593255
|
+
}
|
|
593256
|
+
if (toolName === "file_edit") {
|
|
593257
|
+
if (this._normalizeExpectedHashValue(this._rawExpectedHashValue(args))) {
|
|
593258
|
+
return { args, patchedCount: 0 };
|
|
593259
|
+
}
|
|
593260
|
+
const path12 = this.extractPrimaryToolPath(args);
|
|
593261
|
+
const fresh = path12 ? this._freshReadHashForEditPath(path12) : null;
|
|
593262
|
+
if (!fresh)
|
|
593263
|
+
return { args, patchedCount: 0 };
|
|
593264
|
+
return { args: { ...args, expected_hash: fresh.hash }, patchedCount: 1 };
|
|
593265
|
+
}
|
|
593266
|
+
if (toolName !== "batch_edit" || !Array.isArray(args["edits"])) {
|
|
593267
|
+
return { args, patchedCount: 0 };
|
|
593268
|
+
}
|
|
593269
|
+
let patchedCount = 0;
|
|
593270
|
+
const edits = args["edits"].map((edit) => {
|
|
593271
|
+
if (!edit || typeof edit !== "object" || Array.isArray(edit))
|
|
593272
|
+
return edit;
|
|
593273
|
+
const rec = edit;
|
|
593274
|
+
if (this._normalizeExpectedHashValue(this._rawExpectedHashValue(rec))) {
|
|
593275
|
+
return rec;
|
|
593276
|
+
}
|
|
593277
|
+
const path12 = typeof rec["path"] === "string" ? rec["path"] : typeof rec["file"] === "string" ? rec["file"] : "";
|
|
593278
|
+
const fresh = path12 ? this._freshReadHashForEditPath(path12) : null;
|
|
593279
|
+
if (!fresh)
|
|
593280
|
+
return rec;
|
|
593281
|
+
patchedCount++;
|
|
593282
|
+
return { ...rec, expected_hash: fresh.hash };
|
|
593283
|
+
});
|
|
593284
|
+
return patchedCount > 0 ? { args: { ...args, edits }, patchedCount } : { args, patchedCount: 0 };
|
|
593285
|
+
}
|
|
593286
|
+
_validateFreshExpectedHashesForEdit(toolName, args) {
|
|
593287
|
+
if (process.env["OMNIUS_ALLOW_UNVERIFIED_OLD_STRING_EDIT"] === "1") {
|
|
593288
|
+
return null;
|
|
593289
|
+
}
|
|
593290
|
+
const targets = [];
|
|
593291
|
+
if (toolName === "file_edit") {
|
|
593292
|
+
const path12 = this.extractPrimaryToolPath(args);
|
|
593293
|
+
if (path12) {
|
|
593294
|
+
targets.push({
|
|
593295
|
+
label: path12,
|
|
593296
|
+
path: path12,
|
|
593297
|
+
expectedHash: this._normalizeExpectedHashValue(this._rawExpectedHashValue(args)),
|
|
593298
|
+
rawExpectedHash: this._rawExpectedHashValue(args)
|
|
593299
|
+
});
|
|
593300
|
+
}
|
|
593301
|
+
} else if (toolName === "batch_edit" && Array.isArray(args["edits"])) {
|
|
593302
|
+
args["edits"].forEach((edit, index) => {
|
|
593303
|
+
if (!edit || typeof edit !== "object" || Array.isArray(edit))
|
|
593304
|
+
return;
|
|
593305
|
+
const rec = edit;
|
|
593306
|
+
const path12 = typeof rec["path"] === "string" ? rec["path"] : typeof rec["file"] === "string" ? rec["file"] : "";
|
|
593307
|
+
if (!path12)
|
|
593308
|
+
return;
|
|
593309
|
+
targets.push({
|
|
593310
|
+
label: `edit #${index + 1} ${path12}`,
|
|
593311
|
+
path: path12,
|
|
593312
|
+
expectedHash: this._normalizeExpectedHashValue(this._rawExpectedHashValue(rec)),
|
|
593313
|
+
rawExpectedHash: this._rawExpectedHashValue(rec)
|
|
593314
|
+
});
|
|
593315
|
+
});
|
|
593316
|
+
} else {
|
|
593317
|
+
return null;
|
|
593318
|
+
}
|
|
593319
|
+
if (targets.length === 0)
|
|
593320
|
+
return null;
|
|
593321
|
+
const problems = [];
|
|
593322
|
+
for (const target of targets) {
|
|
593323
|
+
const fresh = this._freshReadHashForEditPath(target.path);
|
|
593324
|
+
if (target.rawExpectedHash !== void 0 && !target.expectedHash) {
|
|
593325
|
+
problems.push(`${target.label}: expected_hash is present but is not a valid 64-character SHA-256`);
|
|
593326
|
+
continue;
|
|
593327
|
+
}
|
|
593328
|
+
if (!fresh && target.expectedHash) {
|
|
593329
|
+
continue;
|
|
593330
|
+
}
|
|
593331
|
+
if (!fresh) {
|
|
593332
|
+
problems.push(`${target.label}: missing expected_hash and no fresh file_read hash is available for this file in the current run`);
|
|
593333
|
+
continue;
|
|
593334
|
+
}
|
|
593335
|
+
if (!target.expectedHash) {
|
|
593336
|
+
problems.push(`${target.label}: missing expected_hash; use sha256=${fresh.hash} from the fresh file_read evidence`);
|
|
593337
|
+
continue;
|
|
593338
|
+
}
|
|
593339
|
+
if (target.expectedHash !== fresh.hash) {
|
|
593340
|
+
problems.push(`${target.label}: expected_hash=${target.expectedHash} does not match fresh file_read sha256=${fresh.hash}`);
|
|
593341
|
+
}
|
|
593342
|
+
}
|
|
593343
|
+
if (problems.length === 0)
|
|
593344
|
+
return null;
|
|
593345
|
+
return [
|
|
593346
|
+
"[EDIT FRESHNESS CONTRACT]",
|
|
593347
|
+
"Exact replacement edits must be built from verified current file content, not remembered text.",
|
|
593348
|
+
"Before file_edit or batch_edit can run, each target must carry expected_hash from file_read. If the runner has fresh read evidence, it will attach that hash automatically; otherwise the edit tool verifies the provided hash against disk before mutating.",
|
|
593349
|
+
"For multiple edits to the same file, use one batch_edit against the same expected_hash so all replacements validate atomically before the file changes.",
|
|
593350
|
+
"",
|
|
593351
|
+
...problems.map((problem) => `- ${problem}`),
|
|
593352
|
+
"",
|
|
593353
|
+
"Next action: file_read the target file or range, then retry the edit with old_string copied exactly from that read and expected_hash set to the read's sha256."
|
|
593354
|
+
].join("\n");
|
|
593355
|
+
}
|
|
592915
593356
|
staleEditFamilyKey(toolName, pathKey, errorKind, targetHash, latestFileHash) {
|
|
592916
593357
|
return [
|
|
592917
593358
|
toolName,
|
|
@@ -631048,6 +631489,7 @@ var init_status_bar = __esm({
|
|
|
631048
631489
|
this._contentScrollOffset = 0;
|
|
631049
631490
|
if (this.active) {
|
|
631050
631491
|
this.repaintContent();
|
|
631492
|
+
this.refreshDynamicBlocks();
|
|
631051
631493
|
this._contentCursorNeedsReplay = true;
|
|
631052
631494
|
if (this.writeDepth > 0) this._contentCursorReplayActive = true;
|
|
631053
631495
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.458",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omnius",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.458",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
|
@@ -4138,9 +4138,9 @@
|
|
|
4138
4138
|
}
|
|
4139
4139
|
},
|
|
4140
4140
|
"node_modules/iconv-lite": {
|
|
4141
|
-
"version": "0.7.
|
|
4142
|
-
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.
|
|
4143
|
-
"integrity": "sha512-
|
|
4141
|
+
"version": "0.7.3",
|
|
4142
|
+
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz",
|
|
4143
|
+
"integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==",
|
|
4144
4144
|
"license": "MIT",
|
|
4145
4145
|
"dependencies": {
|
|
4146
4146
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
package/package.json
CHANGED