@tritard/waterbrother 0.6.1 → 0.6.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/prompt.js +31 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tritard/waterbrother",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Waterbrother: Grok-powered coding CLI with local tools, sessions, operator modes, and approval controls",
5
5
  "type": "module",
6
6
  "bin": {
package/src/prompt.js CHANGED
@@ -8,10 +8,15 @@ export async function promptLine(label, { input = process.stdin, output = proces
8
8
  let buf = "";
9
9
  let resolved = false;
10
10
  const shouldPauseOnCleanup = typeof input.pause === "function";
11
+ const isTTY = input.isTTY && typeof input.setRawMode === "function";
12
+
11
13
  function cleanup() {
12
14
  resolved = true;
13
15
  input.removeListener("data", onData);
14
16
  if (signal) signal.removeEventListener("abort", onAbort);
17
+ if (isTTY) {
18
+ try { input.setRawMode(false); } catch {}
19
+ }
15
20
  if (shouldPauseOnCleanup) {
16
21
  try {
17
22
  input.pause();
@@ -25,10 +30,27 @@ export async function promptLine(label, { input = process.stdin, output = proces
25
30
  if (ch === "\r") continue;
26
31
  if (ch === "\n") {
27
32
  cleanup();
33
+ output.write("\n");
28
34
  resolve(buf);
29
35
  return;
30
36
  }
37
+ if (ch === "\u0003") {
38
+ cleanup();
39
+ reject(new DOMException("The operation was aborted.", "AbortError"));
40
+ return;
41
+ }
42
+ // Backspace
43
+ if (ch === "\u007f" || ch === "\b") {
44
+ if (buf.length > 0) {
45
+ buf = buf.slice(0, -1);
46
+ output.write("\b \b");
47
+ }
48
+ continue;
49
+ }
50
+ // Skip non-printable control chars
51
+ if (ch.charCodeAt(0) < 32) continue;
31
52
  buf += ch;
53
+ output.write(ch);
32
54
  }
33
55
  }
34
56
  function onAbort() {
@@ -36,6 +58,15 @@ export async function promptLine(label, { input = process.stdin, output = proces
36
58
  cleanup();
37
59
  reject(signal.reason || new DOMException("The operation was aborted.", "AbortError"));
38
60
  }
61
+
62
+ // Ensure clean stdin state before listening
63
+ if (isTTY) {
64
+ try { input.setRawMode(false); } catch {}
65
+ }
66
+ input.pause();
67
+ if (isTTY) {
68
+ input.setRawMode(true);
69
+ }
39
70
  input.on("data", onData);
40
71
  input.resume();
41
72
  if (signal) signal.addEventListener("abort", onAbort, { once: true });