sabia 2.0.2 → 2.0.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/package.json +1 -1
  2. package/sabia.mjs +32 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sabia",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "Instala, atualiza e desinstala o Sabiá e os toolkits dele no Kiro e no opencode, com um inventário em ~/.sabia/, e explica a rota dos fluxos (sabia rota).",
5
5
  "type": "module",
6
6
  "bin": {
package/sabia.mjs CHANGED
@@ -362,6 +362,7 @@ function mostrarDiferencas(dif) {
362
362
  }
363
363
 
364
364
  export async function instalar(opcoes = {}) {
365
+ if (process.stdout.isTTY) ctx.log(BANNER + "\n");
365
366
  const inv = lerInventario();
366
367
  const novo = baixarFramework(opcoes);
367
368
  fs.rmSync(sabia("framework"), { recursive: true, force: true });
@@ -887,6 +888,8 @@ export function rotaMapa(opcoes = {}) {
887
888
 
888
889
  const AJUDA = `sabia ${VERSAO} — instala o Sabiá e os toolkits no Kiro e no opencode
889
890
 
891
+ sabia (sem comando, no terminal) modo interativo: o banner uma vez e um prompt para vários comandos
892
+
890
893
  sabia instalar [--alvo kiro,opencode] [--versao X] [--fonte <pasta|url-git>[@ref]]
891
894
  sabia atualizar [--versao X] [--fonte <pasta|url-git>[@ref]]
892
895
  sabia desinstalar [--alvo …]
@@ -921,16 +924,39 @@ export function lerArgs(argv) {
921
924
  return { posicionais, opcoes };
922
925
  }
923
926
 
924
- export async function main(argv = process.argv.slice(2)) {
927
+ /** `sabia` sem comando, no terminal: o banner uma vez e um prompt; cada linha é um comando, até "sair". */
928
+ export async function interativo(entrada) {
929
+ ctx.log(BANNER + "\n\nDigite um comando (ex.: toolkits listar), ajuda ou sair.\n");
930
+ const rl = entrada ? null : readline.createInterface({ input: process.stdin, output: process.stdout });
931
+ const antes = ctx.perguntar;
932
+ // as confirmações dos comandos usam o mesmo prompt: dois readline no mesmo stdin brigam pela linha
933
+ if (rl) ctx.perguntar = async (texto, padrao) => { const r = (await rl.question(`${texto} `)).trim(); return r === "" ? padrao : r; };
934
+ const linhas = entrada ?? (async function* () { for (;;) { try { yield await rl.question("sabia › "); } catch { return; } } })();
935
+ try {
936
+ for await (const linha of linhas) {
937
+ const args = linha.trim().split(/\s+/).filter(Boolean);
938
+ if (args[0] === "sabia") args.shift();
939
+ if (!args.length) continue;
940
+ if (["sair", "exit", "quit"].includes(args[0])) break;
941
+ await main(args.length === 1 && args[0] === "ajuda" ? ["--ajuda"] : args, { dentro: true });
942
+ }
943
+ } finally {
944
+ ctx.perguntar = antes;
945
+ rl?.close();
946
+ }
947
+ return 0;
948
+ }
949
+
950
+ export async function main(argv = process.argv.slice(2), { dentro = false } = {}) {
925
951
  let args;
926
952
  try { args = lerArgs(argv); } catch (e) { console.error(`sabia: ${e.message}`); return 1; }
927
953
  const { posicionais: [cmd, sub, arg], opcoes } = args;
954
+ if (!cmd && !opcoes.ajuda && !opcoes.help && !dentro && process.stdin.isTTY && process.stdout.isTTY) return interativo();
955
+ const perguntarAntes = ctx.perguntar; // o --sim vale só para este comando (no modo interativo vêm outros)
928
956
  if (opcoes.sim) { // cópia alterada à mão continua perguntando: só o --forcar passa por cima
929
957
  const antes = ctx.perguntar;
930
958
  ctx.perguntar = async (texto, padrao) => (/alterado à mão/.test(texto) ? antes(texto, padrao) : /\[s\/N\]/.test(texto) ? "s" : padrao);
931
959
  }
932
- // o banner em todo comando, só no terminal: em pipe ou arquivo (o Mermaid do rota) a saída fica limpa
933
- if (process.stdout.isTTY) ctx.log(BANNER + "\n");
934
960
  try {
935
961
  if (cmd === "instalar") await instalar(opcoes);
936
962
  else if (cmd === "atualizar") await atualizar(opcoes);
@@ -942,11 +968,13 @@ export async function main(argv = process.argv.slice(2)) {
942
968
  else if (cmd === "toolkits" && sub === "remover" && arg) await removerToolkit(arg, opcoes);
943
969
  else if (cmd === "rota" && (sub || opcoes.fluxo || opcoes.mapa))
944
970
  ctx.log(opcoes.mapa ? rotaMapa(opcoes) : opcoes.fluxo ? rotaFluxo(opcoes.fluxo, opcoes) : rota(sub, opcoes));
945
- else { ctx.log(AJUDA); return cmd && !opcoes.ajuda && !opcoes.help ? 1 : 0; }
971
+ else { ctx.log((!dentro && process.stdout.isTTY ? BANNER + "\n\n" : "") + AJUDA); return cmd && !opcoes.ajuda && !opcoes.help ? 1 : 0; }
946
972
  return 0;
947
973
  } catch (e) {
948
974
  console.error(`sabia: ${e.message}`);
949
975
  return 1;
976
+ } finally {
977
+ ctx.perguntar = perguntarAntes;
950
978
  }
951
979
  }
952
980