@oxecli/oxe 1.0.55 → 1.0.57

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/engine.js CHANGED
@@ -43,7 +43,7 @@ export class InferenceEngine {
43
43
  keyData;
44
44
  client;
45
45
  workActive = false;
46
- workRows = 2;
46
+ workRows = 0;
47
47
  inQuery = false;
48
48
  activeAbort = null;
49
49
  interrupted = false;
@@ -403,7 +403,7 @@ export class InferenceEngine {
403
403
  return [conversation, false];
404
404
  const started = Date.now();
405
405
  const comp = new Spinner();
406
- comp.start("Compacting conversation `0s`");
406
+ comp.start(`Compacting conversation ${tickDuration(0)}`);
407
407
  const compTimer = setInterval(() => {
408
408
  comp.update(`Compacting conversation ${tickDuration((Date.now() - started) / 1000)}`);
409
409
  }, 100);
package/dist/ui.js CHANGED
@@ -334,11 +334,10 @@ export function aiMarkdown(text) {
334
334
  return markdownToAnsi(text);
335
335
  }
336
336
  export function mutedMarkdown(text) {
337
- const dimmed = text
337
+ return markdownToAnsi(text)
338
338
  .split("\n")
339
339
  .map((l) => `\x1b[2m${l}\x1b[0m`)
340
340
  .join("\n");
341
- return markdownToAnsi(dimmed);
342
341
  }
343
342
  // ---------------------------------------------------------------------------
344
343
  // Panel Rendering
@@ -377,15 +376,8 @@ function panelString(content, title = "", subtitle = "", expand = true, borderSt
377
376
  for (let i = 0; i < styledLines.length; i++) {
378
377
  const line = styledLines[i];
379
378
  const plain = plainLines[i] ?? "";
380
- if (plain.length > innerW) {
381
- // Truncate cleanly if single line overflows max box width
382
- const truncated = line.slice(0, innerW);
383
- out.push(`\x1b[${borderStyle}m│\x1b[0m ${truncated} \x1b[${borderStyle}m│\x1b[0m`);
384
- }
385
- else {
386
- const pad = Math.max(innerW - plain.length, 0);
387
- out.push(`\x1b[${borderStyle}m│\x1b[0m ${line}${" ".repeat(pad)} \x1b[${borderStyle}m│\x1b[0m`);
388
- }
379
+ const pad = Math.max(innerW - plain.length, 0);
380
+ out.push(`\x1b[${borderStyle}m│\x1b[0m ${line}${" ".repeat(pad)} \x1b[${borderStyle}m│\x1b[0m`);
389
381
  }
390
382
  const bottom = `╰${embed(subtitle, "center")}╯`;
391
383
  out.push(`\x1b[${borderStyle}m${bottom}\x1b[0m`);
@@ -830,60 +822,45 @@ export function renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor
830
822
  const totalRows = body.length + 2;
831
823
  return { frame, cursorRow, cursorCol, totalRows };
832
824
  }
833
- export function isNewlineKey(str, key) {
825
+ export function isShiftEnterKey(str, key) {
834
826
  if (!key)
835
827
  return false;
836
828
  const seq = key.sequence || str || "";
837
- const hasModifier = !!(key.shift || key.ctrl || key.meta);
838
- // Any modified Enter / Return / Linefeed / Ctrl+J
839
- if (hasModifier &&
829
+ if (key.shift &&
840
830
  (key.name === "return" ||
841
831
  key.name === "enter" ||
842
832
  key.name === "linefeed" ||
843
833
  seq === "\r" ||
844
- seq === "\n" ||
845
- (key.ctrl && key.name === "j"))) {
834
+ seq === "\n")) {
846
835
  return true;
847
836
  }
848
- // Kitty protocol: \x1b[13;<mod>u (mod 2=Shift, 3=Alt, 5=Ctrl, 6=Ctrl+Shift, etc.)
849
- if (/^\x1b\[13;([2-9]|\d{2,})u$/.test(seq))
850
- return true;
851
- // Legacy kitty/xterm: \x1b[13;<mod>~
852
- if (/^\x1b\[13;([2-9]|\d{2,})~$/.test(seq))
853
- return true;
854
- // Xterm modifyOtherKeys: \x1b[27;<mod>;13~
855
- if (/^\x1b\[27;([2-9]|\d{2,});13~$/.test(seq))
856
- return true;
857
- // Alt+Enter / Esc+Enter
858
- if (seq === "\x1b\r" ||
859
- seq === "\x1b\n" ||
860
- seq === "\x1b\x0d" ||
861
- seq === "\x1b\x0a") {
837
+ if (seq === "\x1b[13;2u" ||
838
+ seq === "\x1b[13;2~" ||
839
+ seq === "\x1b[13;2_" ||
840
+ seq === "\x1b[27;2;13~" ||
841
+ seq === "\x1bOM") {
862
842
  return true;
863
843
  }
864
- // F3 Shift decode in legacy Node
865
- if (key.name === "f3" && key.shift)
844
+ if (!key.ctrl && (str === "\n" || seq === "\n" || key.name === "linefeed")) {
866
845
  return true;
846
+ }
867
847
  return false;
868
848
  }
849
+ export const isNewlineKey = isShiftEnterKey;
869
850
  export function isSubmitEnterKey(str, key) {
870
851
  if (!key)
871
852
  return false;
872
- if (isNewlineKey(str, key))
853
+ if (isShiftEnterKey(str, key))
873
854
  return false;
874
855
  const seq = key.sequence || str || "";
875
- const isPlainEnterName = (key.name === "return" || key.name === "enter") &&
876
- !key.shift &&
877
- !key.ctrl &&
878
- !key.meta;
879
- if (isPlainEnterName)
880
- return true;
881
- if (seq === "\r" && !key.ctrl && !key.shift && !key.meta)
882
- return true;
883
- if (seq === "\x1b[13u" || seq === "\x1b[13;1u")
884
- return true;
885
- if (seq === "\x1b[27;1;13~")
856
+ if ((key.name === "return" ||
857
+ key.name === "enter" ||
858
+ seq === "\r" ||
859
+ seq === "\x1b[13u" ||
860
+ seq === "\x1b[13;1u") &&
861
+ !key.shift) {
886
862
  return true;
863
+ }
887
864
  return false;
888
865
  }
889
866
  export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
@@ -1017,6 +994,20 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1017
994
  }
1018
995
  cursor += text.length;
1019
996
  };
997
+ // A paste span is treated as a single atomic "block" only when it collapses
998
+ // to a marker (large pastes). Small inline pastes behave like normal text.
999
+ const spanCollapsed = (span) => {
1000
+ return shouldCollapsePaste(buffer.slice(span[0], span[1]));
1001
+ };
1002
+ const deleteWholeSpan = (span) => {
1003
+ const [start, end] = span;
1004
+ buffer = buffer.slice(0, start) + buffer.slice(end);
1005
+ const delta = start - end;
1006
+ pasteSpans = pasteSpans
1007
+ .filter(([s, e]) => s !== start || e !== end)
1008
+ .map(([s, e]) => (s >= end ? [s + delta, e + delta] : [s, e]));
1009
+ cursor = start;
1010
+ };
1020
1011
  const backspace = () => {
1021
1012
  if (cursor <= 0)
1022
1013
  return;
@@ -1025,14 +1016,8 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1025
1016
  histIdx = hist.length;
1026
1017
  }
1027
1018
  const containing = pasteSpans.find(([s, e]) => s < cursor && cursor <= e);
1028
- if (containing) {
1029
- const [start, end] = containing;
1030
- buffer = buffer.slice(0, start) + buffer.slice(end);
1031
- const delta = start - end;
1032
- pasteSpans = pasteSpans
1033
- .filter(([s, e]) => s !== start || e !== end)
1034
- .map(([s, e]) => (s >= end ? [s + delta, e + delta] : [s, e]));
1035
- cursor = start;
1019
+ if (containing && spanCollapsed(containing)) {
1020
+ deleteWholeSpan(containing);
1036
1021
  return;
1037
1022
  }
1038
1023
  const before = Array.from(buffer.slice(0, cursor));
@@ -1064,7 +1049,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1064
1049
  histIdx = hist.length;
1065
1050
  }
1066
1051
  const containing = pasteSpans.find(([s, e]) => s <= cursor && cursor < e);
1067
- if (containing) {
1052
+ if (containing && spanCollapsed(containing)) {
1068
1053
  const [start, end] = containing;
1069
1054
  buffer = buffer.slice(0, start) + buffer.slice(end);
1070
1055
  const delta = start - end;
@@ -1074,6 +1059,22 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1074
1059
  return;
1075
1060
  }
1076
1061
  buffer = buffer.slice(0, cursor) + buffer.slice(cursor + 1);
1062
+ const deletedAt = cursor;
1063
+ const adjusted = [];
1064
+ for (const [s, e] of pasteSpans) {
1065
+ if (deletedAt >= s && deletedAt < e) {
1066
+ const ne = e - 1;
1067
+ if (s < ne)
1068
+ adjusted.push([s, ne]);
1069
+ }
1070
+ else if (deletedAt < s) {
1071
+ adjusted.push([s - 1, e - 1]);
1072
+ }
1073
+ else {
1074
+ adjusted.push([s, e]);
1075
+ }
1076
+ }
1077
+ pasteSpans = adjusted.filter(([s, e]) => s < e);
1077
1078
  };
1078
1079
  const deleteWordBefore = () => {
1079
1080
  if (cursor <= 0)
@@ -1090,7 +1091,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1090
1091
  if (cursor <= 0)
1091
1092
  return;
1092
1093
  for (const [s, e] of pasteSpans) {
1093
- if (s < cursor && cursor <= e) {
1094
+ if (s < cursor && cursor <= e && spanCollapsed([s, e])) {
1094
1095
  cursor = s;
1095
1096
  return;
1096
1097
  }
@@ -1101,7 +1102,7 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
1101
1102
  if (cursor >= buffer.length)
1102
1103
  return;
1103
1104
  for (const [s, e] of pasteSpans) {
1104
- if (s <= cursor && cursor < e) {
1105
+ if (s <= cursor && cursor < e && spanCollapsed([s, e])) {
1105
1106
  cursor = e;
1106
1107
  return;
1107
1108
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxecli/oxe",
3
- "version": "1.0.55",
3
+ "version": "1.0.57",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },