codemaxxing 1.0.2 → 1.0.4

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.
Files changed (2) hide show
  1. package/dist/index.js +70 -32
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1745,61 +1745,99 @@ const pasteEvents = new EventEmitter();
1745
1745
  // Enable bracketed paste mode — terminal wraps pastes in escape sequences
1746
1746
  process.stdout.write("\x1b[?2004h");
1747
1747
  // Intercept stdin to handle pasted content
1748
- // Bracketed paste: \x1b[200~ ... \x1b[201~
1749
- let pasteBuffer = "";
1750
- let inPaste = false;
1751
- function emitPasteChunk(content) {
1748
+ // Strategy: patch emit('data') instead of push() — this is the ONE path all data
1749
+ // must travel through to reach Ink's listeners, regardless of how the TTY/stream
1750
+ // delivers it internally.
1751
+ //
1752
+ // Two detection layers:
1753
+ // 1. Bracketed paste escape sequences (\x1b[200~ ... \x1b[201~)
1754
+ // 2. Burst buffering — accumulate rapid-fire chunks over a short window and check
1755
+ // whether the combined content looks like a multiline paste.
1756
+ let bracketedBuffer = "";
1757
+ let inBracketedPaste = false;
1758
+ let burstBuffer = "";
1759
+ let burstTimer = null;
1760
+ const BURST_WINDOW_MS = 25; // Short enough to feel instant, long enough to catch paste bursts
1761
+ const origEmit = process.stdin.emit.bind(process.stdin);
1762
+ function handlePasteContent(content) {
1752
1763
  const normalized = content.replace(/\r\n/g, "\n").trim();
1753
1764
  if (!normalized)
1754
- return true;
1765
+ return;
1755
1766
  const lineCount = normalized.split("\n").length;
1756
1767
  if (lineCount > 2) {
1768
+ // Real multiline paste → badge it
1757
1769
  pasteEvents.emit("paste", { content: normalized, lines: lineCount });
1758
- return true;
1770
+ return;
1759
1771
  }
1772
+ // Short paste (1-2 lines) → collapse to single line and forward as normal input
1760
1773
  const sanitized = normalized.replace(/\n/g, " ");
1761
1774
  if (sanitized) {
1762
- origPush(sanitized, "utf-8");
1775
+ origEmit("data", sanitized);
1763
1776
  }
1764
- return true;
1765
1777
  }
1766
- function looksLikeRawMultilinePaste(data) {
1767
- const normalized = data.replace(/\x1b\[20[01]~/g, "");
1768
- const newlineMatches = normalized.match(/\r?\n/g) ?? [];
1769
- const newlineCount = newlineMatches.length;
1770
- const contentLength = normalized.replace(/[\r\n]/g, "").trim().length;
1771
- // Avoid swallowing normal Enter presses while still catching terminals that
1772
- // don't support bracketed paste and dump the whole paste as one raw chunk.
1773
- return newlineCount >= 2 || (newlineCount >= 1 && contentLength >= 40);
1778
+ function looksLikeMultilinePaste(data) {
1779
+ const clean = data.replace(/\x1b\[[0-9;]*[A-Za-z]/g, ""); // Strip all ANSI escapes
1780
+ const newlines = (clean.match(/\r?\n/g) ?? []).length;
1781
+ const printable = clean.replace(/[\r\n]/g, "").trim().length;
1782
+ return newlines >= 2 || (newlines >= 1 && printable >= 40);
1783
+ }
1784
+ function flushBurst() {
1785
+ if (!burstBuffer)
1786
+ return;
1787
+ const buffered = burstBuffer;
1788
+ burstBuffer = "";
1789
+ if (looksLikeMultilinePaste(buffered)) {
1790
+ handlePasteContent(buffered);
1791
+ }
1792
+ else {
1793
+ // Normal typing — forward to Ink
1794
+ origEmit("data", buffered);
1795
+ }
1774
1796
  }
1775
- const origPush = process.stdin.push.bind(process.stdin);
1776
- process.stdin.push = function (chunk, encoding) {
1777
- if (chunk === null)
1778
- return origPush(chunk, encoding);
1797
+ process.stdin.emit = function (event, ...args) {
1798
+ // Pass through non-data events untouched
1799
+ if (event !== "data") {
1800
+ return origEmit(event, ...args);
1801
+ }
1802
+ const chunk = args[0];
1779
1803
  let data = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
1804
+ // ── Bracketed paste handling ──
1780
1805
  const hasStart = data.includes("\x1b[200~");
1781
1806
  const hasEnd = data.includes("\x1b[201~");
1782
1807
  if (hasStart) {
1783
- inPaste = true;
1808
+ // Flush any pending burst before entering bracketed mode
1809
+ if (burstTimer) {
1810
+ clearTimeout(burstTimer);
1811
+ burstTimer = null;
1812
+ }
1813
+ flushBurst();
1814
+ inBracketedPaste = true;
1784
1815
  data = data.replace(/\x1b\[200~/g, "");
1785
1816
  }
1786
1817
  if (hasEnd) {
1787
1818
  data = data.replace(/\x1b\[201~/g, "");
1788
- pasteBuffer += data;
1789
- inPaste = false;
1790
- const content = pasteBuffer;
1791
- pasteBuffer = "";
1792
- return emitPasteChunk(content);
1819
+ bracketedBuffer += data;
1820
+ inBracketedPaste = false;
1821
+ const content = bracketedBuffer;
1822
+ bracketedBuffer = "";
1823
+ handlePasteContent(content);
1824
+ return true;
1793
1825
  }
1794
- if (inPaste) {
1795
- pasteBuffer += data;
1826
+ if (inBracketedPaste) {
1827
+ bracketedBuffer += data;
1796
1828
  return true;
1797
1829
  }
1830
+ // ── Burst buffering for non-bracketed paste ──
1831
+ // Strip stray bracketed paste markers that might appear outside a proper pair
1798
1832
  data = data.replace(/\x1b\[20[01]~/g, "");
1799
- if (looksLikeRawMultilinePaste(data)) {
1800
- return emitPasteChunk(data);
1801
- }
1802
- return origPush(typeof chunk === "string" ? data : Buffer.from(data), encoding);
1833
+ burstBuffer += data;
1834
+ if (burstTimer)
1835
+ clearTimeout(burstTimer);
1836
+ burstTimer = setTimeout(() => {
1837
+ burstTimer = null;
1838
+ flushBurst();
1839
+ }, BURST_WINDOW_MS);
1840
+ return true;
1803
1841
  };
1804
1842
  // Disable bracketed paste on exit
1805
1843
  process.on("exit", () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codemaxxing",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Open-source terminal coding agent. Connect any LLM. Max your code.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {