@oxecli/oxe 1.0.75 → 1.0.77
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/engine.js +1 -1
- package/dist/tools.js +34 -49
- package/dist/ui.js +1 -1
- package/package.json +1 -1
package/dist/engine.js
CHANGED
|
@@ -103,7 +103,7 @@ export class InferenceEngine {
|
|
|
103
103
|
result = await toolBash(args.command, args.timeout, args.cwd);
|
|
104
104
|
break;
|
|
105
105
|
case "glob":
|
|
106
|
-
result = toolGlob(args.pattern, args.path, args.limit);
|
|
106
|
+
result = toolGlob(args.pattern, args.path, args.limit, args.depth);
|
|
107
107
|
break;
|
|
108
108
|
case "grep":
|
|
109
109
|
result = toolGrep(args.pattern, args.path, args.glob, args.limit);
|
package/dist/tools.js
CHANGED
|
@@ -44,7 +44,7 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
44
44
|
if (oldContent.length + newContent.length > max_diff_source_chars) {
|
|
45
45
|
pendingDiffOutput.push(`\x1b[90m${pathName}: ${oldContent.length.toLocaleString()} chars -> ${newContent.length.toLocaleString()} chars ` +
|
|
46
46
|
`(diff hidden: exceeds ${max_diff_source_chars.toLocaleString()} char limit)\x1b[0m`);
|
|
47
|
-
return;
|
|
47
|
+
return null;
|
|
48
48
|
}
|
|
49
49
|
const patch = structuredPatch(pathName, pathName, oldContent, newContent, "", "", { context: max_diff_context_lines });
|
|
50
50
|
const contentLines = [];
|
|
@@ -74,7 +74,7 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
74
74
|
const added = contentLines.filter((c) => c.kind === "+").length;
|
|
75
75
|
const removed = contentLines.filter((c) => c.kind === "-").length;
|
|
76
76
|
if (!added && !removed)
|
|
77
|
-
return;
|
|
77
|
+
return null;
|
|
78
78
|
const shown = [];
|
|
79
79
|
let run = [];
|
|
80
80
|
let lastKind = null;
|
|
@@ -121,51 +121,30 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
121
121
|
if (v.newNum)
|
|
122
122
|
maxNum = Math.max(maxNum, v.newNum);
|
|
123
123
|
}
|
|
124
|
-
const numW =
|
|
125
|
-
|
|
126
|
-
for (const v of visible) {
|
|
127
|
-
const len = v.kind === "~" ? plainLen(v.body) : numW + 1 + 2 + plainLen(v.body);
|
|
128
|
-
contentW = Math.max(contentW, len);
|
|
129
|
-
}
|
|
130
|
-
const headerPlain = `${pathName} +${added} -${removed}`;
|
|
131
|
-
const boxW = Math.min(Math.max(contentW + 6, plainLen(headerPlain) + 6), Math.max(termW - 2, 20));
|
|
132
|
-
const innerW = Math.max(boxW - 4, 1);
|
|
133
|
-
const maxPath = Math.max(10, boxW - 2 - plainLen(` +${added} -${removed}`) - 3);
|
|
134
|
-
let pathDisp = pathName;
|
|
135
|
-
if (plainLen(pathDisp) > maxPath)
|
|
136
|
-
pathDisp = truncateStyled(pathDisp, Math.max(maxPath - 1, 1)) + "…";
|
|
137
|
-
const header = `\x1b[1m${pathDisp}\x1b[0m \x1b[32m+${added}\x1b[0m \x1b[31m-${removed}\x1b[0m`;
|
|
138
|
-
const headerStr = `─ ${header} `;
|
|
139
|
-
const top = `╭${headerStr}${"─".repeat(Math.max(0, boxW - 2 - plainLen(headerStr)))}╮`;
|
|
140
|
-
pendingDiffOutput.push(`\x1b[90m${top}\x1b[0m`);
|
|
141
|
-
const bodyMax = Math.max(innerW - numW - 3, 1);
|
|
124
|
+
const numW = String(maxNum).length;
|
|
125
|
+
const bodyMax = Math.max(termW - numW - 4, 20);
|
|
142
126
|
const gap = " ".repeat(numW);
|
|
143
127
|
for (const v of visible) {
|
|
144
128
|
if (v.kind === "~") {
|
|
145
|
-
const body = truncateStyled(v.body,
|
|
146
|
-
|
|
147
|
-
const fill = Math.max(0, innerW - plainLen(text));
|
|
148
|
-
pendingDiffOutput.push(`\x1b[90m│\x1b[0m ${text}${" ".repeat(fill)} \x1b[90m│\x1b[0m`);
|
|
129
|
+
const body = truncateStyled(v.body, bodyMax);
|
|
130
|
+
pendingDiffOutput.push(`\x1b[90m${gap} ${body}\x1b[0m`);
|
|
149
131
|
continue;
|
|
150
132
|
}
|
|
151
133
|
const num = v.kind === "+" ? v.newNum : v.oldNum;
|
|
152
134
|
const numStr = num ? String(num).padStart(numW, " ") : gap;
|
|
153
135
|
if (v.kind === "+" || v.kind === "-") {
|
|
154
|
-
const
|
|
136
|
+
const bg = v.kind === "+" ? "\x1b[42m" : "\x1b[41m";
|
|
137
|
+
const sign = v.kind === "+" ? "+" : "-";
|
|
155
138
|
const body = truncateStyled(v.body, bodyMax);
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
// Whole line is painted green/red, filling to the right edge.
|
|
159
|
-
pendingDiffOutput.push(`\x1b[90m│\x1b[0m ${color}${text}${" ".repeat(fill)}\x1b[0m \x1b[90m│\x1b[0m`);
|
|
139
|
+
const fill = Math.max(0, termW - numW - 4 - plainLen(body));
|
|
140
|
+
pendingDiffOutput.push(`${bg}\x1b[97m${numStr} ${sign} ${body}${" ".repeat(fill)}\x1b[0m`);
|
|
160
141
|
}
|
|
161
142
|
else {
|
|
162
143
|
const body = truncateStyled(v.kind === "\\" ? v.body : highlightCodeLine(v.body), bodyMax);
|
|
163
|
-
|
|
164
|
-
const fill = Math.max(0, innerW - plainLen(text));
|
|
165
|
-
pendingDiffOutput.push(`\x1b[90m│\x1b[0m ${text}${" ".repeat(fill)} \x1b[90m│\x1b[0m`);
|
|
144
|
+
pendingDiffOutput.push(`\x1b[90m${numStr} ${body}\x1b[0m`);
|
|
166
145
|
}
|
|
167
146
|
}
|
|
168
|
-
|
|
147
|
+
return { added, removed };
|
|
169
148
|
}
|
|
170
149
|
export function truncateToolOutput(output, maxChars = max_output_chars) {
|
|
171
150
|
if (output.length > maxChars) {
|
|
@@ -491,7 +470,6 @@ export function toolEditFile(pathName, oldString, newString, replaceAll = false)
|
|
|
491
470
|
const text = data.toString("utf-8");
|
|
492
471
|
const newline = detectNewline(text);
|
|
493
472
|
let match;
|
|
494
|
-
let normalized = false;
|
|
495
473
|
if (text.includes(oldString)) {
|
|
496
474
|
match = oldString;
|
|
497
475
|
}
|
|
@@ -499,7 +477,6 @@ export function toolEditFile(pathName, oldString, newString, replaceAll = false)
|
|
|
499
477
|
const norm = withNewlines(oldString, newline);
|
|
500
478
|
if (text.includes(norm)) {
|
|
501
479
|
match = norm;
|
|
502
|
-
normalized = true;
|
|
503
480
|
}
|
|
504
481
|
else {
|
|
505
482
|
const blocks = findWsBlocks(text, oldString);
|
|
@@ -508,7 +485,6 @@ export function toolEditFile(pathName, oldString, newString, replaceAll = false)
|
|
|
508
485
|
"(line endings and per-line leading/trailing whitespace are normalized for matching)");
|
|
509
486
|
}
|
|
510
487
|
match = blocks[0];
|
|
511
|
-
normalized = true;
|
|
512
488
|
}
|
|
513
489
|
}
|
|
514
490
|
const count = text.split(match).length - 1;
|
|
@@ -519,15 +495,17 @@ export function toolEditFile(pathName, oldString, newString, replaceAll = false)
|
|
|
519
495
|
const newContent = replaceAll
|
|
520
496
|
? text.split(match).join(insert)
|
|
521
497
|
: text.replace(match, insert);
|
|
522
|
-
displayDiff(pathName, text, newContent);
|
|
498
|
+
const summary = displayDiff(pathName, text, newContent);
|
|
523
499
|
try {
|
|
524
500
|
fs.writeFileSync(p, newContent, "utf-8");
|
|
525
501
|
}
|
|
526
502
|
catch (err) {
|
|
527
503
|
return `Error: ${err}`;
|
|
528
504
|
}
|
|
529
|
-
|
|
530
|
-
|
|
505
|
+
if (!summary)
|
|
506
|
+
return `Edited ${pathName}`;
|
|
507
|
+
return (`Added ${summary.added} line${summary.added !== 1 ? "s" : ""}, ` +
|
|
508
|
+
`removed ${summary.removed} line${summary.removed !== 1 ? "s" : ""}`);
|
|
531
509
|
}
|
|
532
510
|
// ---------------------------------------------------------------------------
|
|
533
511
|
// bash
|
|
@@ -651,7 +629,7 @@ function globMatch(name, pattern) {
|
|
|
651
629
|
.replace(/\?/g, ".");
|
|
652
630
|
return new RegExp(`^${regex}$`, "i").test(name);
|
|
653
631
|
}
|
|
654
|
-
function walkFiles(root, current, rel, parts, out) {
|
|
632
|
+
function walkFiles(root, current, rel, parts, out, depthLeft) {
|
|
655
633
|
let entries;
|
|
656
634
|
try {
|
|
657
635
|
entries = fs.readdirSync(current, { withFileTypes: true });
|
|
@@ -665,8 +643,10 @@ function walkFiles(root, current, rel, parts, out) {
|
|
|
665
643
|
if (entry.isDirectory()) {
|
|
666
644
|
if (ignoredDirs.has(name))
|
|
667
645
|
continue;
|
|
646
|
+
if (depthLeft <= 0)
|
|
647
|
+
continue;
|
|
668
648
|
rel.push(name);
|
|
669
|
-
walkFiles(root, path.join(current, name), rel, parts, out);
|
|
649
|
+
walkFiles(root, path.join(current, name), rel, parts, out, depthLeft - 1);
|
|
670
650
|
rel.pop();
|
|
671
651
|
}
|
|
672
652
|
else if (entry.isFile()) {
|
|
@@ -683,13 +663,13 @@ function walkFiles(root, current, rel, parts, out) {
|
|
|
683
663
|
}
|
|
684
664
|
}
|
|
685
665
|
}
|
|
686
|
-
function rglobPruned(base, pattern) {
|
|
666
|
+
function rglobPruned(base, pattern, depth = 12) {
|
|
687
667
|
const norm = pattern.replace(/\\/g, "/");
|
|
688
668
|
const parts = norm.split("/").filter((p) => p !== "" && p !== ".");
|
|
689
669
|
const hasDotDot = parts.includes("..");
|
|
690
670
|
if (hasDotDot) {
|
|
691
671
|
const out = [];
|
|
692
|
-
const walk = (dir) => {
|
|
672
|
+
const walk = (dir, depthLeft) => {
|
|
693
673
|
let entries;
|
|
694
674
|
try {
|
|
695
675
|
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
@@ -700,8 +680,8 @@ function rglobPruned(base, pattern) {
|
|
|
700
680
|
for (const e of entries) {
|
|
701
681
|
const full = path.join(dir, e.name);
|
|
702
682
|
if (e.isDirectory()) {
|
|
703
|
-
if (!ignoredDirs.has(e.name))
|
|
704
|
-
walk(full);
|
|
683
|
+
if (!ignoredDirs.has(e.name) && depthLeft > 0)
|
|
684
|
+
walk(full, depthLeft - 1);
|
|
705
685
|
}
|
|
706
686
|
else if (e.isFile()) {
|
|
707
687
|
out.push([full, fs.statSync(full).size]);
|
|
@@ -712,7 +692,7 @@ function rglobPruned(base, pattern) {
|
|
|
712
692
|
out.push([base, fs.statSync(base).size]);
|
|
713
693
|
}
|
|
714
694
|
else {
|
|
715
|
-
walk(base);
|
|
695
|
+
walk(base, depth);
|
|
716
696
|
}
|
|
717
697
|
return out;
|
|
718
698
|
}
|
|
@@ -724,17 +704,18 @@ function rglobPruned(base, pattern) {
|
|
|
724
704
|
if (!parts.length)
|
|
725
705
|
return [];
|
|
726
706
|
const out = [];
|
|
727
|
-
walkFiles(base, base, [], ["**", ...parts], out);
|
|
707
|
+
walkFiles(base, base, [], ["**", ...parts], out, depth);
|
|
728
708
|
return out;
|
|
729
709
|
}
|
|
730
|
-
export function toolGlob(pattern, pathName = ".", limit = 200) {
|
|
710
|
+
export function toolGlob(pattern, pathName = ".", limit = 200, depth = 12) {
|
|
731
711
|
const base = sanitizePath(pathName) || ".";
|
|
732
712
|
if (!fs.existsSync(base))
|
|
733
713
|
return `Error: path not found: ${pathName}`;
|
|
734
714
|
const lim = typeof limit === "number" ? limit : parseInt(String(limit), 10) || 200;
|
|
715
|
+
const dep = Math.max(0, typeof depth === "number" ? depth : parseInt(String(depth), 10) || 12);
|
|
735
716
|
let matches;
|
|
736
717
|
try {
|
|
737
|
-
matches = rglobPruned(base, pattern);
|
|
718
|
+
matches = rglobPruned(base, pattern, dep);
|
|
738
719
|
}
|
|
739
720
|
catch {
|
|
740
721
|
return `Error: path not found: ${pathName}`;
|
|
@@ -913,6 +894,10 @@ export const RESPONSES_TOOLS = [
|
|
|
913
894
|
type: "integer",
|
|
914
895
|
description: "Max number of matches to return (default 200)",
|
|
915
896
|
},
|
|
897
|
+
depth: {
|
|
898
|
+
type: "integer",
|
|
899
|
+
description: "Max directory depth to descend (default 12)",
|
|
900
|
+
},
|
|
916
901
|
},
|
|
917
902
|
required: ["pattern"],
|
|
918
903
|
},
|
package/dist/ui.js
CHANGED
|
@@ -556,7 +556,7 @@ export class Spinner {
|
|
|
556
556
|
draw() {
|
|
557
557
|
const text = this.render ? this.render() : "";
|
|
558
558
|
const icon = SPINNER_FRAMES[this.frame % SPINNER_FRAMES.length];
|
|
559
|
-
const rendered = `\x1b[36m${icon}\x1b[0m \x1b[90m${text}\x1b[0m`;
|
|
559
|
+
const rendered = `\x1b[1;36m${icon}\x1b[0m \x1b[90m${text}\x1b[0m`;
|
|
560
560
|
// Nothing changed on this tick -> do not rewrite the line (avoids flicker).
|
|
561
561
|
if (rendered === this.lastRendered)
|
|
562
562
|
return;
|