@oxecli/oxe 1.0.110 → 1.0.111
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 +17 -3
- package/dist/tools.js +18 -5
- package/package.json +1 -1
package/dist/engine.js
CHANGED
|
@@ -11,6 +11,10 @@ import { takePendingDiffOutput } from "./tools.js";
|
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
12
12
|
const tokenEstCache = new Map();
|
|
13
13
|
const tokenEstCacheMax = 4096;
|
|
14
|
+
/** Minimum time (ms) a tool's "Working"/"Running" status stays visible after
|
|
15
|
+
* the tool returns, so instant tools (write_file/edit_file) are still seen to
|
|
16
|
+
* stream when called before the result replaces the status line. */
|
|
17
|
+
const MIN_TOOL_STATUS_MS = 350;
|
|
14
18
|
export function estimateTokens(items) {
|
|
15
19
|
let total = 0;
|
|
16
20
|
for (const item of items) {
|
|
@@ -585,12 +589,14 @@ export class InferenceEngine {
|
|
|
585
589
|
for (const c of calls) {
|
|
586
590
|
this.queryCalledTool = true;
|
|
587
591
|
const started = toolCallLabel(c.name, c.arguments);
|
|
588
|
-
// Print the tool label the instant the
|
|
589
|
-
// "╰─
|
|
592
|
+
// Print the tool label the instant the tool starts, then show a
|
|
593
|
+
// "╰─ Working..." (file tools) or "╰─ Running..." (bash) dots line
|
|
594
|
+
// that streams while the tool runs and swaps to the real result.
|
|
590
595
|
dockAppendContent(`${started}\n`);
|
|
591
596
|
dockTransientStart("flush");
|
|
592
597
|
const toolSpinner = new Spinner();
|
|
593
|
-
toolSpinner.startDots(
|
|
598
|
+
toolSpinner.startDots(`\x1b[90m╰─\x1b[0m ${c.name === "bash" ? "Running" : "Working"}`);
|
|
599
|
+
const t0 = Date.now();
|
|
594
600
|
const rawResult = await this.runTool(c.name, c.arguments, this.activeAbort?.signal);
|
|
595
601
|
// A tool call was made, which interrupts any current working phase,
|
|
596
602
|
// so the next agent iteration may commit a fresh "Worked for …" block.
|
|
@@ -599,6 +605,14 @@ export class InferenceEngine {
|
|
|
599
605
|
toolSpinner.stop();
|
|
600
606
|
throw new Error("interrupt");
|
|
601
607
|
}
|
|
608
|
+
// Keep the status line streaming for at least MIN_TOOL_STATUS_MS so
|
|
609
|
+
// even instant tools (write_file/edit_file) visibly show their
|
|
610
|
+
// "Working" indicator when called, then swap to the result. The
|
|
611
|
+
// spinner's own timer animates the dots during this window.
|
|
612
|
+
const elapsed = Date.now() - t0;
|
|
613
|
+
if (elapsed < MIN_TOOL_STATUS_MS) {
|
|
614
|
+
await new Promise((res) => setTimeout(res, MIN_TOOL_STATUS_MS - elapsed));
|
|
615
|
+
}
|
|
602
616
|
const failed = toolOutputFailed(c.name, rawResult);
|
|
603
617
|
const action = formatToolResult(rawResult, failed);
|
|
604
618
|
const diff = takePendingDiffOutput();
|
package/dist/tools.js
CHANGED
|
@@ -31,6 +31,18 @@ function truncateDiffLine(line) {
|
|
|
31
31
|
}
|
|
32
32
|
return line;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Truncate a styled line to at most `maxVisible` visible characters and, if
|
|
36
|
+
* truncation occurred, append a visible ellipsis "…". The diff viewer must
|
|
37
|
+
* NEVER wrap a line onto a new row (that breaks the +/- column alignment), so
|
|
38
|
+
* every row is hard-truncated here; the ellipsis makes the truncation obvious.
|
|
39
|
+
*/
|
|
40
|
+
function truncateStyledEllipsis(text, maxVisible) {
|
|
41
|
+
if (plainLen(text) <= maxVisible)
|
|
42
|
+
return text;
|
|
43
|
+
const dot = maxVisible > 1 ? "…" : "";
|
|
44
|
+
return truncateStyled(text, Math.max(1, maxVisible - (dot ? 1 : 0))) + dot;
|
|
45
|
+
}
|
|
34
46
|
/**
|
|
35
47
|
* Recolor bracket syntax characters (`( ) [ ] { }`) inside an already-ANSI
|
|
36
48
|
* rendered string to `fg`, restoring the row's white base after each bracket.
|
|
@@ -76,8 +88,9 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
76
88
|
// tool result text above it ("╰─ Wrote N chars").
|
|
77
89
|
const ind = " ";
|
|
78
90
|
if (oldContent.length + newContent.length > max_diff_source_chars) {
|
|
79
|
-
|
|
80
|
-
`(diff hidden: exceeds ${max_diff_source_chars.toLocaleString()} char limit)
|
|
91
|
+
const hiddenMsg = `${pathName}: ${oldContent.length.toLocaleString()} chars -> ${newContent.length.toLocaleString()} chars ` +
|
|
92
|
+
`(diff hidden: exceeds ${max_diff_source_chars.toLocaleString()} char limit)`;
|
|
93
|
+
pendingDiffOutput.push(`\x1b[90m${ind}${truncateStyledEllipsis(hiddenMsg, Math.max(terminalWidth() - 2, 1))}\x1b[0m`);
|
|
81
94
|
return null;
|
|
82
95
|
}
|
|
83
96
|
const patch = structuredPatch(pathName, pathName, oldContent, newContent, "", "", { context: max_diff_context_lines });
|
|
@@ -164,7 +177,7 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
164
177
|
const gap = " ".repeat(numW);
|
|
165
178
|
for (const v of visible) {
|
|
166
179
|
if (v.kind === "~") {
|
|
167
|
-
const body =
|
|
180
|
+
const body = truncateStyledEllipsis(v.body, bodyMax);
|
|
168
181
|
pendingDiffOutput.push(`\x1b[90m${ind}${gap} ${body}\x1b[0m`);
|
|
169
182
|
continue;
|
|
170
183
|
}
|
|
@@ -181,7 +194,7 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
181
194
|
// background + white base after each token reset so both hold across
|
|
182
195
|
// the whole body.
|
|
183
196
|
const raw = highlightCodeLine(v.body);
|
|
184
|
-
const body =
|
|
197
|
+
const body = truncateStyledEllipsis(raw.replace(/\x1b\[0m/g, `\x1b[0m${bg}\x1b[97m`), bodyMax);
|
|
185
198
|
// Deleted rows: recolor bracket syntax to the same red as the line
|
|
186
199
|
// number (fg) so brackets match the row's deleted color. Added rows keep
|
|
187
200
|
// their green highlighter as-is.
|
|
@@ -197,7 +210,7 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
197
210
|
// lines (only the number gutter stays dim). highlightCodeLine resets to
|
|
198
211
|
// default after each token, so re-apply the base after every reset.
|
|
199
212
|
const base = v.kind === "\\" ? "\x1b[90m" : "\x1b[97m";
|
|
200
|
-
const body =
|
|
213
|
+
const body = truncateStyledEllipsis(raw.replace(/\x1b\[0m/g, `\x1b[0m${base}`), bodyMax);
|
|
201
214
|
pendingDiffOutput.push(`\x1b[90m${ind}${numStr} \x1b[0m${base}${body}\x1b[0m`);
|
|
202
215
|
}
|
|
203
216
|
}
|