@pikaa-ai/pikaa 0.3.16 → 0.3.18

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/cli.js +67 -46
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -6429,7 +6429,7 @@ function parsePatch(oldSrc, newSrc, contextLines = 3) {
6429
6429
  // package.json
6430
6430
  var package_default = {
6431
6431
  name: "@pikaa-ai/pikaa",
6432
- version: "0.3.16",
6432
+ version: "0.3.18",
6433
6433
  description: "PIKAA CLI - AI coding agent that runs locally in your terminal.",
6434
6434
  main: "./dist/index.js",
6435
6435
  module: "./dist/index.js",
@@ -6986,12 +6986,23 @@ ${preview}${more}`);
6986
6986
  }
6987
6987
 
6988
6988
  // src/cli/ui/line-editor.ts
6989
+ import readline2 from "readline";
6990
+
6991
+ // src/cli/ui/keypress.ts
6989
6992
  import readline from "readline";
6990
6993
  var keypressEventsInitialized = false;
6991
- function ensureKeypressInitialized() {
6994
+ var listeners = new Set;
6995
+ function initGlobalKeypress() {
6992
6996
  if (!keypressEventsInitialized && process.stdin.isTTY) {
6993
6997
  readline.emitKeypressEvents(process.stdin);
6994
6998
  keypressEventsInitialized = true;
6999
+ process.stdin.on("keypress", (str, key) => {
7000
+ for (const listener of Array.from(listeners)) {
7001
+ try {
7002
+ listener(str, key);
7003
+ } catch {}
7004
+ }
7005
+ });
6995
7006
  process.on("exit", () => {
6996
7007
  if (process.stdin.isTTY) {
6997
7008
  try {
@@ -7001,7 +7012,15 @@ function ensureKeypressInitialized() {
7001
7012
  });
7002
7013
  }
7003
7014
  }
7015
+ function addGlobalKeypressListener(listener) {
7016
+ initGlobalKeypress();
7017
+ listeners.add(listener);
7018
+ return () => {
7019
+ listeners.delete(listener);
7020
+ };
7021
+ }
7004
7022
 
7023
+ // src/cli/ui/line-editor.ts
7005
7024
  class InteractiveLineEditor {
7006
7025
  promptSymbol;
7007
7026
  cwd;
@@ -7052,14 +7071,13 @@ class InteractiveLineEditor {
7052
7071
  async readLine() {
7053
7072
  if (!process.stdin.isTTY) {
7054
7073
  return new Promise((resolve17) => {
7055
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
7074
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
7056
7075
  rl.question(this.promptSymbol, (answer) => {
7057
7076
  rl.close();
7058
7077
  resolve17(answer);
7059
7078
  });
7060
7079
  });
7061
7080
  }
7062
- ensureKeypressInitialized();
7063
7081
  return new Promise((resolve17) => {
7064
7082
  let buffer = "";
7065
7083
  let cursor = 0;
@@ -7067,6 +7085,7 @@ class InteractiveLineEditor {
7067
7085
  let scrollTop = 0;
7068
7086
  let popupDismissed = false;
7069
7087
  let lastCursorRowFromTop = 0;
7088
+ let unsubscribeKeypress = null;
7070
7089
  if (process.stdin.isTTY) {
7071
7090
  try {
7072
7091
  process.stdin.setRawMode(true);
@@ -7244,7 +7263,10 @@ class InteractiveLineEditor {
7244
7263
  if (process.stdout && typeof process.stdout.removeListener === "function") {
7245
7264
  process.stdout.removeListener("resize", onResize);
7246
7265
  }
7247
- process.stdin.removeListener("keypress", onKeypress);
7266
+ if (unsubscribeKeypress) {
7267
+ unsubscribeKeypress();
7268
+ unsubscribeKeypress = null;
7269
+ }
7248
7270
  if (process.stdin.isTTY) {
7249
7271
  try {
7250
7272
  process.stdin.setRawMode(false);
@@ -7284,12 +7306,15 @@ class InteractiveLineEditor {
7284
7306
  process.stdout.write(`\x1B[${lastCursorRowFromTop}A`);
7285
7307
  }
7286
7308
  process.stdout.write("\r\x1B[J");
7309
+ if (unsubscribeKeypress) {
7310
+ unsubscribeKeypress();
7311
+ unsubscribeKeypress = null;
7312
+ }
7287
7313
  if (process.stdin.isTTY) {
7288
7314
  try {
7289
7315
  process.stdin.setRawMode(false);
7290
7316
  } catch {}
7291
7317
  }
7292
- process.stdin.removeListener("keypress", onKeypress);
7293
7318
  if (this.onInterrupt) {
7294
7319
  this.onInterrupt();
7295
7320
  }
@@ -7428,7 +7453,7 @@ class InteractiveLineEditor {
7428
7453
  redraw();
7429
7454
  }
7430
7455
  };
7431
- process.stdin.on("keypress", onKeypress);
7456
+ unsubscribeKeypress = addGlobalKeypressListener(onKeypress);
7432
7457
  const RULE_COLOR = "\x1B[38;2;60;60;68m";
7433
7458
  process.stdout.write(`
7434
7459
  ${RULE_COLOR}${getRule()}\x1B[0m
@@ -7439,31 +7464,27 @@ class InteractiveLineEditor {
7439
7464
  }
7440
7465
 
7441
7466
  // src/cli/ui/prompt.ts
7442
- import readline2 from "readline";
7467
+ import readline3 from "readline";
7443
7468
  async function promptChoice(config) {
7444
7469
  const { message, choices, defaultIndex = 0 } = config;
7445
7470
  if (!process.stdin.isTTY) {
7446
7471
  if (!process.stdin.readable) {
7447
- return choices[defaultIndex]?.value ?? choices[0].value;
7472
+ const def = choices[defaultIndex] || choices[0];
7473
+ return def ? def.value : "";
7448
7474
  }
7449
7475
  return new Promise((resolve17) => {
7450
- const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
7451
- const hint = choices.map((c3) => c3.isDefault ? `[${c3.key.toUpperCase()}]` : `[${c3.key}]`).join("/");
7452
- let resolved = false;
7453
- const doResolve = (val) => {
7454
- if (!resolved) {
7455
- resolved = true;
7456
- rl.close();
7457
- resolve17(val);
7458
- }
7459
- };
7460
- rl.question(`${message} ${hint}: `, (answer) => {
7476
+ const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
7477
+ const promptText = ` ${message} (${choices.map((c3) => `[${c3.key}] ${c3.label}`).join(", ")}): `;
7478
+ rl.question(promptText, (answer) => {
7479
+ rl.close();
7461
7480
  const trimmed = answer.trim().toLowerCase();
7462
- const matched = choices.find((c3) => c3.key.toLowerCase() === trimmed);
7463
- doResolve(matched ? matched.value : choices[defaultIndex].value);
7464
- });
7465
- rl.on("close", () => {
7466
- doResolve(choices[defaultIndex].value);
7481
+ const match = choices.find((c3) => c3.key.toLowerCase() === trimmed);
7482
+ if (match) {
7483
+ resolve17(match.value);
7484
+ } else {
7485
+ const def = choices[defaultIndex] || choices[0];
7486
+ resolve17(def ? def.value : "");
7487
+ }
7467
7488
  });
7468
7489
  });
7469
7490
  }
@@ -7471,7 +7492,6 @@ async function promptChoice(config) {
7471
7492
  let selectedIndex = defaultIndex;
7472
7493
  if (selectedIndex < 0 || selectedIndex >= choices.length)
7473
7494
  selectedIndex = 0;
7474
- readline2.emitKeypressEvents(process.stdin);
7475
7495
  const wasRaw = process.stdin.isRaw;
7476
7496
  try {
7477
7497
  process.stdin.setRawMode(true);
@@ -7489,8 +7509,12 @@ async function promptChoice(config) {
7489
7509
  process.stdout.write(`\r\x1B[2K ${style.bold(message)}
7490
7510
  \r\x1B[2K${parts.join(" ")}`);
7491
7511
  };
7512
+ let unsubscribe = null;
7492
7513
  const cleanup = (confirmedChoice) => {
7493
- process.stdin.removeListener("keypress", onKeypress);
7514
+ if (unsubscribe) {
7515
+ unsubscribe();
7516
+ unsubscribe = null;
7517
+ }
7494
7518
  try {
7495
7519
  process.stdin.setRawMode(wasRaw ?? false);
7496
7520
  } catch {}
@@ -7502,21 +7526,12 @@ async function promptChoice(config) {
7502
7526
  if (!key)
7503
7527
  return;
7504
7528
  if (key.ctrl && key.name === "c") {
7505
- cleanup(choices.find((c3) => c3.key.toLowerCase() === "n") || choices[defaultIndex]);
7529
+ const def = choices[defaultIndex] || choices[0];
7530
+ cleanup(def);
7506
7531
  return;
7507
7532
  }
7508
- if (key.name === "escape") {
7509
- cleanup(choices.find((c3) => c3.key.toLowerCase() === "n") || choices[defaultIndex]);
7510
- return;
7511
- }
7512
- if (key.name === "return" || key.name === "enter") {
7513
- cleanup(choices[selectedIndex]);
7514
- return;
7515
- }
7516
- if (key.name === "left") {
7533
+ if (key.name === "left" || key.name === "up" || key.name === "h" || key.name === "k") {
7517
7534
  selectedIndex = (selectedIndex - 1 + choices.length) % choices.length;
7518
- process.stdout.write("\x1B[1A");
7519
- render();
7520
7535
  return;
7521
7536
  }
7522
7537
  if (key.name === "right" || key.name === "tab") {
@@ -7573,7 +7588,6 @@ async function promptToolApproval(params) {
7573
7588
  }
7574
7589
  return new Promise((resolve17) => {
7575
7590
  let selectedIndex = 1;
7576
- readline2.emitKeypressEvents(process.stdin);
7577
7591
  const wasRaw = process.stdin.isRaw;
7578
7592
  try {
7579
7593
  process.stdin.setRawMode(true);
@@ -7582,8 +7596,12 @@ async function promptToolApproval(params) {
7582
7596
  const render = () => {
7583
7597
  renderCard(selectedIndex);
7584
7598
  };
7599
+ let unsubscribe = null;
7585
7600
  const cleanup = (val) => {
7586
- process.stdin.removeListener("keypress", onKeypress);
7601
+ if (unsubscribe) {
7602
+ unsubscribe();
7603
+ unsubscribe = null;
7604
+ }
7587
7605
  try {
7588
7606
  process.stdin.setRawMode(wasRaw ?? false);
7589
7607
  } catch {}
@@ -7642,7 +7660,7 @@ async function promptToolApproval(params) {
7642
7660
  return;
7643
7661
  }
7644
7662
  };
7645
- process.stdin.on("keypress", onKeypress);
7663
+ unsubscribe = addGlobalKeypressListener(onKeypress);
7646
7664
  render();
7647
7665
  });
7648
7666
  }
@@ -7672,7 +7690,7 @@ async function promptUserQuestion(params) {
7672
7690
  return options[0] || "yes";
7673
7691
  }
7674
7692
  return new Promise((resolve17) => {
7675
- const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
7693
+ const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
7676
7694
  const promptLabel = options.length > 0 ? `Select [1-${options.length}] or type custom response: ` : `Your response: `;
7677
7695
  rl.question(` ${style.bold(promptLabel)}`, (answer) => {
7678
7696
  rl.close();
@@ -7741,7 +7759,6 @@ async function promptInteractiveList(config) {
7741
7759
  let selectedIndex = Math.max(0, Math.min(defaultIndex, items.length - 1));
7742
7760
  let scrollTop = 0;
7743
7761
  let renderedLines = 0;
7744
- readline2.emitKeypressEvents(process.stdin);
7745
7762
  const wasRaw = process.stdin.isRaw;
7746
7763
  try {
7747
7764
  process.stdin.setRawMode(true);
@@ -7818,6 +7835,7 @@ async function promptInteractiveList(config) {
7818
7835
  process.stdout.write(buffer);
7819
7836
  renderedLines = lines.length;
7820
7837
  };
7838
+ let unsubscribe = null;
7821
7839
  const cleanup = (res) => {
7822
7840
  if (renderedLines > 0) {
7823
7841
  process.stdout.write(`\x1B[${renderedLines}A\r\x1B[J\x1B[?25h`);
@@ -7825,7 +7843,10 @@ async function promptInteractiveList(config) {
7825
7843
  } else {
7826
7844
  process.stdout.write("\x1B[?25h");
7827
7845
  }
7828
- process.stdin.removeListener("keypress", onKeypress);
7846
+ if (unsubscribe) {
7847
+ unsubscribe();
7848
+ unsubscribe = null;
7849
+ }
7829
7850
  try {
7830
7851
  process.stdin.setRawMode(wasRaw ?? false);
7831
7852
  } catch {}
@@ -7894,7 +7915,7 @@ async function promptInteractiveList(config) {
7894
7915
  render();
7895
7916
  }
7896
7917
  };
7897
- process.stdin.on("keypress", onKeypress);
7918
+ unsubscribe = addGlobalKeypressListener(onKeypress);
7898
7919
  render();
7899
7920
  });
7900
7921
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikaa-ai/pikaa",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
4
4
  "description": "PIKAA CLI - AI coding agent that runs locally in your terminal.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",