@semacode/cli 1.5.6 → 1.5.8

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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
2
+ import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { spawnSync } from "node:child_process";
5
5
  import { createRequire } from "node:module";
@@ -63,8 +63,9 @@ Comandos essenciais:
63
63
  - validacao: \`sema validar <arquivo.sema> --json\`
64
64
  - diagnosticos: \`sema diagnosticos <arquivo.sema> --json\`
65
65
  - formatacao: \`sema formatar <arquivo.sema>\`
66
- - importacao assistida de legado: \`sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> --saida <diretorio>\`
67
- - geracao de codigo: \`sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart|lua> --saida <diretorio>\`
66
+ - importacao assistida de legado: \`sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> --saida <diretorio>\`
67
+ - exemplos oficiais no projeto: \`sema instalar-exemplos\`
68
+ - geracao de codigo: \`sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart|lua> --saida <diretorio>\`
68
69
  - verificacao final: \`sema verificar <arquivo-ou-pasta> [--json]\`
69
70
 
70
71
  Antes de editar:
@@ -350,6 +351,65 @@ function resolverImportadorNodeOpcional(especificador) {
350
351
  }
351
352
  const TSX_IMPORTADOR_CLI = resolverImportadorNodeOpcional("tsx");
352
353
  const TSX_EXECUTOR_CLI = resolverImportadorNodeOpcional("tsx/cli");
354
+ async function caminhoEhDiretorio(caminhoAlvo) {
355
+ try {
356
+ return (await stat(caminhoAlvo)).isDirectory();
357
+ }
358
+ catch {
359
+ return false;
360
+ }
361
+ }
362
+ async function localizarDiretorioExemplosOficiais() {
363
+ const candidatos = [
364
+ path.resolve(DIRETORIO_CLI_ATUAL, "..", "exemplos"),
365
+ path.resolve(DIRETORIO_CLI_ATUAL, "..", "..", "..", "exemplos"),
366
+ ];
367
+ for (const candidato of candidatos) {
368
+ if (await caminhoEhDiretorio(candidato)) {
369
+ return candidato;
370
+ }
371
+ }
372
+ return undefined;
373
+ }
374
+ async function materializarExemplosOficiais(baseProjeto = process.cwd(), preservarExistentes = true) {
375
+ const origem = await localizarDiretorioExemplosOficiais();
376
+ const destino = path.resolve(baseProjeto, "exemplos");
377
+ if (!origem) {
378
+ return {
379
+ sucesso: false,
380
+ origem: null,
381
+ destino,
382
+ criados: [],
383
+ preservados: [],
384
+ erro: "Diretorio de exemplos oficiais nao foi encontrado no pacote da CLI.",
385
+ };
386
+ }
387
+ await mkdir(destino, { recursive: true });
388
+ const criados = [];
389
+ const preservados = [];
390
+ const entradas = await readdir(origem, { withFileTypes: true });
391
+ for (const entrada of entradas.sort((a, b) => a.name.localeCompare(b.name, "pt-BR"))) {
392
+ if (!entrada.isFile() || !entrada.name.endsWith(".sema")) {
393
+ continue;
394
+ }
395
+ const origemArquivo = path.join(origem, entrada.name);
396
+ const destinoArquivo = path.join(destino, entrada.name);
397
+ const jaExiste = await caminhoExiste(destinoArquivo);
398
+ if (jaExiste && preservarExistentes) {
399
+ preservados.push(entrada.name);
400
+ continue;
401
+ }
402
+ await writeFile(destinoArquivo, await readFile(origemArquivo, "utf8"), "utf8");
403
+ criados.push(entrada.name);
404
+ }
405
+ return {
406
+ sucesso: true,
407
+ origem,
408
+ destino,
409
+ criados,
410
+ preservados,
411
+ };
412
+ }
353
413
  function obterArgumentos() {
354
414
  const [, , comando, ...resto] = process.argv;
355
415
  return { comando: comando, resto };
@@ -430,6 +490,7 @@ function ajuda() {
430
490
  "sema exemplos-prompt-ia",
431
491
  "sema contexto-ia <arquivo.sema> [--saida <diretorio>] [--json]",
432
492
  "sema sync-ai-entrypoints [--json]",
493
+ "sema instalar-exemplos [--json]",
433
494
  ]),
434
495
  "",
435
496
  renderizarSecaoAscii("Operacional", [
@@ -3177,7 +3238,34 @@ public:
3177
3238
  ];
3178
3239
  }
3179
3240
  await escreverArquivos(cwd, arquivos);
3241
+ const exemplos = await materializarExemplosOficiais(cwd, true);
3242
+ if (!exemplos.sucesso) {
3243
+ console.error(exemplos.erro);
3244
+ return 1;
3245
+ }
3180
3246
  console.log(`Projeto Sema inicializado com template ${template}.`);
3247
+ console.log(`Exemplos oficiais sincronizados em ${exemplos.destino} (${exemplos.criados.length} criados, ${exemplos.preservados.length} preservados).`);
3248
+ return 0;
3249
+ }
3250
+ async function comandoInstalarExemplos(emJson) {
3251
+ const resultado = await materializarExemplosOficiais(process.cwd(), true);
3252
+ const payload = {
3253
+ comando: "instalar-exemplos",
3254
+ ...resultado,
3255
+ };
3256
+ if (emJson) {
3257
+ console.log(JSON.stringify(payload, null, 2));
3258
+ return resultado.sucesso ? 0 : 1;
3259
+ }
3260
+ if (!resultado.sucesso) {
3261
+ console.error(resultado.erro ?? "Falha ao instalar exemplos oficiais.");
3262
+ return 1;
3263
+ }
3264
+ console.log("Exemplos oficiais sincronizados");
3265
+ console.log(`- Origem: ${resultado.origem}`);
3266
+ console.log(`- Destino: ${resultado.destino}`);
3267
+ console.log(`- Criados: ${resultado.criados.length}`);
3268
+ console.log(`- Preservados: ${resultado.preservados.length}`);
3181
3269
  return 0;
3182
3270
  }
3183
3271
  async function comandoValidar(entrada) {
@@ -3639,10 +3727,26 @@ async function comandoStarterIa() {
3639
3727
  }
3640
3728
  async function comandoSyncAiEntrypoints(emJson) {
3641
3729
  const resumoProjeto = await gerarResumoProjetoIa(process.cwd(), undefined, true);
3730
+ const exemplos = await materializarExemplosOficiais(resumoProjeto.baseProjeto, true);
3731
+ if (!exemplos.sucesso) {
3732
+ if (emJson) {
3733
+ console.log(JSON.stringify({
3734
+ comando: "sync-ai-entrypoints",
3735
+ sucesso: false,
3736
+ baseProjeto: resumoProjeto.baseProjeto,
3737
+ erro: exemplos.erro,
3738
+ exemplos,
3739
+ }, null, 2));
3740
+ return 1;
3741
+ }
3742
+ console.error(exemplos.erro);
3743
+ return 1;
3744
+ }
3642
3745
  const indexJson = JSON.parse(await readFile(path.join(resumoProjeto.pastaSaida, "SEMA_INDEX.json"), "utf8"));
3643
3746
  const artefatos = [...new Set([
3644
3747
  ...ARQUIVOS_CANONICOS_IA_RAIZ,
3645
3748
  ...resumoProjeto.artefatos,
3749
+ "exemplos",
3646
3750
  ])];
3647
3751
  if (emJson) {
3648
3752
  console.log(JSON.stringify({
@@ -3652,6 +3756,7 @@ async function comandoSyncAiEntrypoints(emJson) {
3652
3756
  pastaSaida: resumoProjeto.pastaSaida,
3653
3757
  artefatos,
3654
3758
  entradaCanonica: indexJson.entradaCanonica,
3759
+ exemplos,
3655
3760
  }, null, 2));
3656
3761
  return 0;
3657
3762
  }
@@ -3662,6 +3767,7 @@ async function comandoSyncAiEntrypoints(emJson) {
3662
3767
  console.log(`IA pequena: ${indexJson.entradaCanonica.porCapacidade.pequena.join(" -> ")}`);
3663
3768
  console.log(`IA media: ${indexJson.entradaCanonica.porCapacidade.media.join(" -> ")}`);
3664
3769
  console.log(`IA grande: ${indexJson.entradaCanonica.porCapacidade.grande.join(" -> ")}`);
3770
+ console.log(`Exemplos oficiais: ${exemplos.criados.length} criados, ${exemplos.preservados.length} preservados em ${exemplos.destino}`);
3665
3771
  return 0;
3666
3772
  }
3667
3773
  async function comandoAjudaIa() {
@@ -3690,6 +3796,7 @@ async function comandoAjudaIa() {
3690
3796
  console.log(renderizarSecaoAscii("Fluxo recomendado", [
3691
3797
  "Use `sema starter-ia` para um texto curto de onboarding.",
3692
3798
  "Use `sema sync-ai-entrypoints` para regenerar `SEMA_BRIEF.*` e `SEMA_INDEX.json` na raiz.",
3799
+ "Use `sema instalar-exemplos` para materializar `exemplos/` oficiais sem sobrescrever arquivos locais.",
3693
3800
  "Use `sema resumo <arquivo> --micro --para onboarding` para IA pequena.",
3694
3801
  "Use `sema prompt-curto <arquivo> --curto --para mudanca` para colar contexto em modelo gratuito.",
3695
3802
  "Use `sema prompt-ia`, `sema prompt-ia-ui`, `sema prompt-ia-react` e `sema prompt-ia-sema-primeiro` conforme a tarefa.",
@@ -4201,6 +4308,9 @@ async function principal() {
4201
4308
  case "sync-ai-entrypoints":
4202
4309
  codigoSaida = await comandoSyncAiEntrypoints(possuiFlag(resto, "--json"));
4203
4310
  break;
4311
+ case "instalar-exemplos":
4312
+ codigoSaida = await comandoInstalarExemplos(possuiFlag(resto, "--json"));
4313
+ break;
4204
4314
  case "resumo":
4205
4315
  codigoSaida = await comandoResumo(posicionais[0], resto, possuiFlag(resto, "--json"));
4206
4316
  break;