kooni-bot 0.2.2 → 0.2.3

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/bin/kooni.js +26 -23
  2. package/package.json +1 -1
package/bin/kooni.js CHANGED
@@ -22,7 +22,7 @@ import { execFileSync, spawnSync } from "node:child_process";
22
22
  import { randomUUID } from "node:crypto";
23
23
  import { fileURLToPath } from "node:url";
24
24
 
25
- const CLI_VERSION = "0.2.2";
25
+ const CLI_VERSION = "0.2.3";
26
26
 
27
27
  const REPO = process.env.KOONI_REPO || "iamnocodeveloper/kooni-bot";
28
28
  const BRANCH = process.env.KOONI_BRANCH || "main";
@@ -339,27 +339,30 @@ async function ask(rl, q, val) {
339
339
  return (await rl.question("\n " + C.b(q) + "\n " + C.cyan("› "))).trim();
340
340
  }
341
341
 
342
- // Input oculto para API keys / contraseñas. Usa una interfaz readline DEDICADA
343
- // (no el rl compartido) con máscara de salida para no chocar con los listeners
344
- // del selector y soportar pegado. Devuelve "" si no hay TTY.
345
- async function promptSecret(q) {
342
+ // Input oculto para API keys / contraseñas. Reutiliza la MISMA interfaz `rl`
343
+ // compartida (crear una segunda readline sobre el mismo stdin competía por los
344
+ // datos y nunca recibía Enter el proceso se quedaba colgado). Enmascara el eco
345
+ // parcheando temporalmente `_writeToOutput`: deja pasar solo los saltos de línea.
346
+ async function promptSecret(rl, q) {
346
347
  if (!interactive()) return "";
347
- const rl = createInterface({ input, output, terminal: true });
348
- const answer = await new Promise((resolve) => {
349
- // Enmascara lo que teclea el usuario: solo deja pasar el prompt y los saltos
350
- // de línea (nunca la tecla), para que la API key quede oculta.
351
- const orig = rl._writeToOutput;
352
- rl._writeToOutput = (s) => {
353
- if (s === "\r\n" || s === "\n" || s === "\r") process.stdout.write(s);
354
- else if (typeof orig === "function" && s.includes(" ")) orig.call(rl, s);
355
- };
356
- rl.question("\n " + C.b(q) + "\n " + C.cyan("› "), (a) => {
357
- rl.close();
358
- resolve(a);
359
- });
360
- });
361
- process.stdout.write("\n");
362
- return answer.trim();
348
+ process.stdout.write("\n " + C.b(q) + "\n " + C.cyan("› "));
349
+
350
+ const orig = rl._writeToOutput;
351
+ let masking = true;
352
+ rl._writeToOutput = (s) => {
353
+ if (!masking) return typeof orig === "function" ? orig.call(rl, s) : process.stdout.write(s);
354
+ // Enmascara lo tecleado; solo deja los saltos de línea.
355
+ if (s === "\r\n" || s === "\n" || s === "\r") process.stdout.write(s);
356
+ };
357
+
358
+ try {
359
+ const answer = await rl.question("");
360
+ return answer.trim();
361
+ } finally {
362
+ rl._writeToOutput = orig;
363
+ masking = false;
364
+ process.stdout.write("\n");
365
+ }
363
366
  }
364
367
 
365
368
  async function confirm(rl, q) {
@@ -746,7 +749,7 @@ async function onboarding(rl, answers, defaultDir) {
746
749
  // La API key se pide aquí, apenas se elige el cerebro — y se conserva para el
747
750
  // deploy (se guarda como secret sin mostrarla). En no-interactivo se salta.
748
751
  if (!answers.apiKey) {
749
- answers.apiKey = await promptSecret(t().qApiKey(BRAINS[answers.brainKey].label));
752
+ answers.apiKey = await promptSecret(rl, t().qApiKey(BRAINS[answers.brainKey].label));
750
753
  }
751
754
 
752
755
  answers.what = answers.what ?? (await ask(rl, t().qWhat, undefined) || "");
@@ -873,7 +876,7 @@ async function deployBot(dir, { flags = {}, rl } = {}) {
873
876
  }
874
877
 
875
878
  let dash = "";
876
- if (interactive()) dash = await promptSecret(m("Elige una contraseña para el panel /admin (usuario: admin):", "Choose a password for the /admin dashboard (user: admin):"));
879
+ if (interactive()) dash = await promptSecret(rl, m("Elige una contraseña para el panel /admin (usuario: admin):", "Choose a password for the /admin dashboard (user: admin):"));
877
880
  if (!dash) dash = "kooni-local-password";
878
881
  wrangler(dir, ["secret", "put", "DASHBOARD_PASSWORD"], { input: dash, capture: true });
879
882
  console.log(" " + C.green("✓") + " " + t().secretOk("DASHBOARD_PASSWORD"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kooni-bot",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Kooni — instala tu asistente de IA multicanal (WhatsApp, Instagram, Messenger, Telegram) en TU Cloudflare, en un comando.",
5
5
  "license": "MIT",
6
6
  "type": "module",