@oxecli/oxe 1.0.23 → 1.0.24

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
@@ -319,7 +319,7 @@ export class CLI {
319
319
  this.sessionId = sid;
320
320
  engine.reasoningEffort = String(rec["reasoning_effort"] ?? default_reasoning_effort);
321
321
  clearScreen();
322
- renderPanel("AI CODING AGENT", "", `Engine: Ready ${sid}`, false);
322
+ renderPanel("AI CODING AGENT", "", "Engine: Ready", false);
323
323
  process.stdout.write("\n");
324
324
  process.stdout.write(`\x1b[2mResumed:\x1b[0m ${truncateLabel(rec["label"])}\n`);
325
325
  process.stdout.write("\n");
package/dist/ui.js CHANGED
@@ -730,6 +730,8 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
730
730
  let draft = null;
731
731
  let bracketedPaste = false;
732
732
  let bracketedPasteBuffer = "";
733
+ let pasteBurst = false;
734
+ let pasteBurstTimer = null;
733
735
  readline.emitKeypressEvents(process.stdin);
734
736
  if (process.stdin.isTTY) {
735
737
  process.stdin.setRawMode(true);
@@ -765,6 +767,8 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
765
767
  return;
766
768
  done = true;
767
769
  process.stdin.setRawMode(false);
770
+ if (pasteBurstTimer)
771
+ clearTimeout(pasteBurstTimer);
768
772
  clearBox();
769
773
  process.stdin.removeListener("keypress", onKeypress);
770
774
  process.stdin.pause();
@@ -865,6 +869,20 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
865
869
  draft = { buffer, cursor, spans: pasteSpans.slice() };
866
870
  histIdx = hist.length;
867
871
  }
872
+ // A collapsed paste is one editable unit. Backspace removes the entire
873
+ // pasted block, matching the Python prompt rather than deleting only its
874
+ // final character.
875
+ const containing = pasteSpans.find(([s, e]) => s < cursor && cursor <= e);
876
+ if (containing) {
877
+ const [start, end] = containing;
878
+ buffer = buffer.slice(0, start) + buffer.slice(end);
879
+ const delta = start - end;
880
+ pasteSpans = pasteSpans
881
+ .filter(([s, e]) => s !== start || e !== end)
882
+ .map(([s, e]) => (s >= end ? [s + delta, e + delta] : [s, e]));
883
+ cursor = start;
884
+ return;
885
+ }
868
886
  // remove one grapheme before cursor
869
887
  const before = Array.from(buffer.slice(0, cursor));
870
888
  before.pop();
@@ -1060,6 +1078,15 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1060
1078
  }
1061
1079
  return true;
1062
1080
  };
1081
+ const markPasteBurst = () => {
1082
+ pasteBurst = true;
1083
+ if (pasteBurstTimer)
1084
+ clearTimeout(pasteBurstTimer);
1085
+ pasteBurstTimer = setTimeout(() => {
1086
+ pasteBurst = false;
1087
+ pasteBurstTimer = null;
1088
+ }, 90);
1089
+ };
1063
1090
  const onKeypress = (str, key) => {
1064
1091
  if (consumeBracketedPaste(str, key))
1065
1092
  return;
@@ -1071,6 +1098,15 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1071
1098
  settle(new Error("eof"), true);
1072
1099
  return;
1073
1100
  }
1101
+ // Any modified Enter (Shift/Ctrl+Enter) inserts a newline. This check
1102
+ // must happen before plain submit detection because some terminals expose
1103
+ // Shift+Enter as `return` while keeping the modifier only in the escape
1104
+ // sequence.
1105
+ if (isNewlineKey(key) || (pasteBurst && isSubmitEnterKey(key))) {
1106
+ insert("\n");
1107
+ repaint();
1108
+ return;
1109
+ }
1074
1110
  // Plain Enter submits; any modified Enter (Shift/Ctrl+Enter) inserts a
1075
1111
  // newline, mirroring the Python original's _read_input_event (which maps
1076
1112
  // \x1b[13;2u / \x1b[13;5u / Shift+\r to "\n").
@@ -1080,11 +1116,6 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1080
1116
  }
1081
1117
  return;
1082
1118
  }
1083
- if (isNewlineKey(key)) {
1084
- insert("\n");
1085
- repaint();
1086
- return;
1087
- }
1088
1119
  if (key && key.name === "backspace") {
1089
1120
  backspace();
1090
1121
  repaint();
@@ -1123,7 +1154,10 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1123
1154
  if (str) {
1124
1155
  // Multi-char sequence = a paste (single-char typed keys arrive one per
1125
1156
  // event). Tag it so the prompt box collapses it when it meets the rules.
1126
- insert(str, str.length > 1);
1157
+ const isPaste = str.length > 1;
1158
+ insert(str.replace(/\r\n/g, "\n").replace(/\r/g, "\n"), isPaste);
1159
+ if (isPaste)
1160
+ markPasteBurst();
1127
1161
  repaint();
1128
1162
  }
1129
1163
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxecli/oxe",
3
- "version": "1.0.23",
3
+ "version": "1.0.24",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },