feat: Alinhado o aplicador Python de plano de edição (aplicador_de

- Alinhado o aplicador Python de plano de edição (aplicador_de_plano_de_edicao.py) com o script apply-editorial-actions.mjs de referência: no-op de split restrito aos padrões reais do bridge, pausa entre chamadas ao MCP, tolerância de borda de corte usa a posição real em vez de rejeitar desvio; adicionado backup automático da sequência (duplicate_sequence) e documentado o comando python code/engine/aplicar_plano_de_edicao.py como via alternativa ao painel CEP.

Resumo:
- 18 arquivos alterados
- 5 novos
- 13 modificados
- 0 removidos

 13 files changed, 704 insertions(+), 133 deletions(-)

Arquivos:
  - .jhonny/analises.db
  - CLAUDE.md
  - code/engine/aplicar_plano_de_edicao.py
  - code/engine/editor/__init__.py
  - code/engine/editor/aplicador_de_plano_de_edicao.py
  - code/engine/editor/escrita/escrita_no_editor.py
  - code/engine/integracoes/premiere/__init__.py
  - code/engine/integracoes/premiere/cliente_mcp.py
  - code/engine/testes/duplos_de_premiere.py
  - code/engine/testes/test_aplicador_de_plano_de_edicao.py
  - code/scripts/apply-editorial-actions.mjs
  - code/src/tools/discovery.ts
  - code/src/tools/timeline.ts
  - code/engine/editor/backup_de_sequencia.py
  - code/engine/integracoes/premiere/cliente_mcp_com_pausa.py
  - code/engine/testes/test_backup_de_sequencia.py
  - code/engine/testes/test_cliente_mcp_com_pausa.py
  - code/engine/testes/test_escrita_no_editor.py
This commit is contained in:
João Henrique
2026-09-09 09:31:29 -04:00
parent 4308c72441
commit 69e931eb45
18 changed files with 1040 additions and 133 deletions
@@ -89,7 +89,28 @@ class ClienteMCPPorStdio(ClienteMCP):
resposta = self._enviar("tools/call", {"name": nome_da_ferramenta, "arguments": argumentos or {}})
if resposta.get("error"):
raise ErroDeFerramentaMCP(f"Erro ao executar {nome_da_ferramenta!r} no MCP: {resposta['error']}")
return resposta.get("result", {})
resultado = resposta.get("result", {})
# Uma ferramenta que falha não devolve erro no nível do JSON-RPC: o
# servidor responde "com sucesso" e marca `isError` no resultado. Sem
# olhar esse campo, uma escrita recusada pelo Premiere passaria por
# bem-sucedida — foi assim que uma chamada a uma ferramenta inexistente
# ficou invisível até o efeito aparecer na timeline.
if resultado.get("isError"):
raise ErroDeFerramentaMCP(
f"A ferramenta {nome_da_ferramenta!r} falhou: {self._mensagem_de_erro(resultado)}"
)
return resultado
@staticmethod
def _mensagem_de_erro(resultado: dict[str, Any]) -> str:
"""Extrai a mensagem de erro que o servidor MCP devolveu no resultado."""
conteudo_estruturado = resultado.get("structuredContent")
if isinstance(conteudo_estruturado, dict) and conteudo_estruturado.get("error"):
return str(conteudo_estruturado["error"])
for bloco in resultado.get("content", []):
if isinstance(bloco, dict) and bloco.get("type") == "text":
return str(bloco.get("text", ""))
return "sem detalhes"
def _enviar(self, metodo: str, parametros: dict[str, Any]) -> dict[str, Any]:
"""Envia uma requisição JSON-RPC pela stdin do processo e lê a resposta da stdout.