diff --git a/code/cep-plugin/index.html b/code/cep-plugin/index.html
index 14acecc..0f97f71 100755
--- a/code/cep-plugin/index.html
+++ b/code/cep-plugin/index.html
@@ -46,6 +46,9 @@
+
@@ -580,6 +583,30 @@
+
+
+
Teste a execução de um plano JSON pela engine Python antes de integrar a ação ao fluxo normal de edição.
+
+
+
+
Plano de teste
+ Somente corte
+
+ Cole um JSON com uma ou mais actions kind: "cut". Os tempos precisam estar na mídia original.
+
+
+
+
+
+
+
+
+
+ Detalhes técnicos (engine Python e MCP)
+
+
+
+
diff --git a/code/cep-plugin/main.js b/code/cep-plugin/main.js
index 4299c90..c23f407 100755
--- a/code/cep-plugin/main.js
+++ b/code/cep-plugin/main.js
@@ -233,6 +233,7 @@ function switchTab(name) {
{ key: "bridge", panel: "tabBridge", btn: "tabBtnBridge" },
{ key: "models", panel: "tabModels", btn: "tabBtnModels" },
{ key: "settings", panel: "tabSettings", btn: "tabBtnSettings" },
+ { key: "testar-acoes", panel: "tabTestarAcoes", btn: "tabBtnTestarAcoes" },
];
tabs.forEach(function (t) {
var active = t.key === name;
@@ -252,6 +253,83 @@ function switchTab(name) {
if (name === "tipos-video") tiposVideoAoAbrir();
}
+// ---- Teste isolado de ações pela engine Python ----------------------------
+var TESTAR_ACOES_ENGINE_SCRIPT = "/Volumes/Merongo/SISTEMAS/GENIAL SISTEMAS/Jhonny/code/engine/aplicar_plano_de_edicao.py";
+
+function testarAcoesCarregarExemplo() {
+ var exemplo = {
+ schema_version: "1.0",
+ source: "video.mp4",
+ actions: [{ kind: "cut", start: 0.0, end: 1.0, reason: "Teste de corte inicial pela engine Python." }]
+ };
+ document.getElementById("testarAcoesJson").value = JSON.stringify(exemplo, null, 2);
+ testarAcoesAtualizarStatus("Exemplo carregado. Ajuste o source e os tempos antes de executar.", "");
+}
+
+function testarAcoesLog(mensagem, classe) {
+ var alvo = document.getElementById("testarAcoesLog");
+ if (!alvo) return;
+ var linha = document.createElement("p");
+ linha.textContent = mensagem;
+ if (classe) linha.className = classe;
+ alvo.appendChild(linha);
+ alvo.scrollTop = alvo.scrollHeight;
+}
+
+function testarAcoesAtualizarStatus(mensagem, classe) {
+ var status = document.getElementById("testarAcoesStatus");
+ if (status) { status.textContent = mensagem; status.className = "field-help " + (classe || ""); }
+}
+
+function testarAcoesExecutar() {
+ var campo = document.getElementById("testarAcoesJson");
+ var texto = campo.value.trim();
+ var plano;
+ if (!texto) { testarAcoesAtualizarStatus("Cole um plano JSON antes de executar.", "err"); return; }
+ try { plano = JSON.parse(texto); } catch (erro) {
+ testarAcoesAtualizarStatus("JSON inválido: " + erro.message, "err");
+ testarAcoesLog("JSON inválido: " + erro.message, "err");
+ return;
+ }
+ if (!plano || typeof plano !== "object" || !plano.source || !Array.isArray(plano.actions) || !plano.actions.length) {
+ testarAcoesAtualizarStatus("O plano precisa ter source e uma lista não vazia de actions.", "err");
+ return;
+ }
+ var tipos = plano.actions.map(function (acao) { return acao && acao.kind; });
+ if (tipos.some(function (tipo) { return tipo !== "cut"; })) {
+ testarAcoesAtualizarStatus("Este primeiro teste aceita somente actions kind: cut.", "err");
+ return;
+ }
+ var entrada = path.join(os.tmpdir(), "teste-acoes-" + Date.now() + ".json");
+ try { fs.writeFileSync(entrada, JSON.stringify(plano, null, 2), "utf-8"); } catch (erroEscrita) {
+ testarAcoesAtualizarStatus("Não foi possível criar o plano temporário: " + erroEscrita.message, "err");
+ return;
+ }
+ var botao = document.getElementById("btnTestarAcoesExecutar");
+ if (botao) botao.disabled = true;
+ testarAcoesAtualizarStatus("A engine está conectando ao Premiere e aplicando o corte…", "");
+ testarAcoesLog("Plano temporário criado: " + entrada);
+ taskStart("Teste de ação", "Executando pela engine Python");
+ runStreamed(
+ SCANNER_PYTHON_BIN,
+ [TESTAR_ACOES_ENGINE_SCRIPT, entrada],
+ function (linha) { testarAcoesLog(linha); },
+ function (codigo, ultimoErro) {
+ if (botao) botao.disabled = false;
+ if (codigo !== 0) {
+ testarAcoesAtualizarStatus("Falha na execução. Consulte os detalhes técnicos.", "err");
+ testarAcoesLog(ultimoErro || "A engine terminou com código " + codigo + ".", "err");
+ taskEnd(false, "Teste de ação falhou", ultimoErro || null);
+ return;
+ }
+ testarAcoesAtualizarStatus("Corte executado pela engine Python. Verifique a timeline no Premiere.", "ok");
+ testarAcoesLog("Engine concluída com sucesso.", "ok");
+ taskEnd(true, "Teste de corte concluído");
+ },
+ { cwd: "/Volumes/Merongo/SISTEMAS/GENIAL SISTEMAS/Jhonny/code/engine" }
+ );
+}
+
// ---- Catálogo de tipos de vídeo -------------------------------------------
// A primeira versão usa o armazenamento local do painel. O documento salvo já
// tem formato estável e pode ser migrado para o Schedule Light sem alterar o