@oxecli/oxe 1.0.4 → 1.0.5

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 CHANGED
@@ -189,9 +189,12 @@ 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", false);
192
+ renderPanel("AI CODING AGENT", "", `Engine: Ready ${sid}`, false);
193
+ process.stdout.write("\n");
193
194
  process.stdout.write(`\x1b[2mResumed:\x1b[0m ${truncateLabel(rec["label"])}\n`);
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
+ process.stdout.write("\n");
196
+ 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`);
197
+ process.stdout.write("\n");
195
198
  renderPanel("Conversation history", "Restored");
196
199
  process.stdout.write("\n");
197
200
  if (this.story.length)
package/dist/config.js CHANGED
@@ -209,7 +209,7 @@ export async function loadOrPrompt() {
209
209
  };
210
210
  }
211
211
  /**
212
- * Prompt for a secret (API key) without echoing it to the terminal.
212
+ * Prompt for an API key, echoing what the user types.
213
213
  * Falls back to a plain readline read when stdin isn't a TTY (e.g. piped input).
214
214
  */
215
215
  export async function promptApiKey(prompt) {
@@ -262,7 +262,7 @@ export async function promptApiKey(prompt) {
262
262
  if (b < 32)
263
263
  continue;
264
264
  input += String.fromCharCode(b);
265
- process.stdout.write("*");
265
+ process.stdout.write(String.fromCharCode(b));
266
266
  }
267
267
  };
268
268
  const cleanup = () => {
package/dist/engine.js CHANGED
@@ -175,6 +175,7 @@ export class InferenceEngine {
175
175
  parallel_tool_calls: true,
176
176
  max_output_tokens,
177
177
  reasoning: { effort: this.reasoningEffort },
178
+ stream: true,
178
179
  stream_options: { include_usage: true },
179
180
  store: true,
180
181
  };
package/dist/ui.js CHANGED
@@ -392,13 +392,7 @@ export function renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor
392
392
  const cursorRow = row + 1;
393
393
  const cursorCol = col + prefix.length + 3;
394
394
  const totalRows = body.length + 2;
395
- let cmd = "";
396
- if (totalRows - 1 > cursorRow)
397
- cmd += `\x1b[${totalRows - 1 - cursorRow}A`;
398
- else if (cursorRow > totalRows - 1)
399
- cmd += `\x1b[${cursorRow - (totalRows - 1)}B`;
400
- cmd += `\r\x1b[${cursorCol}C`;
401
- return frame + cmd;
395
+ return { frame, cursorRow, cursorCol, totalRows };
402
396
  }
403
397
  export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
404
398
  return new Promise((resolve, reject) => {
@@ -425,19 +419,46 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
425
419
  process.stdin.setRawMode(true);
426
420
  process.stdin.resume();
427
421
  let done = false;
422
+ let lastCursorRow = 0;
423
+ let lastTotalRows = 0;
428
424
  const finish = (resolveVal) => {
429
425
  if (done)
430
426
  return;
431
427
  done = true;
432
428
  process.stdin.setRawMode(false);
433
- process.stdout.write("\r\x1b[K");
434
- process.stdout.write("\n");
429
+ // Erase the whole prompt box (which occupies `lastTotalRows` lines) so no
430
+ // frame borders are left behind, then leave the cursor on the box's top
431
+ // row (a blank line). That way the caller's single leading newline yields
432
+ // exactly ONE blank row before the echoed user prompt — never two.
433
+ process.stdout.write(`\x1b[${lastCursorRow}A`);
434
+ for (let i = 0; i < lastTotalRows; i++) {
435
+ process.stdout.write("\r\x1b[K");
436
+ if (i < lastTotalRows - 1)
437
+ process.stdout.write("\n");
438
+ }
439
+ // Cursor is now on the last box row; move back up to the box's top row.
440
+ if (lastTotalRows > 1)
441
+ process.stdout.write(`\x1b[${lastTotalRows - 1}A`);
435
442
  resolve(resolveVal);
436
443
  };
437
- const repaint = () => {
438
- const frame = renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor);
439
- process.stdout.write("\r\x1b[K");
440
- process.stdout.write(frame);
444
+ const repaint = (isFirst = false) => {
445
+ const { frame, cursorRow, cursorCol, totalRows } = renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor);
446
+ lastCursorRow = cursorRow;
447
+ lastTotalRows = totalRows;
448
+ const frameLines = frame.split("\n");
449
+ if (!isFirst) {
450
+ // Cursor currently sits at cursorRow (inside the box). Move to the top
451
+ // border, then clear+rewrite each line so old content is fully removed.
452
+ process.stdout.write(`\x1b[${cursorRow}A`);
453
+ }
454
+ for (let i = 0; i < frameLines.length; i++) {
455
+ process.stdout.write("\r\x1b[K" + frameLines[i]);
456
+ if (i < frameLines.length - 1)
457
+ process.stdout.write("\n");
458
+ }
459
+ // Reposition the cursor inside the box.
460
+ const fromBottom = totalRows - 1 - cursorRow;
461
+ process.stdout.write(`\x1b[${fromBottom}A\r\x1b[${cursorCol}C`);
441
462
  };
442
463
  const insert = (text) => {
443
464
  if (histIdx !== hist.length) {
@@ -559,7 +580,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
559
580
  }
560
581
  };
561
582
  process.stdin.on("keypress", onKeypress);
562
- repaint();
583
+ repaint(true);
563
584
  });
564
585
  }
565
586
  // ---------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxecli/oxe",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },