kooni-bot 0.2.2 → 0.2.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.
- package/bin/kooni.js +33 -29
- 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.
|
|
25
|
+
const CLI_VERSION = "0.2.4";
|
|
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.
|
|
343
|
-
// (
|
|
344
|
-
//
|
|
345
|
-
|
|
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
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
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) {
|
|
@@ -496,9 +499,11 @@ const isWin = process.platform === "win32";
|
|
|
496
499
|
|
|
497
500
|
// Ejecuta un binario de forma segura en Windows/macOS/Linux:
|
|
498
501
|
// - Unix/mac: `spawnSync(file, args)` directo.
|
|
499
|
-
// - Windows: `npx`/`pnpm` son shims
|
|
500
|
-
//
|
|
501
|
-
//
|
|
502
|
+
// - Windows: `npx`/`pnpm` son shims, pero `cmd.exe /c` los resuelve SIN la
|
|
503
|
+
// extensión `.cmd` (probado: `cmd.exe /c pnpm --version` funciona, mientras
|
|
504
|
+
// que `pnpm.cmd` explícito falla con "no se reconoce"). Así que aquí NO se
|
|
505
|
+
// mapea a `.cmd`: se lanza `cmd.exe /c <file> <args...>` con args separados.
|
|
506
|
+
// Nada de `shell: true` ni concatenación → sin EINVAL ni DEP0190.
|
|
502
507
|
// - `stdio` hereda por defecto (progreso en vivo); `capture` captura para parsear.
|
|
503
508
|
function run(file, args = [], opts = {}) {
|
|
504
509
|
const cwd = opts.cwd;
|
|
@@ -509,15 +514,14 @@ function run(file, args = [], opts = {}) {
|
|
|
509
514
|
let argv = args;
|
|
510
515
|
|
|
511
516
|
if (isWin) {
|
|
512
|
-
const shim = { npx: "npx.cmd", pnpm: "pnpm.cmd" }[file] || file;
|
|
513
517
|
cmd = "cmd.exe";
|
|
514
|
-
argv = ["/d", "/c",
|
|
518
|
+
argv = ["/d", "/c", file, ...args];
|
|
515
519
|
}
|
|
516
520
|
|
|
517
521
|
const r = spawnSync(cmd, argv, { cwd, input, stdio, encoding: "utf8" });
|
|
518
522
|
if (r.error) throw r.error;
|
|
519
523
|
if (r.status !== 0) {
|
|
520
|
-
const err = new Error(`Command failed: ${[
|
|
524
|
+
const err = new Error(`Command failed: ${[file, ...args].join(" ")}`);
|
|
521
525
|
err.stdout = r.stdout;
|
|
522
526
|
err.stderr = r.stderr;
|
|
523
527
|
err.status = r.status;
|
|
@@ -746,7 +750,7 @@ async function onboarding(rl, answers, defaultDir) {
|
|
|
746
750
|
// La API key se pide aquí, apenas se elige el cerebro — y se conserva para el
|
|
747
751
|
// deploy (se guarda como secret sin mostrarla). En no-interactivo se salta.
|
|
748
752
|
if (!answers.apiKey) {
|
|
749
|
-
answers.apiKey = await promptSecret(t().qApiKey(BRAINS[answers.brainKey].label));
|
|
753
|
+
answers.apiKey = await promptSecret(rl, t().qApiKey(BRAINS[answers.brainKey].label));
|
|
750
754
|
}
|
|
751
755
|
|
|
752
756
|
answers.what = answers.what ?? (await ask(rl, t().qWhat, undefined) || "");
|
|
@@ -873,7 +877,7 @@ async function deployBot(dir, { flags = {}, rl } = {}) {
|
|
|
873
877
|
}
|
|
874
878
|
|
|
875
879
|
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):"));
|
|
880
|
+
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
881
|
if (!dash) dash = "kooni-local-password";
|
|
878
882
|
wrangler(dir, ["secret", "put", "DASHBOARD_PASSWORD"], { input: dash, capture: true });
|
|
879
883
|
console.log(" " + C.green("✓") + " " + t().secretOk("DASHBOARD_PASSWORD"));
|
package/package.json
CHANGED