@oxecli/oxe 1.0.71 → 1.0.73
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 +6 -26
- package/dist/config.js +2 -2
- package/dist/tools.js +60 -30
- package/dist/ui.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { loadOrPrompt, default_reasoning_effort,
|
|
4
|
+
import { loadOrPrompt, default_reasoning_effort, max_action_chars, max_resume_history_items, runtimeOsSummary, } from "./config.js";
|
|
5
5
|
import { InferenceEngine, estimateTokens } from "./engine.js";
|
|
6
6
|
import { saveSession, loadSession, listSessions, nextSessionId, conversationLabel, COMMAND_HELP, stripOrphanCalls, toolOutputFailed, } from "./sessions.js";
|
|
7
7
|
import { clearScreen, enableAnsi, askBottomPrompt, userDisplayText, aiMarkdown, mutedMarkdown, messageText, formatToolAction, truncateEllipsis, renderPanel, renderTableString, enableRawStdin, disableRawStdin, waitRawKey, } from "./ui.js";
|
|
@@ -24,32 +24,12 @@ export class CLI {
|
|
|
24
24
|
this.renderHeader();
|
|
25
25
|
this.config = null;
|
|
26
26
|
}
|
|
27
|
-
renderHeader(
|
|
27
|
+
renderHeader() {
|
|
28
28
|
const version = packageInfo.version ?? "unknown";
|
|
29
|
-
const
|
|
30
|
-
const centeredCell = (value, render) => {
|
|
31
|
-
const left = Math.max(0, Math.floor((cellWidth - value.length) / 2));
|
|
32
|
-
const right = Math.max(0, cellWidth - value.length - left);
|
|
33
|
-
return " ".repeat(left) + render + " ".repeat(right);
|
|
34
|
-
};
|
|
35
|
-
const labelCell = (label) => {
|
|
36
|
-
return centeredCell(label, `[dim]${label}[/dim]`);
|
|
37
|
-
};
|
|
38
|
-
const valueCell = (value, color) => {
|
|
39
|
-
return centeredCell(value, `[bold ${color}]${value}[/bold ${color}]`);
|
|
40
|
-
};
|
|
41
|
-
const description = "A focused terminal workspace for building and shipping software.";
|
|
29
|
+
const description = "A focused terminal workspace for building and shipping.";
|
|
42
30
|
renderPanel("[bold white]Terminal Coding Agent[/bold white]\n" +
|
|
43
31
|
`[dim]${description}[/dim]\n\n` +
|
|
44
|
-
|
|
45
|
-
labelCell("Model") +
|
|
46
|
-
labelCell("Status") +
|
|
47
|
-
"\n" +
|
|
48
|
-
valueCell("", "cyan") +
|
|
49
|
-
valueCell(model, "cyan") +
|
|
50
|
-
valueCell("Ready", "green") +
|
|
51
|
-
"\n\n" +
|
|
52
|
-
`[dim]Environment: ${runtimeOsSummary()}[/dim]`, `\x1b[1;37mOxe\x1b[90m \x1b[1;36mv${version}\x1b[90m`, "Type /help for commands · Ctrl+C to interrupt", false, "90", "left");
|
|
32
|
+
`[dim]Environment: ${runtimeOsSummary()}[/dim]`, `\x1b[1;37mOxe\x1b[90m \x1b[1;36mv${version}\x1b[90m`, "Type /help for commands · Ctrl+C to interrupt", true, "90", "left");
|
|
53
33
|
}
|
|
54
34
|
saveSession(engine) {
|
|
55
35
|
if (!this.inputItems.length)
|
|
@@ -370,7 +350,7 @@ export class CLI {
|
|
|
370
350
|
this.sessionId = sid;
|
|
371
351
|
engine.reasoningEffort = String(rec["reasoning_effort"] ?? default_reasoning_effort);
|
|
372
352
|
clearScreen();
|
|
373
|
-
this.renderHeader(
|
|
353
|
+
this.renderHeader();
|
|
374
354
|
process.stdout.write("\n");
|
|
375
355
|
process.stdout.write(`\x1b[90mResumed:\x1b[0m \x1b[1m${truncateLabel(rec["label"])}\x1b[0m\n`);
|
|
376
356
|
process.stdout.write(`\x1b[90m(${this.inputItems.length} items · ${estimateTokens(this.inputItems).toLocaleString()} tokens)\x1b[0m\n\n`);
|
|
@@ -409,7 +389,7 @@ export class CLI {
|
|
|
409
389
|
this.story = [];
|
|
410
390
|
this.sessionId = null;
|
|
411
391
|
clearScreen();
|
|
412
|
-
this.renderHeader(
|
|
392
|
+
this.renderHeader();
|
|
413
393
|
continue;
|
|
414
394
|
}
|
|
415
395
|
if (lower.startsWith("/resume")) {
|
package/dist/config.js
CHANGED
|
@@ -156,8 +156,8 @@ export async function loadOrPrompt() {
|
|
|
156
156
|
process.stdout.write("\n");
|
|
157
157
|
renderPanel("[bold white]Oxe Desktop Authentication[/bold white]\n\n" +
|
|
158
158
|
`[dim]Only valid Oxe API keys (starting with [bold cyan]${OXE_KEY_PREFIX}[/bold cyan])\n` +
|
|
159
|
-
"generated on your Oxe dashboard are authorized
|
|
160
|
-
"Get your key at: [bold underline]http://localhost:5173/dashboard/api-keys[/bold underline][/dim]", "Oxe Cloud Access", "",
|
|
159
|
+
"generated on your Oxe dashboard are authorized.\n\n" +
|
|
160
|
+
"Get your key at: [bold underline]http://localhost:5173/dashboard/api-keys[/bold underline][/dim]", "Oxe Cloud Access", "", true, "90", "left");
|
|
161
161
|
process.stdout.write("\n");
|
|
162
162
|
api_key = await promptApiKey("Enter Oxe API Key: ");
|
|
163
163
|
if (!api_key) {
|
package/dist/tools.js
CHANGED
|
@@ -4,7 +4,7 @@ import { execFile, spawn } from "node:child_process";
|
|
|
4
4
|
import { structuredPatch } from "diff";
|
|
5
5
|
import { max_diff_source_chars, max_diff_lines, max_diff_context_lines, max_diff_line_chars, max_read_line_chars, max_read_file_bytes, max_read_lines, max_output_chars, max_bash_timeout_seconds, max_grep_file_bytes, strict_max_properties, ignoredDirs, } from "./config.js";
|
|
6
6
|
import { toolLoadSkill } from "./skills.js";
|
|
7
|
-
import { truncateStyled, plainLen, terminalWidth } from "./ui.js";
|
|
7
|
+
import { truncateStyled, plainLen, terminalWidth, highlightCodeLine } from "./ui.js";
|
|
8
8
|
export { toolLoadSkill };
|
|
9
9
|
// ---------------------------------------------------------------------------
|
|
10
10
|
// Path sanitization helper
|
|
@@ -49,13 +49,26 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
49
49
|
const patch = structuredPatch(pathName, pathName, oldContent, newContent, "", "", { context: max_diff_context_lines });
|
|
50
50
|
const contentLines = [];
|
|
51
51
|
for (const hunk of patch.hunks) {
|
|
52
|
+
let oldNum = hunk.oldStart;
|
|
53
|
+
let newNum = hunk.newStart;
|
|
52
54
|
for (const l of hunk.lines) {
|
|
53
|
-
if (l.startsWith("
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
else
|
|
58
|
-
contentLines.push({ line: l, kind: "
|
|
55
|
+
if (l.startsWith("\\")) {
|
|
56
|
+
// "" meta line: no line numbers.
|
|
57
|
+
contentLines.push({ line: l, kind: "\\", oldNum: null, newNum: null });
|
|
58
|
+
}
|
|
59
|
+
else if (l.startsWith("+")) {
|
|
60
|
+
contentLines.push({ line: l, kind: "+", oldNum: null, newNum });
|
|
61
|
+
newNum++;
|
|
62
|
+
}
|
|
63
|
+
else if (l.startsWith("-")) {
|
|
64
|
+
contentLines.push({ line: l, kind: "-", oldNum, newNum: null });
|
|
65
|
+
oldNum++;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
contentLines.push({ line: l, kind: " ", oldNum, newNum });
|
|
69
|
+
oldNum++;
|
|
70
|
+
newNum++;
|
|
71
|
+
}
|
|
59
72
|
}
|
|
60
73
|
}
|
|
61
74
|
const added = contentLines.filter((c) => c.kind === "+").length;
|
|
@@ -69,14 +82,17 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
69
82
|
if (!run.length)
|
|
70
83
|
return;
|
|
71
84
|
const kind = run[0].kind;
|
|
72
|
-
const limit = kind === " " ? max_diff_context_lines : max_diff_lines;
|
|
85
|
+
const limit = kind === " " || kind === "\\" ? max_diff_context_lines : max_diff_lines;
|
|
73
86
|
const hidden = run.length - limit;
|
|
74
|
-
for (const r of run.slice(0, limit))
|
|
75
|
-
shown.push({ kind, line: truncateDiffLine(r.line) });
|
|
87
|
+
for (const r of run.slice(0, limit)) {
|
|
88
|
+
shown.push({ kind, line: truncateDiffLine(r.line), oldNum: r.oldNum, newNum: r.newNum });
|
|
89
|
+
}
|
|
76
90
|
if (hidden > 0) {
|
|
77
91
|
shown.push({
|
|
78
92
|
kind: "~",
|
|
79
93
|
line: `… (${hidden} ${hidden === 1 ? "line" : "lines"} of diff hidden) …`,
|
|
94
|
+
oldNum: null,
|
|
95
|
+
newNum: null,
|
|
80
96
|
});
|
|
81
97
|
}
|
|
82
98
|
run = [];
|
|
@@ -91,20 +107,28 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
91
107
|
flush();
|
|
92
108
|
// Build the lines, stripping the leading + / - / space marker for display.
|
|
93
109
|
// Summary lines ("~") are already plain text and are kept whole.
|
|
94
|
-
const visible = shown.map(({ kind, line }) => {
|
|
110
|
+
const visible = shown.map(({ kind, line, oldNum, newNum }) => {
|
|
95
111
|
if (kind === "~")
|
|
96
|
-
return { kind, body: line };
|
|
97
|
-
const k = line[0] === "+" ? "+" : line[0] === "-" ? "-" : " ";
|
|
98
|
-
return { kind: k, body: line.slice(1) };
|
|
112
|
+
return { kind, body: line, oldNum, newNum };
|
|
113
|
+
const k = line[0] === "+" ? "+" : line[0] === "-" ? "-" : line[0] === "\\" ? "\\" : " ";
|
|
114
|
+
return { kind: k, body: line.slice(1), oldNum, newNum };
|
|
99
115
|
});
|
|
100
|
-
// A "… (N lines hidden) …" summary line is neutral context.
|
|
101
116
|
const termW = terminalWidth();
|
|
117
|
+
let maxNum = 1;
|
|
118
|
+
for (const v of visible) {
|
|
119
|
+
if (v.oldNum)
|
|
120
|
+
maxNum = Math.max(maxNum, v.oldNum);
|
|
121
|
+
if (v.newNum)
|
|
122
|
+
maxNum = Math.max(maxNum, v.newNum);
|
|
123
|
+
}
|
|
124
|
+
const numW = Math.max(String(maxNum).length, 2);
|
|
102
125
|
let contentW = 0;
|
|
103
126
|
for (const v of visible) {
|
|
104
|
-
|
|
127
|
+
const len = v.kind === "~" ? plainLen(v.body) : numW + 1 + 2 + plainLen(v.body);
|
|
128
|
+
contentW = Math.max(contentW, len);
|
|
105
129
|
}
|
|
106
130
|
const headerPlain = `${pathName} +${added} -${removed}`;
|
|
107
|
-
const boxW = Math.min(Math.max(contentW, plainLen(headerPlain)
|
|
131
|
+
const boxW = Math.min(Math.max(contentW + 6, plainLen(headerPlain) + 6), Math.max(termW - 2, 20));
|
|
108
132
|
const innerW = Math.max(boxW - 4, 1);
|
|
109
133
|
const maxPath = Math.max(10, boxW - 2 - plainLen(` +${added} -${removed}`) - 3);
|
|
110
134
|
let pathDisp = pathName;
|
|
@@ -114,26 +138,32 @@ function displayDiff(pathName, oldContent, newContent) {
|
|
|
114
138
|
const headerStr = `─ ${header} `;
|
|
115
139
|
const top = `╭${headerStr}${"─".repeat(Math.max(0, boxW - 2 - plainLen(headerStr)))}╮`;
|
|
116
140
|
pendingDiffOutput.push(`\x1b[90m${top}\x1b[0m`);
|
|
141
|
+
const bodyMax = Math.max(innerW - numW - 3, 1);
|
|
142
|
+
const gap = " ".repeat(numW);
|
|
117
143
|
for (const v of visible) {
|
|
118
|
-
let line;
|
|
119
144
|
if (v.kind === "~") {
|
|
120
145
|
const body = truncateStyled(v.body, innerW - 2);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
line = `\x1b[32m+ ${body}\x1b[0m`;
|
|
146
|
+
const text = `\x1b[90m${gap} ${body}\x1b[0m`;
|
|
147
|
+
const fill = Math.max(0, innerW - plainLen(text));
|
|
148
|
+
pendingDiffOutput.push(`\x1b[90m│\x1b[0m ${text}${" ".repeat(fill)} \x1b[90m│\x1b[0m`);
|
|
149
|
+
continue;
|
|
126
150
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
151
|
+
const num = v.kind === "+" ? v.newNum : v.oldNum;
|
|
152
|
+
const numStr = num ? String(num).padStart(numW, " ") : gap;
|
|
153
|
+
if (v.kind === "+" || v.kind === "-") {
|
|
154
|
+
const color = v.kind === "+" ? "\x1b[32m" : "\x1b[31m";
|
|
155
|
+
const body = truncateStyled(v.body, bodyMax);
|
|
156
|
+
const text = `${numStr} ${v.kind === "+" ? "+ " : "- "}${body}`;
|
|
157
|
+
const fill = Math.max(0, innerW - plainLen(text));
|
|
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`);
|
|
130
160
|
}
|
|
131
161
|
else {
|
|
132
|
-
const body = truncateStyled(v.body
|
|
133
|
-
|
|
162
|
+
const body = truncateStyled(v.kind === "\\" ? v.body : highlightCodeLine(v.body), bodyMax);
|
|
163
|
+
const text = `\x1b[90m${numStr} ${body}\x1b[0m`;
|
|
164
|
+
const fill = Math.max(0, innerW - plainLen(text));
|
|
165
|
+
pendingDiffOutput.push(`\x1b[90m│\x1b[0m ${text}${" ".repeat(fill)} \x1b[90m│\x1b[0m`);
|
|
134
166
|
}
|
|
135
|
-
const fill = Math.max(0, innerW - plainLen(line));
|
|
136
|
-
pendingDiffOutput.push(`\x1b[90m│\x1b[0m ${line}${" ".repeat(fill)} \x1b[90m│\x1b[0m`);
|
|
137
167
|
}
|
|
138
168
|
pendingDiffOutput.push(`\x1b[90m╰${"─".repeat(boxW - 2)}╯\x1b[0m`);
|
|
139
169
|
}
|
package/dist/ui.js
CHANGED
|
@@ -153,7 +153,7 @@ const KEYWORDS = new Set([
|
|
|
153
153
|
"lambda", "with", "as", "yield", "pass", "None", "True", "False", "null",
|
|
154
154
|
"undefined", "true", "false", "fn", "struct", "pub", "impl", "mut", "use",
|
|
155
155
|
]);
|
|
156
|
-
function highlightCodeLine(line, _lang = "") {
|
|
156
|
+
export function highlightCodeLine(line, _lang = "") {
|
|
157
157
|
if (!line)
|
|
158
158
|
return "";
|
|
159
159
|
if (/^\s*(\/\/|#|\/\*)/.test(line)) {
|