@semacode/cli 2.3.1 → 3.5.0
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/README.md +265 -217
- package/dist/agentContextPack.js +14 -10
- package/dist/agentEntryPoints.d.ts +5 -0
- package/dist/agentEntryPoints.js +592 -568
- package/dist/angular-consumer-standalone.js +1 -1
- package/dist/bin.d.ts +6 -0
- package/dist/bin.js +130 -0
- package/dist/cliArgs.js +4 -4
- package/dist/cliControlError.d.ts +12 -0
- package/dist/cliControlError.js +47 -0
- package/dist/cliGrammar.d.ts +11 -0
- package/dist/cliGrammar.js +551 -0
- package/dist/cliHelp.d.ts +13 -0
- package/dist/cliHelp.js +19 -0
- package/dist/cliHelpTexto.d.ts +3 -0
- package/dist/cliHelpTexto.js +168 -0
- package/dist/cliRuntime.d.ts +2 -0
- package/dist/cliRuntime.js +31 -0
- package/dist/comandos.js +9 -22
- package/dist/contexto.js +5 -5
- package/dist/dev/index.d.ts +1 -0
- package/dist/dev/index.js +51 -9
- package/dist/discovery/catalog.js +3 -3
- package/dist/distribuicao/filesystemGlobal.d.ts +63 -0
- package/dist/distribuicao/filesystemGlobal.js +701 -0
- package/dist/distribuicao/index.d.ts +7 -0
- package/dist/distribuicao/index.js +227 -0
- package/dist/distribuicao/launcherGlobal.d.ts +53 -0
- package/dist/distribuicao/launcherGlobal.js +643 -0
- package/dist/distribuicao/launcherWindows.d.ts +28 -0
- package/dist/distribuicao/launcherWindows.js +326 -0
- package/dist/distribuicao/lockContextGlobal.d.ts +10 -0
- package/dist/distribuicao/lockContextGlobal.js +17 -0
- package/dist/distribuicao/lockGlobal.d.ts +6 -0
- package/dist/distribuicao/lockGlobal.js +520 -0
- package/dist/distribuicao/skillGlobal.d.ts +48 -0
- package/dist/distribuicao/skillGlobal.js +652 -0
- package/dist/distribuicao/skillIntentPolicy.d.ts +21 -0
- package/dist/distribuicao/skillIntentPolicy.js +115 -0
- package/dist/distribuicao/tipos.d.ts +50 -0
- package/dist/distribuicao/tipos.js +10 -0
- package/dist/distribuicao/versaoSemantica.d.ts +3 -0
- package/dist/distribuicao/versaoSemantica.js +62 -0
- package/dist/docs.part01.d.ts +4 -1
- package/dist/docs.part01.js +8 -0
- package/dist/docs.part02.js +9 -1
- package/dist/drift.part01.d.ts +33 -25
- package/dist/drift.part01.js +2 -1
- package/dist/drift.part04.d.ts +26 -5
- package/dist/drift.part04.js +123 -19
- package/dist/drift.part05.d.ts +2 -2
- package/dist/drift.part05.js +8 -6
- package/dist/drift.part06.d.ts +2 -2
- package/dist/drift.part06.js +113 -26
- package/dist/drift.part07.d.ts +11 -11
- package/dist/drift.part07.js +261 -265
- package/dist/drift.part08.d.ts +2 -2
- package/dist/drift.part08.js +35 -26
- package/dist/drift.part09.d.ts +2 -2
- package/dist/drift.part09.js +10 -3
- package/dist/drift.part11.js +261 -58
- package/dist/drift.part12.d.ts +1 -1
- package/dist/drift.part12.js +193 -21
- package/dist/drift.part13.d.ts +20 -39
- package/dist/drift.part13.js +601 -647
- package/dist/drift.part14.js +23 -7
- package/dist/driftCacheCas.d.ts +43 -0
- package/dist/driftCacheCas.js +351 -0
- package/dist/driftCacheFilesystem.d.ts +64 -0
- package/dist/driftCacheFilesystem.js +313 -0
- package/dist/driftCacheModes.d.ts +38 -0
- package/dist/driftCacheModes.js +147 -0
- package/dist/driftCacheStore.d.ts +80 -0
- package/dist/driftCacheStore.js +603 -0
- package/dist/driftCatalogo.d.ts +2 -28
- package/dist/driftCatalogo.js +143 -284
- package/dist/driftEscopo.d.ts +1 -3
- package/dist/driftEscopo.js +235 -151
- package/dist/driftEscopoReferencias.d.ts +5 -1
- package/dist/driftEscopoReferencias.js +375 -28
- package/dist/driftOrcamento.d.ts +0 -6
- package/dist/driftOrcamento.js +2 -1
- package/dist/execucoesExternas.js +19 -5
- package/dist/exemplosOficiais.d.ts +2 -1
- package/dist/exemplosOficiais.js +9 -3
- package/dist/geracaoCore.d.ts +1 -0
- package/dist/geracaoCore.js +6 -6
- package/dist/iaPrompts.d.ts +3 -3
- package/dist/iaPrompts.js +312 -313
- package/dist/importador.part01.d.ts +1 -1
- package/dist/importador.part06.d.ts +2 -0
- package/dist/importador.part06.js +87 -1
- package/dist/importador.part09.js +7 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +6 -25
- package/dist/index.part01.d.ts +20 -28
- package/dist/index.part01.js +16 -237
- package/dist/index.part02.js +36 -22
- package/dist/index.part03.d.ts +24 -2
- package/dist/index.part03.js +83 -19
- package/dist/index.part04.d.ts +10 -2
- package/dist/index.part04.js +152 -123
- package/dist/index.part05.js +80 -78
- package/dist/index.part06.js +34 -17
- package/dist/index.part07.d.ts +8 -2
- package/dist/index.part07.js +153 -7
- package/dist/index.part08.d.ts +1 -1
- package/dist/index.part08.js +25 -30
- package/dist/initCommand.d.ts +1 -0
- package/dist/initCommand.js +20 -4
- package/dist/initTemplatesBase.js +6 -4
- package/dist/pipelineConteudo/command.d.ts +1 -0
- package/dist/pipelineConteudo/command.js +9 -2
- package/dist/pipelineConteudo/help.d.ts +2 -0
- package/dist/pipelineConteudo/help.js +33 -0
- package/dist/profileAuthorCommand.js +3 -7
- package/dist/profileCommand.js +3 -7
- package/dist/projetoCarregar.js +35 -17
- package/dist/projetoCatalogo.d.ts +1 -0
- package/dist/projetoCatalogo.js +64 -25
- package/dist/projetoConfig.js +2 -0
- package/dist/projetoLegado.js +18 -0
- package/dist/projetoOrigens.d.ts +2 -0
- package/dist/projetoOrigens.js +65 -9
- package/dist/projetoTipos.d.ts +1 -0
- package/dist/resultadoCli.d.ts +20 -0
- package/dist/resultadoCli.js +57 -0
- package/dist/saidaCli.d.ts +35 -0
- package/dist/saidaCli.js +118 -0
- package/dist/sistemasInterativos/acceptanceEvidence.d.ts +22 -0
- package/dist/sistemasInterativos/acceptanceEvidence.js +345 -0
- package/dist/sistemasInterativos/engineObservation.d.ts +12 -0
- package/dist/sistemasInterativos/engineObservation.js +438 -0
- package/dist/sistemasInterativos/jobOrchestration.d.ts +2 -0
- package/dist/sistemasInterativos/jobOrchestration.js +204 -0
- package/dist/sistemasInterativos/operationPrimitives.d.ts +21 -0
- package/dist/sistemasInterativos/operationPrimitives.js +194 -0
- package/dist/sistemasInterativos/operations.d.ts +4 -39
- package/dist/sistemasInterativos/operations.js +5 -1164
- package/dist/skillCommand.d.ts +5 -0
- package/dist/skillCommand.js +88 -0
- package/dist/tipos.d.ts +1 -1
- package/dist/typescript-http-modelos.d.ts +1 -1
- package/dist/typescript-http-rotas.d.ts +1 -0
- package/dist/typescript-http-rotas.js +93 -0
- package/dist/typescript-http.d.ts +1 -1
- package/dist/typescript-http.js +1 -1
- package/dist/verificacaoCache.d.ts +25 -0
- package/dist/verificacaoCache.js +80 -0
- package/docs/README.md +34 -30
- package/docs/ai-integration.md +25 -12
- package/docs/ai-onboarding.md +37 -18
- package/docs/ai-workflow.md +9 -7
- package/docs/cli.md +125 -7
- package/docs/commands.md +41 -20
- package/docs/deploy.md +21 -8
- package/docs/descoberta-capacidades.md +106 -106
- package/docs/documentation.md +49 -39
- package/docs/drift-cache.md +108 -0
- package/docs/getting-started.md +43 -18
- package/docs/pipeline-conteudo.md +246 -246
- package/docs/profiles.md +54 -54
- package/docs/repositories.md +19 -2
- package/docs/rollback.md +15 -8
- package/docs/security.md +25 -3
- package/docs/sistemas-interativos.md +379 -374
- package/docs/syntax.md +14 -0
- package/docs/testing.md +139 -40
- package/exemplos/express_crud.sema +139 -0
- package/exemplos/fastify_crud.sema +146 -0
- package/exemplos/pipeline-conteudo/README.md +44 -44
- package/exemplos/pipeline-conteudo/alvos.json +23 -23
- package/exemplos/pipeline-conteudo/definicao.json +136 -136
- package/exemplos/profile_simulation.sema +211 -211
- package/exemplos/sistemas-interativos/README.md +100 -100
- package/exemplos/sistemas-interativos/advanced/acceptance-context-evaluate-valid.json +5 -5
- package/exemplos/sistemas-interativos/advanced/acceptance-lock-valid.json +16 -16
- package/exemplos/sistemas-interativos/advanced/asset-provenance-valid.json +32 -32
- package/exemplos/sistemas-interativos/advanced/autonomy-repair-valid.json +93 -93
- package/exemplos/sistemas-interativos/advanced/control-run-definition-valid.json +78 -78
- package/exemplos/sistemas-interativos/advanced/control-run-valid.json +27 -27
- package/exemplos/sistemas-interativos/advanced/distributed-workers-valid.json +79 -79
- package/exemplos/sistemas-interativos/advanced/editor-state-valid.json +42 -42
- package/exemplos/sistemas-interativos/advanced/engine-snapshot-after-valid.json +32 -32
- package/exemplos/sistemas-interativos/advanced/engine-snapshot-before-valid.json +23 -23
- package/exemplos/sistemas-interativos/advanced/job-orchestration-valid.json +39 -39
- package/exemplos/sistemas-interativos/advanced/multimodal-evidence-valid.json +46 -46
- package/exemplos/sistemas-interativos/advanced/multiplayer-authority-valid.json +39 -39
- package/exemplos/sistemas-interativos/advanced/playtest-fuzz-valid.json +37 -37
- package/exemplos/sistemas-interativos/advanced/portability-valid.json +104 -104
- package/exemplos/sistemas-interativos/advanced/temporal-evidence-valid.json +27 -27
- package/exemplos/sistemas-interativos/advanced/temporal-valid.json +118 -118
- package/exemplos/sistemas-interativos/experience-ir-valid.json +459 -459
- package/exemplos/sistemas-interativos/game-2d.json +83 -83
- package/exemplos/sistemas-interativos/game-3d-human.json +81 -81
- package/exemplos/sistemas-interativos/game-pixel-16-bit.json +97 -97
- package/exemplos/sistemas-interativos/game-pixel-8-bit.json +94 -94
- package/exemplos/sistemas-interativos/game-xr-human.json +80 -80
- package/exemplos/sistemas-interativos/hybrid-2-5d.json +108 -108
- package/exemplos/sistemas-interativos/protocol-mutating-rollback-valid.json +75 -75
- package/exemplos/sistemas-interativos/protocol-read-only-valid.json +58 -58
- package/exemplos/sistemas-interativos/simulation-2d-controlled.json +97 -97
- package/exemplos/sistemas-interativos/simulation-3d-calibrated-autonomous.json +141 -141
- package/exemplos/sistemas-interativos/simulation-headless-autonomous-batch.json +112 -112
- package/exemplos/sistemas-interativos/simulation-pixel-16-bit.json +103 -103
- package/exemplos/sistemas-interativos/simulation-text-controlled.json +95 -95
- package/node_modules/@sema/gerador-cpp/package.json +1 -1
- package/node_modules/@sema/gerador-dotnet/package.json +1 -1
- package/node_modules/@sema/gerador-lua/dist/index.js +51 -51
- package/node_modules/@sema/gerador-php/dist/index.js +113 -113
- package/node_modules/@sema/nucleo/dist/ir/conversor.part01.js +37 -38
- package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +1 -0
- package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +1 -0
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js +1 -0
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part01.d.ts +7 -0
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part01.js +33 -10
- package/package.json +9 -4
- package/scripts/postinstall.mjs +148 -0
- package/skills/sema/SKILL.md +199 -0
- package/skills/sema/agents/openai.yaml +4 -0
- package/dist/driftCache.d.ts +0 -49
- package/dist/driftCache.js +0 -311
- package/dist/driftCacheIncremental.d.ts +0 -98
- package/dist/driftCacheIncremental.js +0 -596
- package/dist/driftCatalogoPersistente.d.ts +0 -8
- package/dist/driftCatalogoPersistente.js +0 -77
- package/node_modules/@sema/gerador-cpp/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-css/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-css/dist/index.part01.js.map +0 -1
- package/node_modules/@sema/gerador-css/dist/index.part02.js.map +0 -1
- package/node_modules/@sema/gerador-dart/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-dotnet/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-html/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-javascript/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-lua/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-php/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-python/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-python/dist/index.part01.js.map +0 -1
- package/node_modules/@sema/gerador-python/dist/index.part02.js.map +0 -1
- package/node_modules/@sema/gerador-typescript/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-typescript/dist/index.part01.js.map +0 -1
- package/node_modules/@sema/gerador-typescript/dist/index.part02.js.map +0 -1
- package/node_modules/@sema/gerador-typescript/dist/index.part03.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/ast/tipos.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/diagnosticos/index.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/diagnosticos/melhorador.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/diagnosticos/snippets.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/formatador/index.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/formatador/index.part01.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/formatador/index.part02.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/index.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/ir/conversor.part01.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/ir/conversor.part02.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/ir/conversor.part03.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/ir/modelos.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/parser/parser.declaracoes.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/parser/parser.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/parser/parser.modulo.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/parser/parser.part01.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/parser/parser.part02.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/parser/parser.part03.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/persistencia/contratos.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part01.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part02.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part03.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part04.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part05.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part06.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part07.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.part08.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.part01.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.part02.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/orcamentoSemantico.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/seguranca.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/util/arquivos.js.map +0 -1
- package/node_modules/@sema/padroes/dist/index.js.map +0 -1
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
// SEMA-GOVERNED: sema.produto.distribuicao_global
|
|
2
|
+
// Descrição: instala somente a allowlist empacotada da skill Sema em destinos globais explicitamente permitidos.
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { readdir, realpath } from "node:fs/promises";
|
|
8
|
+
import { FalhaDistribuicaoGlobal, caminhoContido, escreverArquivoAtomico, falhaParaResultado, garantirDiretoriosSeguros, identidadeDiretorioSeguro, lerArquivoSeguro, lstatOuNull, moverDiretorioSeguro, nomeTemporarioDiretorio, removerDiretorioTemporarioGerenciado, resolverDentroDaHome, resolverHomeReal, statDiretorioSeguro, validarArquivoRegular, validarCadeiaExistente, } from "./filesystemGlobal.js";
|
|
9
|
+
import { comLockDistribuicaoGlobal } from "./lockGlobal.js";
|
|
10
|
+
import { versaoSemanticaValida } from "./versaoSemantica.js";
|
|
11
|
+
export const ARQUIVOS_SKILL_SEMA_GERENCIADOS = [
|
|
12
|
+
"SKILL.md",
|
|
13
|
+
"agents/openai.yaml",
|
|
14
|
+
];
|
|
15
|
+
export const NOME_RECIBO_SKILL_SEMA = ".sema-managed.json";
|
|
16
|
+
const ESQUEMA_RECIBO = "sema.skill-install-receipt/v1";
|
|
17
|
+
const GERENCIADOR_RECIBO = "@semacode/cli";
|
|
18
|
+
const RAIZ_PACOTE_PADRAO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
19
|
+
const LIMITE_ARQUIVO_SKILL = 2 * 1024 * 1024;
|
|
20
|
+
const LIMITE_RECIBO = 32 * 1024;
|
|
21
|
+
function sha256(bytes) {
|
|
22
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
23
|
+
}
|
|
24
|
+
function chavesExatas(valor, esperadas) {
|
|
25
|
+
const atuais = Object.keys(valor).sort();
|
|
26
|
+
return atuais.length === esperadas.length
|
|
27
|
+
&& atuais.every((chave, indice) => chave === [...esperadas].sort()[indice]);
|
|
28
|
+
}
|
|
29
|
+
function resultadoDestino(destino, estado, codigo, alterado = false) {
|
|
30
|
+
return {
|
|
31
|
+
id: destino.id,
|
|
32
|
+
estado,
|
|
33
|
+
alterado,
|
|
34
|
+
destino_simbolico: destino.virtual,
|
|
35
|
+
codigo,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function destinoCanonico(homeReal) {
|
|
39
|
+
return {
|
|
40
|
+
id: "agents",
|
|
41
|
+
caminho: resolverDentroDaHome(homeReal, ".agents", "skills", "sema"),
|
|
42
|
+
virtual: "$HOME/.agents/skills/sema",
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function destinoClaude(homeReal) {
|
|
46
|
+
return {
|
|
47
|
+
id: "claude",
|
|
48
|
+
caminho: resolverDentroDaHome(homeReal, ".claude", "skills", "sema"),
|
|
49
|
+
virtual: "$HOME/.claude/skills/sema",
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function prioridadeEstado(estado) {
|
|
53
|
+
return {
|
|
54
|
+
READY: 0,
|
|
55
|
+
MISSING: 1,
|
|
56
|
+
STALE: 2,
|
|
57
|
+
BROKEN_TARGET: 3,
|
|
58
|
+
PERMISSION_DENIED: 4,
|
|
59
|
+
}[estado];
|
|
60
|
+
}
|
|
61
|
+
function agregar(destinos, espelhoClaudeDetectado) {
|
|
62
|
+
const estado = destinos.reduce((pior, atual) => prioridadeEstado(atual.estado) > prioridadeEstado(pior)
|
|
63
|
+
? atual.estado
|
|
64
|
+
: pior, "READY");
|
|
65
|
+
const agents = destinos.find((destino) => destino.id === "agents");
|
|
66
|
+
const claude = destinos.find((destino) => destino.id === "claude");
|
|
67
|
+
return {
|
|
68
|
+
estado,
|
|
69
|
+
alterado: destinos.some((destino) => destino.alterado),
|
|
70
|
+
origem_simbolica: "$PACKAGE_ROOT/skills/sema",
|
|
71
|
+
destino_agents: agents?.estado ?? "BROKEN_TARGET",
|
|
72
|
+
destino_claude: claude?.estado ?? "NOT_DETECTED",
|
|
73
|
+
espelho_claude_detectado: espelhoClaudeDetectado,
|
|
74
|
+
ownership_valido: destinos.every((destino) => (destino.estado === "READY" || destino.estado === "STALE")),
|
|
75
|
+
digest_alinhado: destinos.every((destino) => destino.estado === "READY"),
|
|
76
|
+
cache_plugin_intocado: true,
|
|
77
|
+
destinos,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function resultadoBloqueiaMutacao(resultado) {
|
|
81
|
+
return resultado.destinos.some((destino) => (destino.estado === "BROKEN_TARGET"
|
|
82
|
+
|| destino.estado === "PERMISSION_DENIED"));
|
|
83
|
+
}
|
|
84
|
+
function resultadoInteiramenteReady(resultado) {
|
|
85
|
+
return resultado.estado === "READY"
|
|
86
|
+
&& resultado.destinos.length > 0
|
|
87
|
+
&& resultado.destinos.every((destino) => destino.estado === "READY");
|
|
88
|
+
}
|
|
89
|
+
function semAlteracao(resultado) {
|
|
90
|
+
return {
|
|
91
|
+
...resultado,
|
|
92
|
+
alterado: false,
|
|
93
|
+
destinos: resultado.destinos.map((destino) => ({ ...destino, alterado: false })),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function comAlteracoesConfirmadas(final, sincronizado) {
|
|
97
|
+
const alteracoes = new Map(sincronizado.destinos.map((destino) => [
|
|
98
|
+
destino.id,
|
|
99
|
+
destino.alterado,
|
|
100
|
+
]));
|
|
101
|
+
const destinos = final.destinos.map((destino) => ({
|
|
102
|
+
...destino,
|
|
103
|
+
alterado: alteracoes.get(destino.id) ?? false,
|
|
104
|
+
}));
|
|
105
|
+
return {
|
|
106
|
+
...final,
|
|
107
|
+
alterado: destinos.some((destino) => destino.alterado),
|
|
108
|
+
destinos,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function falhaRollback(resultadoAtual) {
|
|
112
|
+
return {
|
|
113
|
+
...resultadoAtual,
|
|
114
|
+
estado: "BROKEN_TARGET",
|
|
115
|
+
alterado: true,
|
|
116
|
+
destino_agents: "BROKEN_TARGET",
|
|
117
|
+
destino_claude: resultadoAtual.espelho_claude_detectado
|
|
118
|
+
? "BROKEN_TARGET"
|
|
119
|
+
: "NOT_DETECTED",
|
|
120
|
+
ownership_valido: false,
|
|
121
|
+
digest_alinhado: false,
|
|
122
|
+
destinos: resultadoAtual.destinos.map((destino) => ({
|
|
123
|
+
...destino,
|
|
124
|
+
estado: "BROKEN_TARGET",
|
|
125
|
+
alterado: true,
|
|
126
|
+
codigo: "ROLLBACK_FALHOU",
|
|
127
|
+
})),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function validarVersaoPacote(valor) {
|
|
131
|
+
if (!versaoSemanticaValida(valor)) {
|
|
132
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "PACOTE_INVALIDO");
|
|
133
|
+
}
|
|
134
|
+
return valor;
|
|
135
|
+
}
|
|
136
|
+
async function carregarSnapshot(opcoes) {
|
|
137
|
+
const raizInformada = opcoes.raizPacote ?? RAIZ_PACOTE_PADRAO;
|
|
138
|
+
if (!path.isAbsolute(raizInformada) || raizInformada.includes("\0")) {
|
|
139
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "PACOTE_INVALIDO");
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const raizPacote = await realpath(path.resolve(raizInformada));
|
|
143
|
+
await statDiretorioSeguro(raizPacote);
|
|
144
|
+
const origem = path.resolve(raizPacote, "skills", "sema");
|
|
145
|
+
if (!caminhoContido(raizPacote, origem)) {
|
|
146
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "PACOTE_INVALIDO");
|
|
147
|
+
}
|
|
148
|
+
await statDiretorioSeguro(path.join(raizPacote, "skills"));
|
|
149
|
+
await statDiretorioSeguro(origem);
|
|
150
|
+
await statDiretorioSeguro(path.join(origem, "agents"));
|
|
151
|
+
const pacoteJson = JSON.parse((await lerArquivoSeguro(path.join(raizPacote, "package.json"), LIMITE_RECIBO, raizPacote)).toString("utf8"));
|
|
152
|
+
if (pacoteJson.name !== GERENCIADOR_RECIBO) {
|
|
153
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "PACOTE_INVALIDO");
|
|
154
|
+
}
|
|
155
|
+
const packageVersion = validarVersaoPacote(pacoteJson.version);
|
|
156
|
+
const arquivos = new Map();
|
|
157
|
+
const hashes = {};
|
|
158
|
+
for (const relativo of ARQUIVOS_SKILL_SEMA_GERENCIADOS) {
|
|
159
|
+
const absoluto = path.resolve(origem, ...relativo.split("/"));
|
|
160
|
+
if (!caminhoContido(origem, absoluto)) {
|
|
161
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "PACOTE_INVALIDO");
|
|
162
|
+
}
|
|
163
|
+
const bytes = await lerArquivoSeguro(absoluto, LIMITE_ARQUIVO_SKILL, origem);
|
|
164
|
+
arquivos.set(relativo, bytes);
|
|
165
|
+
hashes[relativo] = sha256(bytes);
|
|
166
|
+
}
|
|
167
|
+
const recibo = {
|
|
168
|
+
schema: ESQUEMA_RECIBO,
|
|
169
|
+
manager: GERENCIADOR_RECIBO,
|
|
170
|
+
skill: "sema",
|
|
171
|
+
packageVersion,
|
|
172
|
+
files: hashes,
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
raizPacote,
|
|
176
|
+
origem,
|
|
177
|
+
arquivos,
|
|
178
|
+
recibo,
|
|
179
|
+
reciboTexto: `${JSON.stringify(recibo, null, 2)}\n`,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
catch (erro) {
|
|
183
|
+
const falha = falhaParaResultado(erro);
|
|
184
|
+
if (falha.estado === "PERMISSION_DENIED")
|
|
185
|
+
throw falha;
|
|
186
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "PACOTE_INVALIDO");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async function resolverAmbiente(opcoes) {
|
|
190
|
+
const homeReal = await resolverHomeReal(opcoes.diretorioUsuario ?? os.homedir());
|
|
191
|
+
const claudeRaiz = resolverDentroDaHome(homeReal, ".claude");
|
|
192
|
+
const espelhoClaudeDetectado = (await lstatOuNull(claudeRaiz)) !== null;
|
|
193
|
+
return {
|
|
194
|
+
homeReal,
|
|
195
|
+
snapshot: await carregarSnapshot(opcoes),
|
|
196
|
+
espelhoClaudeDetectado,
|
|
197
|
+
destinos: [
|
|
198
|
+
destinoCanonico(homeReal),
|
|
199
|
+
...(espelhoClaudeDetectado ? [destinoClaude(homeReal)] : []),
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function reciboValido(valor) {
|
|
204
|
+
if (!valor || typeof valor !== "object" || Array.isArray(valor))
|
|
205
|
+
return false;
|
|
206
|
+
const candidato = valor;
|
|
207
|
+
if (!chavesExatas(candidato, ["schema", "manager", "skill", "packageVersion", "files"])
|
|
208
|
+
|| candidato.schema !== ESQUEMA_RECIBO
|
|
209
|
+
|| candidato.manager !== GERENCIADOR_RECIBO
|
|
210
|
+
|| candidato.skill !== "sema")
|
|
211
|
+
return false;
|
|
212
|
+
try {
|
|
213
|
+
validarVersaoPacote(candidato.packageVersion);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
if (!candidato.files || typeof candidato.files !== "object" || Array.isArray(candidato.files)
|
|
219
|
+
|| !chavesExatas(candidato.files, [...ARQUIVOS_SKILL_SEMA_GERENCIADOS]))
|
|
220
|
+
return false;
|
|
221
|
+
return ARQUIVOS_SKILL_SEMA_GERENCIADOS.every((arquivo) => (typeof candidato.files?.[arquivo] === "string"
|
|
222
|
+
&& /^[a-f0-9]{64}$/u.test(candidato.files[arquivo])));
|
|
223
|
+
}
|
|
224
|
+
async function estruturaDestinoPermitida(destino) {
|
|
225
|
+
const topo = await readdir(destino, { withFileTypes: true });
|
|
226
|
+
if (topo.length === 0)
|
|
227
|
+
return true;
|
|
228
|
+
if (!chavesExatas(Object.fromEntries(topo.map((entrada) => [entrada.name, true])), ["SKILL.md", "agents", NOME_RECIBO_SKILL_SEMA]))
|
|
229
|
+
return false;
|
|
230
|
+
const agents = path.join(destino, "agents");
|
|
231
|
+
await statDiretorioSeguro(agents);
|
|
232
|
+
const entradasAgents = await readdir(agents, { withFileTypes: true });
|
|
233
|
+
if (entradasAgents.length !== 1 || entradasAgents[0]?.name !== "openai.yaml")
|
|
234
|
+
return false;
|
|
235
|
+
await validarArquivoRegular(path.join(destino, "SKILL.md"), destino);
|
|
236
|
+
await validarArquivoRegular(path.join(agents, "openai.yaml"), destino);
|
|
237
|
+
await validarArquivoRegular(path.join(destino, NOME_RECIBO_SKILL_SEMA), destino);
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
async function diagnosticarDestino(ambiente, destino) {
|
|
241
|
+
try {
|
|
242
|
+
const cadeia = await validarCadeiaExistente(ambiente.homeReal, path.dirname(destino.caminho));
|
|
243
|
+
if (cadeia === "ausente") {
|
|
244
|
+
return { resultado: resultadoDestino(destino, "MISSING", "DESTINO_AUSENTE") };
|
|
245
|
+
}
|
|
246
|
+
const info = await lstatOuNull(destino.caminho);
|
|
247
|
+
if (!info)
|
|
248
|
+
return { resultado: resultadoDestino(destino, "MISSING", "DESTINO_AUSENTE") };
|
|
249
|
+
await validarCadeiaExistente(ambiente.homeReal, destino.caminho);
|
|
250
|
+
const identidade = await identidadeDiretorioSeguro(destino.caminho);
|
|
251
|
+
const entradas = await readdir(destino.caminho);
|
|
252
|
+
if (entradas.length === 0) {
|
|
253
|
+
return {
|
|
254
|
+
resultado: resultadoDestino(destino, "MISSING", "DESTINO_AUSENTE"),
|
|
255
|
+
identidade,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
if (!await estruturaDestinoPermitida(destino.caminho)) {
|
|
259
|
+
return {
|
|
260
|
+
resultado: resultadoDestino(destino, "BROKEN_TARGET", "CONTEUDO_NAO_GERENCIADO"),
|
|
261
|
+
identidade,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
let reciboDesconhecido;
|
|
265
|
+
try {
|
|
266
|
+
reciboDesconhecido = JSON.parse((await lerArquivoSeguro(path.join(destino.caminho, NOME_RECIBO_SKILL_SEMA), LIMITE_RECIBO, ambiente.homeReal)).toString("utf8"));
|
|
267
|
+
}
|
|
268
|
+
catch (erro) {
|
|
269
|
+
const falha = falhaParaResultado(erro);
|
|
270
|
+
if (falha.estado === "PERMISSION_DENIED") {
|
|
271
|
+
return {
|
|
272
|
+
resultado: resultadoDestino(destino, falha.estado, falha.codigo),
|
|
273
|
+
identidade,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
resultado: resultadoDestino(destino, "BROKEN_TARGET", "RECIBO_INVALIDO"),
|
|
278
|
+
identidade,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
if (!reciboValido(reciboDesconhecido)) {
|
|
282
|
+
return {
|
|
283
|
+
resultado: resultadoDestino(destino, "BROKEN_TARGET", "RECIBO_INVALIDO"),
|
|
284
|
+
identidade,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
for (const relativo of ARQUIVOS_SKILL_SEMA_GERENCIADOS) {
|
|
288
|
+
const absoluto = path.resolve(destino.caminho, ...relativo.split("/"));
|
|
289
|
+
const bytes = await lerArquivoSeguro(absoluto, LIMITE_ARQUIVO_SKILL, ambiente.homeReal);
|
|
290
|
+
if (sha256(bytes) !== reciboDesconhecido.files[relativo]) {
|
|
291
|
+
return {
|
|
292
|
+
resultado: resultadoDestino(destino, "BROKEN_TARGET", "DESTINO_ALTERADO"),
|
|
293
|
+
identidade,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const atualizado = reciboDesconhecido.packageVersion === ambiente.snapshot.recibo.packageVersion
|
|
298
|
+
&& ARQUIVOS_SKILL_SEMA_GERENCIADOS.every((arquivo) => (reciboDesconhecido.files[arquivo] === ambiente.snapshot.recibo.files[arquivo]));
|
|
299
|
+
return {
|
|
300
|
+
resultado: resultadoDestino(destino, atualizado ? "READY" : "STALE", atualizado
|
|
301
|
+
? "DESTINO_PRONTO"
|
|
302
|
+
: "DESTINO_DESATUALIZADO"),
|
|
303
|
+
identidade,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
catch (erro) {
|
|
307
|
+
const falha = falhaParaResultado(erro);
|
|
308
|
+
return { resultado: resultadoDestino(destino, falha.estado, falha.codigo) };
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
async function criarStage(ambiente, destino, arquivos = ambiente.snapshot.arquivos, reciboTexto = ambiente.snapshot.reciboTexto) {
|
|
312
|
+
const pai = path.dirname(destino.caminho);
|
|
313
|
+
await garantirDiretoriosSeguros(ambiente.homeReal, pai);
|
|
314
|
+
const caminho = path.join(pai, nomeTemporarioDiretorio("stage"));
|
|
315
|
+
if (!caminhoContido(ambiente.homeReal, caminho) || await lstatOuNull(caminho)) {
|
|
316
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "DESTINO_ALTERADO");
|
|
317
|
+
}
|
|
318
|
+
await garantirDiretoriosSeguros(ambiente.homeReal, caminho);
|
|
319
|
+
const identidade = await identidadeDiretorioSeguro(caminho);
|
|
320
|
+
try {
|
|
321
|
+
if ((await readdir(caminho)).length !== 0) {
|
|
322
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "DESTINO_ALTERADO");
|
|
323
|
+
}
|
|
324
|
+
await garantirDiretoriosSeguros(ambiente.homeReal, path.join(caminho, "agents"));
|
|
325
|
+
for (const relativo of ARQUIVOS_SKILL_SEMA_GERENCIADOS) {
|
|
326
|
+
const bytes = arquivos.get(relativo);
|
|
327
|
+
if (!bytes)
|
|
328
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "PACOTE_INVALIDO");
|
|
329
|
+
await escreverArquivoAtomico(ambiente.homeReal, path.resolve(caminho, ...relativo.split("/")), bytes, 0o600);
|
|
330
|
+
}
|
|
331
|
+
await escreverArquivoAtomico(ambiente.homeReal, path.join(caminho, NOME_RECIBO_SKILL_SEMA), reciboTexto, 0o600);
|
|
332
|
+
return { caminho, identidade };
|
|
333
|
+
}
|
|
334
|
+
catch (erro) {
|
|
335
|
+
try {
|
|
336
|
+
if (await lstatOuNull(caminho)) {
|
|
337
|
+
await removerDiretorioTemporarioGerenciado(ambiente.homeReal, caminho, identidade);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
if (erro instanceof FalhaDistribuicaoGlobal && erro.codigo === "LOCK_PERDIDO") {
|
|
342
|
+
throw erro;
|
|
343
|
+
}
|
|
344
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "ROLLBACK_FALHOU");
|
|
345
|
+
}
|
|
346
|
+
throw erro;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
async function removerTemporarioSeExiste(ambiente, caminho, identidade) {
|
|
350
|
+
if (await lstatOuNull(caminho)) {
|
|
351
|
+
await removerDiretorioTemporarioGerenciado(ambiente.homeReal, caminho, identidade);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
async function compensarBackupAposPublicacao(ambiente, destino, backup) {
|
|
355
|
+
const atual = await diagnosticarDestino(ambiente, destino);
|
|
356
|
+
const backupVirtual = { ...destino, caminho: backup.caminho };
|
|
357
|
+
const original = await diagnosticarDestino(ambiente, backupVirtual);
|
|
358
|
+
if (atual.resultado.estado !== "READY" || !atual.identidade
|
|
359
|
+
|| !["READY", "STALE", "MISSING"]
|
|
360
|
+
.includes(original.resultado.estado)
|
|
361
|
+
|| !original.identidade
|
|
362
|
+
|| original.identidade.dev !== backup.identidade.dev
|
|
363
|
+
|| original.identidade.ino !== backup.identidade.ino) {
|
|
364
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "ROLLBACK_FALHOU");
|
|
365
|
+
}
|
|
366
|
+
const descarte = path.join(path.dirname(destino.caminho), nomeTemporarioDiretorio("backup"));
|
|
367
|
+
const identidadeDescarte = await moverDiretorioSeguro(ambiente.homeReal, destino.caminho, descarte, atual.identidade);
|
|
368
|
+
try {
|
|
369
|
+
await moverDiretorioSeguro(ambiente.homeReal, backup.caminho, destino.caminho, backup.identidade);
|
|
370
|
+
}
|
|
371
|
+
catch (erro) {
|
|
372
|
+
if (!await lstatOuNull(destino.caminho)) {
|
|
373
|
+
await moverDiretorioSeguro(ambiente.homeReal, descarte, destino.caminho, identidadeDescarte).catch(() => undefined);
|
|
374
|
+
}
|
|
375
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "ROLLBACK_FALHOU");
|
|
376
|
+
}
|
|
377
|
+
try {
|
|
378
|
+
await removerDiretorioTemporarioGerenciado(ambiente.homeReal, descarte, identidadeDescarte);
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "ROLLBACK_FALHOU");
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async function sincronizarDestino(ambiente, destino) {
|
|
385
|
+
const antes = await diagnosticarDestino(ambiente, destino);
|
|
386
|
+
if (!["MISSING", "STALE"].includes(antes.resultado.estado)) {
|
|
387
|
+
return antes.resultado;
|
|
388
|
+
}
|
|
389
|
+
let stage;
|
|
390
|
+
let backupPendente;
|
|
391
|
+
let destinoPublicado = false;
|
|
392
|
+
try {
|
|
393
|
+
stage = await criarStage(ambiente, destino);
|
|
394
|
+
const stageDestino = { ...destino, caminho: stage.caminho };
|
|
395
|
+
const stageValidado = await diagnosticarDestino(ambiente, stageDestino);
|
|
396
|
+
if (stageValidado.resultado.estado !== "READY") {
|
|
397
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "DESTINO_ALTERADO");
|
|
398
|
+
}
|
|
399
|
+
const imediatamenteAntes = await diagnosticarDestino(ambiente, destino);
|
|
400
|
+
if (imediatamenteAntes.resultado.estado === "READY") {
|
|
401
|
+
await removerTemporarioSeExiste(ambiente, stage.caminho, stage.identidade);
|
|
402
|
+
return imediatamenteAntes.resultado;
|
|
403
|
+
}
|
|
404
|
+
if (!["MISSING", "STALE"]
|
|
405
|
+
.includes(imediatamenteAntes.resultado.estado)) {
|
|
406
|
+
await removerTemporarioSeExiste(ambiente, stage.caminho, stage.identidade);
|
|
407
|
+
return imediatamenteAntes.resultado;
|
|
408
|
+
}
|
|
409
|
+
const alvoExiste = await lstatOuNull(destino.caminho) !== null;
|
|
410
|
+
const backup = path.join(path.dirname(destino.caminho), nomeTemporarioDiretorio("backup"));
|
|
411
|
+
if (alvoExiste) {
|
|
412
|
+
if (!imediatamenteAntes.identidade) {
|
|
413
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "DESTINO_ALTERADO");
|
|
414
|
+
}
|
|
415
|
+
const identidadeBackup = await moverDiretorioSeguro(ambiente.homeReal, destino.caminho, backup, imediatamenteAntes.identidade);
|
|
416
|
+
backupPendente = { caminho: backup, identidade: identidadeBackup };
|
|
417
|
+
}
|
|
418
|
+
try {
|
|
419
|
+
await moverDiretorioSeguro(ambiente.homeReal, stage.caminho, destino.caminho, stage.identidade);
|
|
420
|
+
destinoPublicado = true;
|
|
421
|
+
}
|
|
422
|
+
catch (erro) {
|
|
423
|
+
if (backupPendente && !await lstatOuNull(destino.caminho)) {
|
|
424
|
+
await moverDiretorioSeguro(ambiente.homeReal, backupPendente.caminho, destino.caminho, backupPendente.identidade);
|
|
425
|
+
backupPendente = undefined;
|
|
426
|
+
}
|
|
427
|
+
throw erro;
|
|
428
|
+
}
|
|
429
|
+
if (backupPendente) {
|
|
430
|
+
await removerDiretorioTemporarioGerenciado(ambiente.homeReal, backupPendente.caminho, backupPendente.identidade);
|
|
431
|
+
backupPendente = undefined;
|
|
432
|
+
}
|
|
433
|
+
const depois = await diagnosticarDestino(ambiente, destino);
|
|
434
|
+
return {
|
|
435
|
+
...depois.resultado,
|
|
436
|
+
alterado: depois.resultado.estado === "READY",
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
catch (erro) {
|
|
440
|
+
if (backupPendente && destinoPublicado) {
|
|
441
|
+
try {
|
|
442
|
+
await compensarBackupAposPublicacao(ambiente, destino, backupPendente);
|
|
443
|
+
backupPendente = undefined;
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "ROLLBACK_FALHOU");
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
const falha = falhaParaResultado(erro);
|
|
450
|
+
return resultadoDestino(destino, falha.estado, falha.codigo);
|
|
451
|
+
}
|
|
452
|
+
finally {
|
|
453
|
+
if (stage) {
|
|
454
|
+
try {
|
|
455
|
+
await removerTemporarioSeExiste(ambiente, stage.caminho, stage.identidade);
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "ROLLBACK_FALHOU");
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
function fallback(opcoes, erro) {
|
|
464
|
+
const falha = falhaParaResultado(erro);
|
|
465
|
+
const virtual = {
|
|
466
|
+
id: "agents",
|
|
467
|
+
estado: falha.estado,
|
|
468
|
+
alterado: falha.codigo === "LOCK_PERDIDO" || falha.codigo === "ROLLBACK_FALHOU",
|
|
469
|
+
destino_simbolico: "$HOME/.agents/skills/sema",
|
|
470
|
+
codigo: falha.codigo,
|
|
471
|
+
};
|
|
472
|
+
void opcoes;
|
|
473
|
+
return agregar([virtual], false);
|
|
474
|
+
}
|
|
475
|
+
export async function statusSkillGlobal(opcoes = {}) {
|
|
476
|
+
try {
|
|
477
|
+
const ambiente = await resolverAmbiente(opcoes);
|
|
478
|
+
const destinos = await Promise.all(ambiente.destinos.map(async (destino) => ((await diagnosticarDestino(ambiente, destino)).resultado)));
|
|
479
|
+
return agregar(destinos, ambiente.espelhoClaudeDetectado);
|
|
480
|
+
}
|
|
481
|
+
catch (erro) {
|
|
482
|
+
return fallback(opcoes, erro);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
async function sincronizarSkillGlobalSemLock(opcoes = {}) {
|
|
486
|
+
const diagnosticoInicial = await statusSkillGlobal(opcoes);
|
|
487
|
+
if (resultadoBloqueiaMutacao(diagnosticoInicial))
|
|
488
|
+
return semAlteracao(diagnosticoInicial);
|
|
489
|
+
let snapshot;
|
|
490
|
+
try {
|
|
491
|
+
snapshot = await capturarSnapshotSkillGlobalTransacao(opcoes);
|
|
492
|
+
}
|
|
493
|
+
catch {
|
|
494
|
+
return semAlteracao(await statusSkillGlobal(opcoes));
|
|
495
|
+
}
|
|
496
|
+
const sincronizado = await sincronizarSkillGlobalTransacional(snapshot);
|
|
497
|
+
const final = sincronizado.estado === "READY"
|
|
498
|
+
? await statusSkillGlobal(opcoes)
|
|
499
|
+
: sincronizado;
|
|
500
|
+
if (resultadoInteiramenteReady(final)) {
|
|
501
|
+
return comAlteracoesConfirmadas(final, sincronizado);
|
|
502
|
+
}
|
|
503
|
+
try {
|
|
504
|
+
await restaurarSnapshotSkillGlobalTransacao(snapshot);
|
|
505
|
+
}
|
|
506
|
+
catch {
|
|
507
|
+
return falhaRollback(await statusSkillGlobal(opcoes));
|
|
508
|
+
}
|
|
509
|
+
return semAlteracao(await statusSkillGlobal(opcoes));
|
|
510
|
+
}
|
|
511
|
+
export async function sincronizarSkillGlobal(opcoes = {}) {
|
|
512
|
+
try {
|
|
513
|
+
return await comLockDistribuicaoGlobal(opcoes, async ({ diretorioUsuario }) => (sincronizarSkillGlobalSemLock({ ...opcoes, diretorioUsuario })));
|
|
514
|
+
}
|
|
515
|
+
catch (erro) {
|
|
516
|
+
return fallback(opcoes, erro);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
export async function capturarSnapshotSkillGlobalTransacao(opcoes = {}) {
|
|
520
|
+
const ambiente = await resolverAmbiente(opcoes);
|
|
521
|
+
const destinos = [];
|
|
522
|
+
for (const destino of ambiente.destinos) {
|
|
523
|
+
const diagnostico = await diagnosticarDestino(ambiente, destino);
|
|
524
|
+
if (diagnostico.resultado.estado === "BROKEN_TARGET"
|
|
525
|
+
|| diagnostico.resultado.estado === "PERMISSION_DENIED") {
|
|
526
|
+
throw new FalhaDistribuicaoGlobal(diagnostico.resultado.estado === "PERMISSION_DENIED"
|
|
527
|
+
? "PERMISSION_DENIED"
|
|
528
|
+
: "BROKEN_TARGET", diagnostico.resultado.codigo);
|
|
529
|
+
}
|
|
530
|
+
const existente = await lstatOuNull(destino.caminho) !== null;
|
|
531
|
+
if (!existente) {
|
|
532
|
+
destinos.push({ destino, existente: false, vazio: false });
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
const entradas = await readdir(destino.caminho);
|
|
536
|
+
if (entradas.length === 0) {
|
|
537
|
+
destinos.push({ destino, existente: true, vazio: true });
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
const arquivos = new Map();
|
|
541
|
+
for (const relativo of ARQUIVOS_SKILL_SEMA_GERENCIADOS) {
|
|
542
|
+
arquivos.set(relativo, await lerArquivoSeguro(path.resolve(destino.caminho, ...relativo.split("/")), LIMITE_ARQUIVO_SKILL, ambiente.homeReal));
|
|
543
|
+
}
|
|
544
|
+
destinos.push({
|
|
545
|
+
destino,
|
|
546
|
+
existente: true,
|
|
547
|
+
vazio: false,
|
|
548
|
+
arquivos,
|
|
549
|
+
recibo: await lerArquivoSeguro(path.join(destino.caminho, NOME_RECIBO_SKILL_SEMA), LIMITE_RECIBO, ambiente.homeReal),
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
return { ambiente, destinos };
|
|
553
|
+
}
|
|
554
|
+
async function destinoIgualSnapshot(ambiente, snapshot) {
|
|
555
|
+
const existente = await lstatOuNull(snapshot.destino.caminho) !== null;
|
|
556
|
+
if (!snapshot.existente)
|
|
557
|
+
return !existente;
|
|
558
|
+
if (!existente)
|
|
559
|
+
return false;
|
|
560
|
+
await validarCadeiaExistente(ambiente.homeReal, snapshot.destino.caminho);
|
|
561
|
+
if (snapshot.vazio)
|
|
562
|
+
return (await readdir(snapshot.destino.caminho)).length === 0;
|
|
563
|
+
if (!snapshot.arquivos || !snapshot.recibo
|
|
564
|
+
|| !await estruturaDestinoPermitida(snapshot.destino.caminho))
|
|
565
|
+
return false;
|
|
566
|
+
for (const relativo of ARQUIVOS_SKILL_SEMA_GERENCIADOS) {
|
|
567
|
+
const atual = await lerArquivoSeguro(path.resolve(snapshot.destino.caminho, ...relativo.split("/")), LIMITE_ARQUIVO_SKILL, ambiente.homeReal);
|
|
568
|
+
if (!atual.equals(snapshot.arquivos.get(relativo) ?? Buffer.alloc(0)))
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
571
|
+
const reciboAtual = await lerArquivoSeguro(path.join(snapshot.destino.caminho, NOME_RECIBO_SKILL_SEMA), LIMITE_RECIBO, ambiente.homeReal);
|
|
572
|
+
return reciboAtual.equals(snapshot.recibo);
|
|
573
|
+
}
|
|
574
|
+
async function restaurarDestinoSnapshot(ambiente, snapshot) {
|
|
575
|
+
if (await destinoIgualSnapshot(ambiente, snapshot))
|
|
576
|
+
return;
|
|
577
|
+
const atual = await diagnosticarDestino(ambiente, snapshot.destino);
|
|
578
|
+
if (atual.resultado.estado !== "READY") {
|
|
579
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "DESTINO_ALTERADO");
|
|
580
|
+
}
|
|
581
|
+
const pai = path.dirname(snapshot.destino.caminho);
|
|
582
|
+
let stage;
|
|
583
|
+
try {
|
|
584
|
+
if (snapshot.arquivos && snapshot.recibo) {
|
|
585
|
+
stage = await criarStage(ambiente, snapshot.destino, snapshot.arquivos, snapshot.recibo.toString("utf8"));
|
|
586
|
+
}
|
|
587
|
+
const backup = path.join(pai, nomeTemporarioDiretorio("backup"));
|
|
588
|
+
const identidadeAtual = atual.identidade
|
|
589
|
+
?? await identidadeDiretorioSeguro(snapshot.destino.caminho);
|
|
590
|
+
const identidadeBackup = await moverDiretorioSeguro(ambiente.homeReal, snapshot.destino.caminho, backup, identidadeAtual);
|
|
591
|
+
try {
|
|
592
|
+
if (stage) {
|
|
593
|
+
await moverDiretorioSeguro(ambiente.homeReal, stage.caminho, snapshot.destino.caminho, stage.identidade);
|
|
594
|
+
}
|
|
595
|
+
else if (snapshot.existente && snapshot.vazio) {
|
|
596
|
+
await garantirDiretoriosSeguros(ambiente.homeReal, snapshot.destino.caminho);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
catch (erro) {
|
|
600
|
+
if (!await lstatOuNull(snapshot.destino.caminho)) {
|
|
601
|
+
await moverDiretorioSeguro(ambiente.homeReal, backup, snapshot.destino.caminho, identidadeBackup);
|
|
602
|
+
}
|
|
603
|
+
throw erro;
|
|
604
|
+
}
|
|
605
|
+
await removerDiretorioTemporarioGerenciado(ambiente.homeReal, backup, identidadeBackup);
|
|
606
|
+
if (!await destinoIgualSnapshot(ambiente, snapshot)) {
|
|
607
|
+
throw new FalhaDistribuicaoGlobal("BROKEN_TARGET", "ROLLBACK_FALHOU");
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
finally {
|
|
611
|
+
if (stage) {
|
|
612
|
+
await removerTemporarioSeExiste(ambiente, stage.caminho, stage.identidade);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
async function sincronizarSkillGlobalTransacionalSemLock(snapshot) {
|
|
617
|
+
const destinos = [];
|
|
618
|
+
for (let indice = 0; indice < snapshot.destinos.length; indice += 1) {
|
|
619
|
+
const item = snapshot.destinos[indice];
|
|
620
|
+
if (!item)
|
|
621
|
+
continue;
|
|
622
|
+
const resultadoAtual = await sincronizarDestino(snapshot.ambiente, item.destino);
|
|
623
|
+
destinos.push(resultadoAtual);
|
|
624
|
+
if (resultadoAtual.estado !== "READY") {
|
|
625
|
+
for (const restante of snapshot.destinos.slice(indice + 1)) {
|
|
626
|
+
destinos.push((await diagnosticarDestino(snapshot.ambiente, restante.destino)).resultado);
|
|
627
|
+
}
|
|
628
|
+
break;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return agregar(destinos, snapshot.ambiente.espelhoClaudeDetectado);
|
|
632
|
+
}
|
|
633
|
+
export async function sincronizarSkillGlobalTransacional(snapshot) {
|
|
634
|
+
return comLockDistribuicaoGlobal({ diretorioUsuario: snapshot.ambiente.homeReal }, async () => sincronizarSkillGlobalTransacionalSemLock(snapshot));
|
|
635
|
+
}
|
|
636
|
+
async function restaurarSnapshotSkillGlobalTransacaoSemLock(snapshot) {
|
|
637
|
+
const falhas = [];
|
|
638
|
+
for (const destino of [...snapshot.destinos].reverse()) {
|
|
639
|
+
try {
|
|
640
|
+
await restaurarDestinoSnapshot(snapshot.ambiente, destino);
|
|
641
|
+
}
|
|
642
|
+
catch (erro) {
|
|
643
|
+
falhas.push(erro);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
if (falhas.length > 0)
|
|
647
|
+
throw new AggregateError(falhas, "ROLLBACK_FALHOU");
|
|
648
|
+
}
|
|
649
|
+
export async function restaurarSnapshotSkillGlobalTransacao(snapshot) {
|
|
650
|
+
return comLockDistribuicaoGlobal({ diretorioUsuario: snapshot.ambiente.homeReal }, async () => restaurarSnapshotSkillGlobalTransacaoSemLock(snapshot));
|
|
651
|
+
}
|
|
652
|
+
//# sourceMappingURL=skillGlobal.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const INTENCOES_SKILL_SEMA: readonly ["INFORMAR", "INSTALAR_GLOBAL", "ATUALIZAR_GLOBAL", "REPARAR_GLOBAL", "ADOTAR_WORKSPACE"];
|
|
2
|
+
export type IntencaoSkillSema = typeof INTENCOES_SKILL_SEMA[number];
|
|
3
|
+
export type AcaoIntencaoSkillSema = "npm_view_version:@semacode/cli@latest" | "validar_semver_exata_resolvida" | `npm_install_global:@semacode/cli@${string}` | "provar_cli_path_com_versao_e_skill" | "provar_launcher_gerenciado_com_versao_e_skill" | "preferir_launcher_gerenciado_se_path_stale_ou_sem_skill" | "provar_versao_instalada" | "consultar_status_distribuicao" | "sincronizar_distribuicao_se_necessario" | "consultar_status_final_ready" | "declarar_cli_indisponivel_apos_path_e_launcher_gerenciado_invalidos" | "responder_sem_mutar" | "pedir_autorizacao_adocao" | "descobrir_explicar_flow_project_adoption" | "iniciar_template_base" | "sync_codex" | "ler_agents_e_boot";
|
|
4
|
+
export interface EntradaIntencaoSkillSema {
|
|
5
|
+
intencao: IntencaoSkillSema;
|
|
6
|
+
versaoSolicitada?: string;
|
|
7
|
+
cliDisponivel: boolean;
|
|
8
|
+
adocaoAutorizada: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface PlanoIntencaoSkillSema {
|
|
11
|
+
instalar_pacote_global: boolean;
|
|
12
|
+
sincronizar_distribuicao_se_necessario: boolean;
|
|
13
|
+
mutar_workspace: boolean;
|
|
14
|
+
bloqueado_por_autorizacao_adocao: boolean;
|
|
15
|
+
resolver_latest_para_semver_exata: boolean;
|
|
16
|
+
provar_path_e_launcher_gerenciado: boolean;
|
|
17
|
+
exigir_prova_versao: boolean;
|
|
18
|
+
exigir_status_final_ready: boolean;
|
|
19
|
+
acoes_ordenadas: AcaoIntencaoSkillSema[];
|
|
20
|
+
}
|
|
21
|
+
export declare function planejarIntencaoSkillSema(entrada: EntradaIntencaoSkillSema): PlanoIntencaoSkillSema;
|