@oxecli/oxe 1.0.0 → 1.0.2
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 +14 -4
- package/dist/oxe.js +5 -0
- package/dist/ui.js +65 -25
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -17,7 +17,7 @@ export class CLI {
|
|
|
17
17
|
promptHistory = [];
|
|
18
18
|
constructor() {
|
|
19
19
|
clearScreen();
|
|
20
|
-
renderPanel("AI CODING AGENT", "Engine: Ready");
|
|
20
|
+
renderPanel("AI CODING AGENT", "", "Engine: Ready");
|
|
21
21
|
process.stdout.write("\n");
|
|
22
22
|
this.config = null;
|
|
23
23
|
}
|
|
@@ -189,7 +189,7 @@ export class CLI {
|
|
|
189
189
|
this.sessionId = sid;
|
|
190
190
|
engine.reasoningEffort = String(rec["reasoning_effort"] ?? default_reasoning_effort);
|
|
191
191
|
clearScreen();
|
|
192
|
-
renderPanel(`AI CODING AGENT (resumed ${sid})`, "Engine: Ready");
|
|
192
|
+
renderPanel(`AI CODING AGENT (resumed ${sid})`, "", "Engine: Ready");
|
|
193
193
|
process.stdout.write(`\x1b[2mResumed:\x1b[0m ${truncateLabel(rec["label"])}\n`);
|
|
194
194
|
process.stdout.write(`\x1b[2m(${this.inputItems.length} items · ${estimateTokens(this.inputItems).toLocaleString()} tokens · Effort: \x1b[1;36m${engine.reasoningEffort}\x1b[0m\x1b[2m)\x1b[0m\n\n`);
|
|
195
195
|
renderPanel("Conversation history", "Restored");
|
|
@@ -226,7 +226,7 @@ export class CLI {
|
|
|
226
226
|
this.story = [];
|
|
227
227
|
this.sessionId = null;
|
|
228
228
|
clearScreen();
|
|
229
|
-
renderPanel("AI CODING AGENT", "Engine: Ready");
|
|
229
|
+
renderPanel("AI CODING AGENT", "", "Engine: Ready");
|
|
230
230
|
process.stdout.write("\n");
|
|
231
231
|
continue;
|
|
232
232
|
}
|
|
@@ -271,7 +271,17 @@ export class CLI {
|
|
|
271
271
|
export async function main() {
|
|
272
272
|
enableAnsi();
|
|
273
273
|
const app = new CLI();
|
|
274
|
-
|
|
274
|
+
let config;
|
|
275
|
+
try {
|
|
276
|
+
config = await loadOrPrompt();
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
if (err?.message === "interrupt" || err?.message === "eof") {
|
|
280
|
+
process.stdout.write("\nClosing terminal session. Goodbye!\n");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
throw err;
|
|
284
|
+
}
|
|
275
285
|
app.config = config;
|
|
276
286
|
const engine = new InferenceEngine(config);
|
|
277
287
|
try {
|
package/dist/oxe.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { main } from "./cli.js";
|
|
2
2
|
export { main };
|
|
3
3
|
main().catch((err) => {
|
|
4
|
+
const msg = err?.message;
|
|
5
|
+
if (msg === "interrupt" || msg === "eof") {
|
|
6
|
+
// Graceful exit on Ctrl+C / Ctrl+D — no stack trace.
|
|
7
|
+
process.exit(0);
|
|
8
|
+
}
|
|
4
9
|
console.error(err);
|
|
5
10
|
process.exit(1);
|
|
6
11
|
});
|
package/dist/ui.js
CHANGED
|
@@ -134,26 +134,47 @@ export function mutedMarkdown(text) {
|
|
|
134
134
|
// ---------------------------------------------------------------------------
|
|
135
135
|
// Panel
|
|
136
136
|
// ---------------------------------------------------------------------------
|
|
137
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Render a rich-style rounded panel: title in the top border, optional subtitle
|
|
139
|
+
* in the bottom border, content lines inside.
|
|
140
|
+
*/
|
|
141
|
+
export function renderPanel(content, title = "", subtitle = "", borderStyle = "90" // 90 = bright black (grey50)
|
|
142
|
+
) {
|
|
138
143
|
const w = terminalWidth();
|
|
139
144
|
const innerW = Math.max(w - 4, 10);
|
|
140
145
|
const styled = markupToAnsi(content);
|
|
146
|
+
const styledLines = styled.split("\n");
|
|
141
147
|
const plainLines = styled.replace(/\x1b\[[0-9;]*m/g, "").split("\n");
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
// Effective width used by the border (accounting for a title/subtitle side)
|
|
149
|
+
const borderW = innerW;
|
|
150
|
+
const topSegs = [];
|
|
151
|
+
topSegs.push("╭");
|
|
144
152
|
if (title) {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
console.log(`\x1b[90m|${titleStr}${" ".repeat(pad)}|`);
|
|
153
|
+
const t = ` ${title} `;
|
|
154
|
+
topSegs.push(`─${t}${"─".repeat(Math.max(borderW - t.length - 2, 0))}`);
|
|
148
155
|
}
|
|
149
|
-
|
|
156
|
+
else {
|
|
157
|
+
topSegs.push("─".repeat(borderW));
|
|
158
|
+
}
|
|
159
|
+
topSegs.push("╮");
|
|
160
|
+
process.stdout.write(`\x1b[${borderStyle}m${topSegs.join("")}\x1b[0m\n`);
|
|
150
161
|
for (let i = 0; i < styledLines.length; i++) {
|
|
151
162
|
const line = styledLines[i];
|
|
152
163
|
const plain = plainLines[i] ?? "";
|
|
153
|
-
const pad = Math.max(
|
|
154
|
-
|
|
164
|
+
const pad = Math.max(borderW - plain.length - 1, 0);
|
|
165
|
+
process.stdout.write(`\x1b[${borderStyle}m│\x1b[0m ${line}${" ".repeat(pad)} \x1b[${borderStyle}m│\x1b[0m\n`);
|
|
166
|
+
}
|
|
167
|
+
const bottomSegs = [];
|
|
168
|
+
bottomSegs.push("╰");
|
|
169
|
+
if (subtitle) {
|
|
170
|
+
const s = ` ${subtitle} `;
|
|
171
|
+
bottomSegs.push(`─${s}${"─".repeat(Math.max(borderW - s.length - 2, 0))}`);
|
|
155
172
|
}
|
|
156
|
-
|
|
173
|
+
else {
|
|
174
|
+
bottomSegs.push("─".repeat(borderW));
|
|
175
|
+
}
|
|
176
|
+
bottomSegs.push("╯");
|
|
177
|
+
process.stdout.write(`\x1b[${borderStyle}m${bottomSegs.join("")}\x1b[0m\n`);
|
|
157
178
|
}
|
|
158
179
|
// ---------------------------------------------------------------------------
|
|
159
180
|
// Durations
|
|
@@ -324,7 +345,10 @@ export function splitBlocks(buffer, pasteSpans) {
|
|
|
324
345
|
}
|
|
325
346
|
return segs;
|
|
326
347
|
}
|
|
327
|
-
function renderBufferWithCursor(buffer, pasteSpans, prefix, cursor) {
|
|
348
|
+
function renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor) {
|
|
349
|
+
const w = terminalWidth();
|
|
350
|
+
const innerW = Math.max(w - 4, 10);
|
|
351
|
+
const border = "─".repeat(innerW);
|
|
328
352
|
const [row, col] = cursorLineCol(buffer, cursor);
|
|
329
353
|
const segs = splitBlocks(buffer, pasteSpans);
|
|
330
354
|
let display = "";
|
|
@@ -334,23 +358,39 @@ function renderBufferWithCursor(buffer, pasteSpans, prefix, cursor) {
|
|
|
334
358
|
display += " ";
|
|
335
359
|
display += kind === "collapsed" ? `\x1b[1m\x1b[36m${disp}\x1b[0m` : disp;
|
|
336
360
|
}
|
|
337
|
-
const lines = display.split("\n");
|
|
338
361
|
const prefixStr = `\x1b[1m${prefix}\x1b[0m `;
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
362
|
+
const innerLines = (prefixStr + display).split("\n");
|
|
363
|
+
// Build the panel lines, each padded to innerW.
|
|
364
|
+
const lines = [];
|
|
365
|
+
for (const l of innerLines) {
|
|
366
|
+
const plain = l.replace(/\x1b\[[0-9;]*m/g, "");
|
|
367
|
+
const pad = Math.max(innerW - 1 - plain.length, 0);
|
|
368
|
+
lines.push(`\x1b[90m│\x1b[0m ${l}${" ".repeat(pad)} \x1b[90m│\x1b[0m`);
|
|
369
|
+
}
|
|
370
|
+
// Placeholder row when empty
|
|
371
|
+
if (!buffer) {
|
|
372
|
+
const ph = `\x1b[2m${PROMPT_PLACEHOLDER}\x1b[0m`;
|
|
373
|
+
const pad = Math.max(innerW - 1 - PROMPT_PLACEHOLDER.length, 0);
|
|
374
|
+
lines.push(`\x1b[90m│\x1b[0m ${ph}${" ".repeat(pad)} \x1b[90m│\x1b[0m`);
|
|
375
|
+
}
|
|
376
|
+
const frame = [
|
|
377
|
+
`\x1b[90m┌─${label}─${border.slice(label.length + 2)}┐\x1b[0m`,
|
|
378
|
+
...lines,
|
|
379
|
+
`\x1b[90m└${border}┘\x1b[0m`,
|
|
380
|
+
].join("\n");
|
|
381
|
+
// Compute where the cursor should be placed.
|
|
344
382
|
let cursorRow = row;
|
|
345
383
|
let cursorCol = col + (row === 0 ? prefix.length + 1 : 0);
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
384
|
+
// +1 row for the top border.
|
|
385
|
+
cursorRow += 1;
|
|
386
|
+
const totalRows = frame.split("\n").length;
|
|
349
387
|
let cmd = "";
|
|
350
|
-
if (
|
|
351
|
-
cmd += `\x1b[${
|
|
352
|
-
|
|
353
|
-
|
|
388
|
+
if (totalRows - 1 > cursorRow)
|
|
389
|
+
cmd += `\x1b[${totalRows - 1 - cursorRow}A`;
|
|
390
|
+
else if (cursorRow > totalRows - 1)
|
|
391
|
+
cmd += `\x1b[${cursorRow - (totalRows - 1)}B`;
|
|
392
|
+
cmd += `\r\x1b[${cursorCol + 2}C`;
|
|
393
|
+
return frame + cmd;
|
|
354
394
|
}
|
|
355
395
|
export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
356
396
|
return new Promise((resolve, reject) => {
|
|
@@ -387,7 +427,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
|
|
|
387
427
|
resolve(resolveVal);
|
|
388
428
|
};
|
|
389
429
|
const repaint = () => {
|
|
390
|
-
const frame = renderBufferWithCursor(buffer, pasteSpans, prefix, cursor);
|
|
430
|
+
const frame = renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor);
|
|
391
431
|
process.stdout.write("\r\x1b[K");
|
|
392
432
|
process.stdout.write(frame);
|
|
393
433
|
};
|