@oxecli/oxe 1.0.11 → 1.0.13
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/cli.js +12 -6
- package/dist/engine.js +1 -2
- package/dist/oxe.js +10 -0
- package/dist/ui.js +40 -15
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -46,7 +46,13 @@ export class CLI {
|
|
|
46
46
|
showHelp() {
|
|
47
47
|
process.stdout.write("\n");
|
|
48
48
|
for (const [cmd, desc] of COMMAND_HELP) {
|
|
49
|
-
|
|
49
|
+
// The whole command column is bold; any `<arg>` placeholder (e.g. <n>,
|
|
50
|
+
// <level>) is additionally cyan — matching the original's
|
|
51
|
+
// `[bold cyan]<n>[/bold cyan]`. Pad based on the plain text length so the
|
|
52
|
+
// ANSI codes don't skew the column alignment.
|
|
53
|
+
const styled = cmd.replace(/(<[^>]+>)/g, "\x1b[36m$1\x1b[0m");
|
|
54
|
+
const pad = Math.max(18 - cmd.length, 0);
|
|
55
|
+
process.stdout.write(`\x1b[1m${styled}${" ".repeat(pad)}\x1b[0m\x1b[2m${desc}\x1b[0m\n`);
|
|
50
56
|
}
|
|
51
57
|
process.stdout.write("\n");
|
|
52
58
|
}
|
|
@@ -222,7 +228,7 @@ export class CLI {
|
|
|
222
228
|
if (lower === "/exit" || lower === "/quit") {
|
|
223
229
|
this.saveSession(engine);
|
|
224
230
|
await engine.cleanupStoredResponses();
|
|
225
|
-
process.stdout.write("\nClosing terminal session. Goodbye!\n");
|
|
231
|
+
process.stdout.write("\nClosing terminal session. Goodbye!\n\n");
|
|
226
232
|
break;
|
|
227
233
|
}
|
|
228
234
|
if (lower === "/help") {
|
|
@@ -286,7 +292,7 @@ export class CLI {
|
|
|
286
292
|
if (this.interruptPending) {
|
|
287
293
|
this.saveSession(engine);
|
|
288
294
|
await engine.cleanupStoredResponses();
|
|
289
|
-
process.stdout.write("\nClosing terminal session. Goodbye!\n");
|
|
295
|
+
process.stdout.write("\nClosing terminal session. Goodbye!\n\n");
|
|
290
296
|
break;
|
|
291
297
|
}
|
|
292
298
|
this.interruptPending = true;
|
|
@@ -314,9 +320,9 @@ export async function main() {
|
|
|
314
320
|
catch (err) {
|
|
315
321
|
if (err?.message === "interrupt" || err?.message === "eof") {
|
|
316
322
|
// cleanup() already moved to a fresh line; the leading newline below
|
|
317
|
-
// leaves that row as a blank
|
|
318
|
-
//
|
|
319
|
-
process.stdout.write("\nClosing terminal session. Goodbye!\n");
|
|
323
|
+
// leaves that row as a blank (one under the prompt), and the trailing
|
|
324
|
+
// double-newline leaves a blank row under the message too.
|
|
325
|
+
process.stdout.write("\nClosing terminal session. Goodbye!\n\n");
|
|
320
326
|
process.exit(0);
|
|
321
327
|
return;
|
|
322
328
|
}
|
package/dist/engine.js
CHANGED
|
@@ -2,7 +2,7 @@ import OpenAI from "openai";
|
|
|
2
2
|
import { max_output_tokens, max_empty_retries, max_agent_steps, max_context_tokens, context_overhead_margin, compact_keep_recent_turns, max_summary_source_chars, max_read_file_stored_chars, } from "./config.js";
|
|
3
3
|
import { SYSTEM_PROMPT } from "./system.js";
|
|
4
4
|
import { buildTools, truncateToolOutput, TOOL_IMPLEMENTATIONS } from "./tools.js";
|
|
5
|
-
import { mutedMarkdown, aiMarkdown, tickDuration, displayRows, safeCommitPoint, printAiChunk, formatToolAction, renderPanel, Spinner, hideCursor,
|
|
5
|
+
import { mutedMarkdown, aiMarkdown, tickDuration, displayRows, safeCommitPoint, printAiChunk, formatToolAction, renderPanel, Spinner, hideCursor, } from "./ui.js";
|
|
6
6
|
import { reportUsage } from "./api.js";
|
|
7
7
|
import { stripOrphanCalls, persistCompactionSummary, toolOutputFailed, } from "./sessions.js";
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
@@ -548,7 +548,6 @@ export class InferenceEngine {
|
|
|
548
548
|
}
|
|
549
549
|
finally {
|
|
550
550
|
this.inQuery = false;
|
|
551
|
-
showCursor();
|
|
552
551
|
if (stats["tokens"] > 0 && this.keyData) {
|
|
553
552
|
const userId = this.keyData["user_id"];
|
|
554
553
|
if (userId) {
|
package/dist/oxe.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { main } from "./cli.js";
|
|
2
2
|
export { main };
|
|
3
|
+
// The TUI keeps the terminal cursor hidden except inside a prompt field. Always
|
|
4
|
+
// restore it on exit so the shell isn't left with an invisible cursor.
|
|
5
|
+
process.on("exit", () => {
|
|
6
|
+
try {
|
|
7
|
+
process.stdout.write("\x1b[?25h");
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
/* ignore */
|
|
11
|
+
}
|
|
12
|
+
});
|
|
3
13
|
main().catch((err) => {
|
|
4
14
|
const msg = err?.message;
|
|
5
15
|
if (msg === "interrupt" || msg === "eof") {
|
package/dist/ui.js
CHANGED
|
@@ -588,6 +588,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
588
588
|
let done = false;
|
|
589
589
|
let lastCursorRow = 0;
|
|
590
590
|
let lastTotalRows = 0;
|
|
591
|
+
let prevFrameLines = null;
|
|
591
592
|
// Erase the prompt region: a leading blank line + the box. Cursor sits at
|
|
592
593
|
// lastCursorRow inside the box; move up to the box's top border, erase the
|
|
593
594
|
// box rows, then erase the leading blank line, leaving the cursor on that
|
|
@@ -609,7 +610,6 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
609
610
|
return;
|
|
610
611
|
done = true;
|
|
611
612
|
process.stdin.setRawMode(false);
|
|
612
|
-
showCursor();
|
|
613
613
|
clearBox();
|
|
614
614
|
process.stdin.removeListener("keypress", onKeypress);
|
|
615
615
|
process.stdin.pause();
|
|
@@ -620,9 +620,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
620
620
|
};
|
|
621
621
|
const repaint = (isFirst = false) => {
|
|
622
622
|
const { frame, cursorRow, cursorCol, totalRows } = renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor);
|
|
623
|
-
|
|
624
|
-
lastTotalRows = totalRows;
|
|
625
|
-
const frameLines = frame.split("\n");
|
|
623
|
+
const newLines = frame.split("\n");
|
|
626
624
|
if (isFirst) {
|
|
627
625
|
// The caller's content always ends with "\n", so the cursor sits at the
|
|
628
626
|
// start of a fresh (blank) line — that line is the leading blank
|
|
@@ -630,20 +628,47 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
630
628
|
// one line so the box starts below that blank; do NOT emit a second
|
|
631
629
|
// blank here (it caused a double gap above the box / on cancel).
|
|
632
630
|
process.stdout.write("\n");
|
|
631
|
+
for (let i = 0; i < newLines.length; i++) {
|
|
632
|
+
process.stdout.write(newLines[i]);
|
|
633
|
+
if (i < newLines.length - 1)
|
|
634
|
+
process.stdout.write("\n");
|
|
635
|
+
}
|
|
636
|
+
prevFrameLines = newLines;
|
|
637
|
+
lastCursorRow = cursorRow;
|
|
638
|
+
lastTotalRows = totalRows;
|
|
639
|
+
// Cursor sits on the bottom border line; move it up to the input row.
|
|
640
|
+
const up = totalRows - 1 - cursorRow;
|
|
641
|
+
process.stdout.write(`\x1b[${up}A\r\x1b[${cursorCol}C`);
|
|
642
|
+
return;
|
|
633
643
|
}
|
|
634
644
|
else {
|
|
635
|
-
// Cursor currently sits at
|
|
636
|
-
//
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
645
|
+
// Cursor currently sits at the previous input position (lastCursorRow
|
|
646
|
+
// inside the box). Move up to the top border, then rewrite ONLY the
|
|
647
|
+
// lines whose content actually changed, leaving the static borders
|
|
648
|
+
// untouched — this avoids the whole-box flicker on every keystroke.
|
|
649
|
+
process.stdout.write(`\x1b[${lastCursorRow}A\r`);
|
|
650
|
+
const oldLines = prevFrameLines ?? [];
|
|
651
|
+
const maxLen = Math.max(oldLines.length, newLines.length);
|
|
652
|
+
for (let i = 0; i < maxLen; i++) {
|
|
653
|
+
if (newLines[i] !== oldLines[i]) {
|
|
654
|
+
process.stdout.write("\r\x1b[K" + (newLines[i] ?? ""));
|
|
655
|
+
}
|
|
656
|
+
if (i < maxLen - 1)
|
|
657
|
+
process.stdout.write("\n");
|
|
658
|
+
}
|
|
659
|
+
// Cursor now sits at line (maxLen-1), column 0. Move it to the target
|
|
660
|
+
// input row (cursorRow), handling line-count changes in either direction.
|
|
661
|
+
const atLine = maxLen - 1;
|
|
662
|
+
if (atLine > cursorRow)
|
|
663
|
+
process.stdout.write(`\x1b[${atLine - cursorRow}A`);
|
|
664
|
+
else if (atLine < cursorRow)
|
|
665
|
+
process.stdout.write(`\x1b[${cursorRow - atLine}B`);
|
|
666
|
+
process.stdout.write(`\r\x1b[${cursorCol}C`);
|
|
667
|
+
prevFrameLines = newLines;
|
|
668
|
+
lastCursorRow = cursorRow;
|
|
669
|
+
lastTotalRows = totalRows;
|
|
670
|
+
return;
|
|
643
671
|
}
|
|
644
|
-
// Reposition the cursor inside the box.
|
|
645
|
-
const fromBottom = totalRows - 1 - cursorRow;
|
|
646
|
-
process.stdout.write(`\x1b[${fromBottom}A\r\x1b[${cursorCol}C`);
|
|
647
672
|
};
|
|
648
673
|
const insert = (text) => {
|
|
649
674
|
if (histIdx !== hist.length) {
|