xgen-dex-cli 1.7.1 → 1.7.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.
@@ -288,7 +288,7 @@ import { Box as Box2, Text as Text2 } from "ink";
288
288
 
289
289
  // src/tui/ime-text-input.tsx
290
290
  import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
291
- import { Box, Text, useCursor, useInput, useStdin } from "ink";
291
+ import { Box, Text, useCursor, useInput } from "ink";
292
292
  import stringWidth2 from "string-width";
293
293
 
294
294
  // src/tui/terminal-input.ts
@@ -504,67 +504,6 @@ function backspace(session) {
504
504
  };
505
505
  }
506
506
 
507
- // src/tui/kitty.ts
508
- var ESC = "\x1B";
509
- var QUERY = `${ESC}[?u`;
510
- var KEY_CODES = {
511
- 57358: "capslock",
512
- 57449: "rightalt"
513
- };
514
- var CAPS_LOCK_BIT = 64;
515
- function parseKeyEvents(chunk) {
516
- const events = [];
517
- const pattern = /\u001B\[(\d+)(?::\d+)*(?:;(\d+)(?::(\d+))?)?(?:;[\d:]*)?u/g;
518
- for (const match of chunk.matchAll(pattern)) {
519
- const code = Number(match[1]);
520
- const modifiers = match[2] ? Number(match[2]) - 1 : 0;
521
- events.push({
522
- name: KEY_CODES[code],
523
- // eslint-disable-next-line no-bitwise
524
- capsLock: (modifiers & CAPS_LOCK_BIT) !== 0,
525
- eventType: match[3] ? Number(match[3]) : 1
526
- });
527
- }
528
- return events;
529
- }
530
- function knownKittyTerminal(env = process.env) {
531
- if (env.KITTY_WINDOW_ID) return true;
532
- if (env.GHOSTTY_RESOURCES_DIR) return true;
533
- const term = (env.TERM ?? "").toLowerCase();
534
- if (term === "xterm-kitty" || term === "xterm-ghostty" || term.includes("foot")) return true;
535
- const program = (env.TERM_PROGRAM ?? "").toLowerCase();
536
- return program === "wezterm" || program === "ghostty" || program === "kitty";
537
- }
538
- async function supportsKittyKeyboard(streams, timeoutMs = 200, env = process.env) {
539
- if (env.DEX_NO_KITTY === "1") return false;
540
- if (!streams.stdout.isTTY || !streams.isTTY) return false;
541
- if (knownKittyTerminal(env)) return true;
542
- const wasRaw = streams.stdin.isRaw === true;
543
- const wasPaused = !wasRaw;
544
- streams.stdin.setRawMode?.(true);
545
- streams.stdin.resume?.();
546
- return new Promise((resolve) => {
547
- let settled = false;
548
- let seen = "";
549
- const finish = (supported) => {
550
- if (settled) return;
551
- settled = true;
552
- clearTimeout(timer);
553
- streams.stdin.removeListener("data", onData);
554
- if (!wasRaw) streams.stdin.setRawMode?.(false);
555
- if (wasPaused) streams.stdin.pause?.();
556
- resolve(supported);
557
- };
558
- const onData = (data) => {
559
- seen += typeof data === "string" ? data : data.toString("utf8");
560
- if (/\u001B\[\?\d*u/.test(seen)) finish(true);
561
- };
562
- const timer = setTimeout(() => finish(false), timeoutMs);
563
- streams.stdin.on("data", onData);
564
- streams.stdout.write(QUERY);
565
- });
566
- }
567
-
568
507
  // src/tui/ime-text-input.tsx
569
508
  import { jsx, jsxs } from "react/jsx-runtime";
570
509
  var segmenter = new Intl.Segmenter("ko", { granularity: "grapheme" });
@@ -628,22 +567,6 @@ function ImeTextInput(props) {
628
567
  moveCursor(nextCursor, segments.length);
629
568
  props.onChange(nextValue);
630
569
  };
631
- const { stdin: stdin2, isRawModeSupported } = useStdin();
632
- const onModeKeyRef = useRef2(void 0);
633
- onModeKeyRef.current = () => props.onHangulModeChange?.(!props.hangulMode);
634
- useEffect2(() => {
635
- if (!props.focus || !isRawModeSupported) return void 0;
636
- const onData = (data) => {
637
- const chunk = typeof data === "string" ? data : data.toString("utf8");
638
- for (const event of parseKeyEvents(chunk)) {
639
- typingRef.current = { ...typingRef.current, capsLock: event.capsLock };
640
- if (event.eventType !== 1) continue;
641
- if (event.name === "rightalt" || event.name === "capslock") onModeKeyRef.current?.();
642
- }
643
- };
644
- stdin2?.on("data", onData);
645
- return () => void stdin2?.off("data", onData);
646
- }, [props.focus, isRawModeSupported, stdin2]);
647
570
  useEffect2(() => {
648
571
  if (!props.focus || !props.hangulMode) {
649
572
  typingRef.current = { ...IDLE, capsLock: typingRef.current.capsLock };
@@ -1115,6 +1038,15 @@ function Dashboard(props) {
1115
1038
  setHangulMode(enabled);
1116
1039
  props.preferences?.onHangulModeChange?.(enabled);
1117
1040
  };
1041
+ useEffect6(
1042
+ () => props.preferences?.onModeKey?.(
1043
+ () => setHangulMode((current) => {
1044
+ props.preferences?.onHangulModeChange?.(!current);
1045
+ return !current;
1046
+ })
1047
+ ),
1048
+ [props.preferences]
1049
+ );
1118
1050
  const viewport = useRef3({ lineCount: 0, height: 0 });
1119
1051
  const [starting, setStarting] = useState7(false);
1120
1052
  const controller = useRef3(null);
@@ -1770,25 +1702,25 @@ function RetryInput({ onRetry }) {
1770
1702
  }
1771
1703
 
1772
1704
  // src/tui/screen.ts
1773
- var ESC2 = "\x1B";
1774
- var ENTER_ALT_SCREEN = `${ESC2}[?1049h`;
1775
- var LEAVE_ALT_SCREEN = `${ESC2}[?1049l`;
1776
- var SHOW_CURSOR = `${ESC2}[?25h`;
1705
+ var ESC = "\x1B";
1706
+ var ENTER_ALT_SCREEN = `${ESC}[?1049h`;
1707
+ var LEAVE_ALT_SCREEN = `${ESC}[?1049l`;
1708
+ var SHOW_CURSOR = `${ESC}[?25h`;
1777
1709
  var DISABLE_REPORTS = [
1778
- `${ESC2}[?1004l`,
1710
+ `${ESC}[?1004l`,
1779
1711
  // 포커스 들어옴/나감
1780
- `${ESC2}[?1000l`,
1712
+ `${ESC}[?1000l`,
1781
1713
  // 마우스 클릭
1782
- `${ESC2}[?1002l`,
1714
+ `${ESC}[?1002l`,
1783
1715
  // 마우스 드래그
1784
- `${ESC2}[?1003l`,
1716
+ `${ESC}[?1003l`,
1785
1717
  // 마우스 이동 전부
1786
- `${ESC2}[?1006l`
1718
+ `${ESC}[?1006l`
1787
1719
  // SGR 확장 좌표
1788
1720
  ].join("");
1789
- var ENABLE_BRACKETED_PASTE = `${ESC2}[?2004h`;
1790
- var DISABLE_BRACKETED_PASTE = `${ESC2}[?2004l`;
1791
- var POP_KITTY_KEYBOARD = `${ESC2}[<u`;
1721
+ var ENABLE_BRACKETED_PASTE = `${ESC}[?2004h`;
1722
+ var DISABLE_BRACKETED_PASTE = `${ESC}[?2004l`;
1723
+ var POP_KITTY_KEYBOARD = `${ESC}[<u`;
1792
1724
  function createScreenGuard(stream, options = {}) {
1793
1725
  const alt = Boolean(stream.isTTY);
1794
1726
  let entered = false;
@@ -1841,6 +1773,131 @@ async function writePreferences(preferences, env = process.env) {
1841
1773
  }
1842
1774
  }
1843
1775
 
1776
+ // src/tui/kitty.ts
1777
+ var ESC2 = "\x1B";
1778
+ var QUERY = `${ESC2}[?u`;
1779
+ var KEY_CODES = {
1780
+ 57358: "capslock",
1781
+ 57449: "rightalt"
1782
+ };
1783
+ var CAPS_LOCK_BIT = 64;
1784
+ function parseKeyEvents(chunk) {
1785
+ const events = [];
1786
+ const pattern = /\u001B\[(\d+)(?::\d+)*(?:;(\d+)(?::(\d+))?)?(?:;[\d:]*)?u/g;
1787
+ for (const match of chunk.matchAll(pattern)) {
1788
+ const code = Number(match[1]);
1789
+ const modifiers = match[2] ? Number(match[2]) - 1 : 0;
1790
+ events.push({
1791
+ name: KEY_CODES[code],
1792
+ // eslint-disable-next-line no-bitwise
1793
+ capsLock: (modifiers & CAPS_LOCK_BIT) !== 0,
1794
+ eventType: match[3] ? Number(match[3]) : 1
1795
+ });
1796
+ }
1797
+ return events;
1798
+ }
1799
+ function knownKittyTerminal(env = process.env) {
1800
+ if (env.KITTY_WINDOW_ID) return true;
1801
+ if (env.GHOSTTY_RESOURCES_DIR) return true;
1802
+ const term = (env.TERM ?? "").toLowerCase();
1803
+ if (term === "xterm-kitty" || term === "xterm-ghostty" || term.includes("foot")) return true;
1804
+ const program = (env.TERM_PROGRAM ?? "").toLowerCase();
1805
+ return program === "wezterm" || program === "ghostty" || program === "kitty";
1806
+ }
1807
+ async function supportsKittyKeyboard(streams, timeoutMs = 200, env = process.env) {
1808
+ if (env.DEX_NO_KITTY === "1") return false;
1809
+ if (!streams.stdout.isTTY || !streams.isTTY) return false;
1810
+ if (knownKittyTerminal(env)) return true;
1811
+ const wasRaw = streams.stdin.isRaw === true;
1812
+ const wasPaused = !wasRaw;
1813
+ streams.stdin.setRawMode?.(true);
1814
+ streams.stdin.resume?.();
1815
+ return new Promise((resolve) => {
1816
+ let settled = false;
1817
+ let seen = "";
1818
+ const finish = (supported) => {
1819
+ if (settled) return;
1820
+ settled = true;
1821
+ clearTimeout(timer);
1822
+ streams.stdin.removeListener("data", onData);
1823
+ if (!wasRaw) streams.stdin.setRawMode?.(false);
1824
+ if (wasPaused) streams.stdin.pause?.();
1825
+ resolve(supported);
1826
+ };
1827
+ const onData = (data) => {
1828
+ seen += typeof data === "string" ? data : data.toString("utf8");
1829
+ if (/\u001B\[\?\d*u/.test(seen)) finish(true);
1830
+ };
1831
+ const timer = setTimeout(() => finish(false), timeoutMs);
1832
+ streams.stdin.on("data", onData);
1833
+ streams.stdout.write(QUERY);
1834
+ });
1835
+ }
1836
+ var KEY_EVENT = /\u001B\[([0-9]+)(?::[0-9:]*)?(?:;([0-9]*(?::[0-9]+)?))?(?:;([0-9:]+))?u/g;
1837
+ function normalizeKeyEvents(chunk) {
1838
+ return chunk.replace(
1839
+ KEY_EVENT,
1840
+ (all, code, modifiers, text) => {
1841
+ const hasAlternate = all.slice(0, all.indexOf(";") === -1 ? all.length : all.indexOf(";")).includes(":");
1842
+ const needsModifier = modifiers !== void 0 && modifiers.length === 0;
1843
+ if (!hasAlternate && !needsModifier) return all;
1844
+ const mods = modifiers === void 0 ? void 0 : modifiers.length > 0 ? modifiers : "1";
1845
+ const fields = [code, mods, text].filter((field) => field !== void 0).join(";");
1846
+ return `\x1B[${fields}u`;
1847
+ }
1848
+ );
1849
+ }
1850
+ var PARTIAL_TAIL = /\u001B\[[0-9:;]*$/;
1851
+ var MAX_PARTIAL = 64;
1852
+ function createNormalizer() {
1853
+ let pending = "";
1854
+ return (chunk) => {
1855
+ const combined = pending + chunk;
1856
+ const match = PARTIAL_TAIL.exec(combined);
1857
+ if (match && combined.length - match.index <= MAX_PARTIAL) {
1858
+ pending = combined.slice(match.index);
1859
+ return normalizeKeyEvents(combined.slice(0, match.index));
1860
+ }
1861
+ pending = "";
1862
+ return normalizeKeyEvents(combined);
1863
+ };
1864
+ }
1865
+ function normalizedStdin(stdin2, onSpecialKey) {
1866
+ const normalize = createNormalizer();
1867
+ return new Proxy(stdin2, {
1868
+ get(target, property, receiver) {
1869
+ if (property === "read") {
1870
+ return (...args) => {
1871
+ const chunk = target.read(...args);
1872
+ if (chunk === null || chunk === void 0) return null;
1873
+ const text = typeof chunk === "string" ? chunk : String(chunk);
1874
+ if (onSpecialKey) {
1875
+ for (const event of parseKeyEvents(text)) {
1876
+ if (event.name && event.eventType === 1) onSpecialKey(event.name);
1877
+ }
1878
+ }
1879
+ return normalize(text);
1880
+ };
1881
+ }
1882
+ void receiver;
1883
+ const value = Reflect.get(target, property, target);
1884
+ return typeof value === "function" ? value.bind(target) : value;
1885
+ }
1886
+ });
1887
+ }
1888
+ function createKeySignal() {
1889
+ const listeners = /* @__PURE__ */ new Set();
1890
+ return {
1891
+ notify(name) {
1892
+ for (const listener of listeners) listener(name);
1893
+ },
1894
+ subscribe(listener) {
1895
+ listeners.add(listener);
1896
+ return () => void listeners.delete(listener);
1897
+ }
1898
+ };
1899
+ }
1900
+
1844
1901
  // src/tui/index.tsx
1845
1902
  import { jsx as jsx11 } from "react/jsx-runtime";
1846
1903
  async function runTui(engine) {
@@ -1856,6 +1913,7 @@ async function runTui(engine) {
1856
1913
  const preferences = await readPreferences();
1857
1914
  const kitty = await supportsKittyKeyboard({ stdin, stdout, isTTY: stdin.isTTY });
1858
1915
  screen = createScreenGuard(stdout, { kittyKeyboard: kitty });
1916
+ const modeKeys = createKeySignal();
1859
1917
  screen.enter();
1860
1918
  try {
1861
1919
  const instance = render(
@@ -1865,13 +1923,21 @@ async function runTui(engine) {
1865
1923
  engine,
1866
1924
  preferences: {
1867
1925
  hangulMode: preferences.hangulMode,
1868
- onHangulModeChange: (enabled) => void writePreferences({ hangulMode: enabled })
1926
+ onHangulModeChange: (enabled) => void writePreferences({ hangulMode: enabled }),
1927
+ onModeKey: modeKeys.subscribe
1869
1928
  }
1870
1929
  }
1871
1930
  ),
1872
1931
  {
1873
1932
  exitOnCtrlC: true,
1874
1933
  patchConsole: true,
1934
+ // 프로토콜을 켜면 kitty 가 ink 이 못 읽는 모양으로 키를 보낸다 — 사이에서
1935
+ // 고쳐 넘기지 않으면 글자가 하나도 입력되지 않는다.
1936
+ ...kitty ? {
1937
+ stdin: normalizedStdin(stdin, (name) => {
1938
+ if (name === "rightalt" || name === "capslock") modeKeys.notify(name);
1939
+ })
1940
+ } : {},
1875
1941
  // 모든 키를 이스케이프로 받아야 한/영 키(오른쪽 Alt)와 Caps Lock 이 사건으로
1876
1942
  // 온다. 그런데 그렇게만 켜면 터미널이 **글쇠 코드만** 보내서 Shift+r 이
1877
1943
  // 소문자 `r` 로 도착한다 — 된소리도 영문 대문자도 사라진다. 그래서 글자까지
@@ -1899,4 +1965,4 @@ async function runTui(engine) {
1899
1965
  export {
1900
1966
  runTui
1901
1967
  };
1902
- //# sourceMappingURL=tui-H3VM2MGV.js.map
1968
+ //# sourceMappingURL=tui-VLPJMWUK.js.map