@umbral/cli 0.0.4 → 0.0.5

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 +90 -32
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -854,7 +854,7 @@ function getTemplate(detection) {
854
854
  }
855
855
 
856
856
  // src/claude-generate.ts
857
- import { spawnSync } from "child_process";
857
+ import { spawn, spawnSync } from "child_process";
858
858
  function isClaudeAvailable() {
859
859
  try {
860
860
  const r = spawnSync("claude", ["--version"], {
@@ -970,19 +970,9 @@ function normalizeEde(raw, index) {
970
970
  }
971
971
  };
972
972
  }
973
- function generateWithClaude(detections) {
974
- if (detections.length === 0) return null;
975
- const prompt = buildPrompt(detections);
973
+ function parseEdes(stdout2) {
976
974
  try {
977
- const result = spawnSync("claude", ["--print"], {
978
- input: prompt,
979
- encoding: "utf-8",
980
- timeout: 12e4,
981
- shell: true,
982
- maxBuffer: 5 * 1024 * 1024
983
- });
984
- if (result.status !== 0 || !result.stdout) return null;
985
- const jsonStr = extractJson(result.stdout);
975
+ const jsonStr = extractJson(stdout2);
986
976
  const parsed = JSON.parse(jsonStr);
987
977
  if (!Array.isArray(parsed) || parsed.length === 0) return null;
988
978
  const edes = [];
@@ -1000,6 +990,78 @@ function generateWithClaude(detections) {
1000
990
  return null;
1001
991
  }
1002
992
  }
993
+ function generateWithClaude(detections) {
994
+ if (detections.length === 0) return Promise.resolve(null);
995
+ const prompt = buildPrompt(detections);
996
+ return new Promise((resolve) => {
997
+ const child = spawn("claude", ["--print"], {
998
+ shell: true,
999
+ stdio: ["pipe", "pipe", "pipe"]
1000
+ });
1001
+ let stdout2 = "";
1002
+ let stderr = "";
1003
+ let timedOut = false;
1004
+ const timeout = setTimeout(() => {
1005
+ timedOut = true;
1006
+ child.kill();
1007
+ }, 12e4);
1008
+ child.stdout.on("data", (chunk) => {
1009
+ stdout2 += chunk.toString();
1010
+ });
1011
+ child.stderr.on("data", (chunk) => {
1012
+ stderr += chunk.toString();
1013
+ });
1014
+ child.on("close", (code) => {
1015
+ clearTimeout(timeout);
1016
+ if (timedOut || code !== 0 || !stdout2) {
1017
+ resolve(null);
1018
+ return;
1019
+ }
1020
+ resolve(parseEdes(stdout2));
1021
+ });
1022
+ child.on("error", () => {
1023
+ clearTimeout(timeout);
1024
+ resolve(null);
1025
+ });
1026
+ child.stdin.write(prompt);
1027
+ child.stdin.end();
1028
+ });
1029
+ }
1030
+
1031
+ // src/spinner.ts
1032
+ var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1033
+ function createSpinner(text) {
1034
+ let i = 0;
1035
+ const start = Date.now();
1036
+ const w = process.stdout;
1037
+ function elapsed() {
1038
+ const s = Math.floor((Date.now() - start) / 1e3);
1039
+ return s < 60 ? `${s}s` : `${Math.floor(s / 60)}m ${s % 60}s`;
1040
+ }
1041
+ function render() {
1042
+ w.write(`\r ${FRAMES[i % FRAMES.length]} ${text} (${elapsed()})`);
1043
+ i++;
1044
+ }
1045
+ render();
1046
+ const interval = setInterval(render, 80);
1047
+ function clear(symbol, msg) {
1048
+ clearInterval(interval);
1049
+ const line = ` ${symbol} ${msg}`;
1050
+ w.write(`\r${line}${"".padEnd(40)}
1051
+ `);
1052
+ }
1053
+ return {
1054
+ update(newText) {
1055
+ text = newText;
1056
+ },
1057
+ succeed(msg) {
1058
+ clear("\u2713", msg);
1059
+ },
1060
+ fail(msg) {
1061
+ clear("\u2717", msg);
1062
+ }
1063
+ };
1064
+ }
1003
1065
 
1004
1066
  // src/generate.ts
1005
1067
  function generateFromTemplates(detections) {
@@ -1054,14 +1116,21 @@ function generateFromTemplates(detections) {
1054
1116
  }
1055
1117
  return proposals;
1056
1118
  }
1057
- function generateProposals(detections, onStatus) {
1119
+ async function generateProposals(detections) {
1058
1120
  if (isClaudeAvailable()) {
1059
- onStatus?.("Generando EDEs con Claude Code...");
1060
- const claudeEdes = generateWithClaude(detections);
1121
+ const spinner = createSpinner("Generando EDEs con Claude Code...");
1122
+ const claudeEdes = await generateWithClaude(detections);
1061
1123
  if (claudeEdes && claudeEdes.length > 0) {
1124
+ spinner.succeed(
1125
+ `${claudeEdes.length} EDEs generadas con Claude Code (IA)`
1126
+ );
1062
1127
  return { proposals: claudeEdes, source: "claude" };
1063
1128
  }
1064
- onStatus?.("Claude no pudo generar EDEs, usando templates...");
1129
+ spinner.fail("Claude no pudo generar EDEs \u2014 usando templates");
1130
+ } else {
1131
+ process.stdout.write(
1132
+ " \u21B3 Claude Code no disponible \u2014 usando templates locales\n"
1133
+ );
1065
1134
  }
1066
1135
  return { proposals: generateFromTemplates(detections), source: "templates" };
1067
1136
  }
@@ -1500,18 +1569,7 @@ async function initCommand(options) {
1500
1569
  }
1501
1570
  }
1502
1571
  w("\n");
1503
- const { proposals, source } = generateProposals(
1504
- analysis.detections,
1505
- (msg) => w(` ${msg}
1506
- `)
1507
- );
1508
- if (source === "claude") {
1509
- w(` \u2713 ${proposals.length} EDEs generadas con Claude Code (IA)
1510
- `);
1511
- } else {
1512
- w(` \u21B3 EDEs generadas desde templates locales
1513
- `);
1514
- }
1572
+ const { proposals, source } = await generateProposals(analysis.detections);
1515
1573
  if (proposals.length === 0) {
1516
1574
  w("\n No hay propuestas de EDEs para generar.\n");
1517
1575
  w(" Configurando infraestructura base...\n\n");
@@ -1644,7 +1702,7 @@ async function mcpCommand() {
1644
1702
  }
1645
1703
 
1646
1704
  // src/commands/start.ts
1647
- import { execSync, spawn } from "child_process";
1705
+ import { execSync, spawn as spawn2 } from "child_process";
1648
1706
  import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync4 } from "fs";
1649
1707
  import { join as join15 } from "path";
1650
1708
  import { homedir as homedir3 } from "os";
@@ -1754,7 +1812,7 @@ async function startCommand(options) {
1754
1812
  stdio: "inherit"
1755
1813
  });
1756
1814
  } else {
1757
- const child = spawn("docker", ["compose", "-f", COMPOSE_PATH, "up"], {
1815
+ const child = spawn2("docker", ["compose", "-f", COMPOSE_PATH, "up"], {
1758
1816
  stdio: "inherit"
1759
1817
  });
1760
1818
  child.on("close", (code) => process.exit(code ?? 0));
@@ -1807,7 +1865,7 @@ function stopCommand() {
1807
1865
 
1808
1866
  // src/index.ts
1809
1867
  var program = new Command();
1810
- program.name("umbral").description("Umbral \u2014 Framework de gobernanza para proyectos con Claude Code").version("0.0.4");
1868
+ program.name("umbral").description("Umbral \u2014 Framework de gobernanza para proyectos con Claude Code").version("0.0.5");
1811
1869
  program.command("init").description("Inicializar Umbral en el proyecto actual").option("--yes", "Aceptar todas las propuestas sin preguntar").option("--path <path>", "Ruta al proyecto (default: directorio actual)").action(initCommand);
1812
1870
  program.command("start").description("Levantar la plataforma Umbral (Neo4j + Dashboard web)").option("--port <port>", "Puerto para el dashboard (default: auto)").option("--no-detach", "Correr en primer plano (sin -d)").action(startCommand);
1813
1871
  program.command("stop").description("Detener la plataforma Umbral").action(stopCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umbral/cli",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {