primocode 10.16.0 → 10.17.1

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 (237) hide show
  1. package/LICENSES/edit-ia-pro.txt +32 -0
  2. package/LICENSES/fontes-OFL.txt +476 -0
  3. package/LICENSES/hyperframes-Apache-2.0.txt +205 -0
  4. package/LICENSES/permanent-marker-Apache-2.0.txt +204 -0
  5. package/LICENSES/selfie-multiclass-Apache-2.0.txt +227 -0
  6. package/LICENSES/three-MIT.txt +23 -0
  7. package/LICENSES/video-use-MIT.txt +24 -0
  8. package/LICENSES/woven-sfx-CC0.txt +16 -0
  9. package/LICENSES/yunet-MIT.txt +21 -0
  10. package/README.md +2 -2
  11. package/bin/primocode.js +28 -8
  12. package/editor/LICENSE.md +11 -0
  13. package/editor/README.md +321 -0
  14. package/editor/SKILL.md +307 -0
  15. package/editor/THIRD_PARTY_NOTICES.md +228 -0
  16. package/editor/assets/baixar.json +591 -0
  17. package/editor/assets/fonts/anton/OFL.txt +93 -0
  18. package/editor/assets/fonts/caveat/OFL.txt +93 -0
  19. package/editor/assets/fonts/figtree/OFL.txt +93 -0
  20. package/editor/assets/fonts/fonts.json +10 -0
  21. package/editor/assets/fonts/montserrat/OFL.txt +93 -0
  22. package/editor/assets/fonts/permanentmarker/LICENSE.txt +202 -0
  23. package/editor/assets/models/SELFIE_MULTICLASS_LICENSE.txt +227 -0
  24. package/editor/assets/models/YUNET_LICENSE.txt +21 -0
  25. package/editor/assets/sfx/licencas/bass_drop.txt +32 -0
  26. package/editor/assets/sfx/licencas/cash.txt +76 -0
  27. package/editor/assets/sfx/licencas/charge.txt +31 -0
  28. package/editor/assets/sfx/licencas/click.txt +46 -0
  29. package/editor/assets/sfx/licencas/coin.txt +50 -0
  30. package/editor/assets/sfx/licencas/count.txt +47 -0
  31. package/editor/assets/sfx/licencas/data.txt +31 -0
  32. package/editor/assets/sfx/licencas/error.txt +32 -0
  33. package/editor/assets/sfx/licencas/flash.txt +31 -0
  34. package/editor/assets/sfx/licencas/gears.txt +82 -0
  35. package/editor/assets/sfx/licencas/keyboard.txt +48 -0
  36. package/editor/assets/sfx/licencas/metal_hit.txt +62 -0
  37. package/editor/assets/sfx/licencas/metal_riser.txt +61 -0
  38. package/editor/assets/sfx/licencas/mouse_click.txt +50 -0
  39. package/editor/assets/sfx/licencas/notification.txt +54 -0
  40. package/editor/assets/sfx/licencas/pop.txt +38 -0
  41. package/editor/assets/sfx/licencas/rewind.txt +32 -0
  42. package/editor/assets/sfx/licencas/rise.txt +46 -0
  43. package/editor/assets/sfx/licencas/sinteticos.txt +21 -0
  44. package/editor/assets/sfx/licencas/snap.txt +50 -0
  45. package/editor/assets/sfx/licencas/success.txt +40 -0
  46. package/editor/assets/sfx/licencas/synth_hit.txt +32 -0
  47. package/editor/assets/sfx/licencas/tick.txt +14 -0
  48. package/editor/assets/sfx/licencas/whoosh.txt +47 -0
  49. package/editor/assets/sfx/licencas/wind.txt +31 -0
  50. package/editor/assets/sfx/sfx.json +832 -0
  51. package/editor/assets/sfx/sfx_sinteticos.json +317 -0
  52. package/editor/assets/sfx/sfx_woven.json +387 -0
  53. package/editor/assets/sfx/woven/LICENCA.md +16 -0
  54. package/editor/fichas/briefing-do-video.md +45 -0
  55. package/editor/fichas/conferencia-da-amostra.md +56 -0
  56. package/editor/fichas/matriz-de-ganchos.csv +3 -0
  57. package/editor/fichas/padrao.json +16 -0
  58. package/editor/fichas/planilha-de-cenas.csv +4 -0
  59. package/editor/fichas/planilha-de-versoes.csv +4 -0
  60. package/editor/fichas/plano-em-blocos.md +32 -0
  61. package/editor/fichas/registro-de-materiais.json +27 -0
  62. package/editor/helpers/assets_ocr/ocr_vision.swift +41 -0
  63. package/editor/helpers/bordas_precisas.py +272 -0
  64. package/editor/helpers/camera_viva.py +426 -0
  65. package/editor/helpers/captions.py +601 -0
  66. package/editor/helpers/common.py +308 -0
  67. package/editor/helpers/compose_final.py +3555 -0
  68. package/editor/helpers/conferir_corte.py +234 -0
  69. package/editor/helpers/conferir_dados.py +405 -0
  70. package/editor/helpers/contact_sheet.py +282 -0
  71. package/editor/helpers/corte_por_onda.py +433 -0
  72. package/editor/helpers/corte_seco.py +595 -0
  73. package/editor/helpers/denoise.py +971 -0
  74. package/editor/helpers/efeitos.py +408 -0
  75. package/editor/helpers/efeitos_gerar.py +159 -0
  76. package/editor/helpers/elevenlabs_api.py +442 -0
  77. package/editor/helpers/face_layout.py +570 -0
  78. package/editor/helpers/fetch_images.py +423 -0
  79. package/editor/helpers/ganho_por_trecho.py +214 -0
  80. package/editor/helpers/gen_image.py +312 -0
  81. package/editor/helpers/gen_music.py +316 -0
  82. package/editor/helpers/gen_sfx.py +148 -0
  83. package/editor/helpers/grade.py +307 -0
  84. package/editor/helpers/icloud.py +119 -0
  85. package/editor/helpers/make_sfx.py +940 -0
  86. package/editor/helpers/matte.py +1342 -0
  87. package/editor/helpers/medir_referencia.py +2232 -0
  88. package/editor/helpers/mixar_trilha.py +354 -0
  89. package/editor/helpers/montar_corte.py +295 -0
  90. package/editor/helpers/motion/__init__.py +13 -0
  91. package/editor/helpers/motion/engine.py +1915 -0
  92. package/editor/helpers/motion/registry.py +510 -0
  93. package/editor/helpers/motion/render.py +665 -0
  94. package/editor/helpers/motion/templates/barra_progresso.py +370 -0
  95. package/editor/helpers/motion/templates/carimbo.py +132 -0
  96. package/editor/helpers/motion/templates/checklist.py +271 -0
  97. package/editor/helpers/motion/templates/comentario_cta.py +380 -0
  98. package/editor/helpers/motion/templates/contador.py +222 -0
  99. package/editor/helpers/motion/templates/destaque.py +263 -0
  100. package/editor/helpers/motion/templates/etiqueta_preco.py +461 -0
  101. package/editor/helpers/motion/templates/grafico_barras.py +510 -0
  102. package/editor/helpers/motion/templates/grafico_linha.py +462 -0
  103. package/editor/helpers/motion/templates/notificacao.py +266 -0
  104. package/editor/helpers/motion/templates/palavra_impacto.py +410 -0
  105. package/editor/helpers/motion/templates/passos.py +321 -0
  106. package/editor/helpers/motion/templates/riscado.py +298 -0
  107. package/editor/helpers/motion/templates/selo_garantia.py +150 -0
  108. package/editor/helpers/motion_render.py +241 -0
  109. package/editor/helpers/motion_sugerir.py +961 -0
  110. package/editor/helpers/noise_check.py +134 -0
  111. package/editor/helpers/pack_transcripts.py +223 -0
  112. package/editor/helpers/palavras_na_onda.py +176 -0
  113. package/editor/helpers/plano_sfx.py +839 -0
  114. package/editor/helpers/portao.py +427 -0
  115. package/editor/helpers/preview_server.py +1177 -0
  116. package/editor/helpers/rastrear_rosto.py +298 -0
  117. package/editor/helpers/render_cut.py +1256 -0
  118. package/editor/helpers/respiros.py +89 -0
  119. package/editor/helpers/sincronizar_cameras.py +571 -0
  120. package/editor/helpers/speech_regions.py +423 -0
  121. package/editor/helpers/style_catalog.json +231 -0
  122. package/editor/helpers/style_samples.py +246 -0
  123. package/editor/helpers/tela_verde.py +2113 -0
  124. package/editor/helpers/text_render.py +2059 -0
  125. package/editor/helpers/texto_na_tela.py +366 -0
  126. package/editor/helpers/timeline_view.py +292 -0
  127. package/editor/helpers/tira_de_quadros.py +113 -0
  128. package/editor/helpers/transcribe.py +734 -0
  129. package/editor/helpers/transcribe_batch.py +129 -0
  130. package/editor/helpers/trilhas.py +1146 -0
  131. package/editor/helpers/trilhas_humores.json +66 -0
  132. package/editor/helpers/valores.py +187 -0
  133. package/editor/helpers/verify_cut.py +820 -0
  134. package/editor/helpers/voice_levels.py +233 -0
  135. package/editor/helpers/voz_check.py +386 -0
  136. package/editor/helpers/voz_limpa.py +81 -0
  137. package/editor/helpers/watch_preview.py +372 -0
  138. package/editor/modelo-projeto/LEIA.md +402 -0
  139. package/editor/modelo-projeto/assets/fontes/OFL-Caveat.txt +93 -0
  140. package/editor/modelo-projeto/assets/fontes/OFL-JetBrainsMono.txt +93 -0
  141. package/editor/modelo-projeto/assets/fontes/OFL-Montserrat.txt +93 -0
  142. package/editor/modelo-projeto/assets/fontes/larguras.json +1 -0
  143. package/editor/modelo-projeto/assets/three/BufferGeometryUtils.js +1438 -0
  144. package/editor/modelo-projeto/assets/three/GLTFLoader.js +4895 -0
  145. package/editor/modelo-projeto/assets/three/LICENSE +21 -0
  146. package/editor/modelo-projeto/assets/three/ORIGEM.txt +17 -0
  147. package/editor/modelo-projeto/assets/three/RoomEnvironment.js +185 -0
  148. package/editor/modelo-projeto/assets/three/three.core.min.js +6 -0
  149. package/editor/modelo-projeto/assets/three/three.module.min.js +6 -0
  150. package/editor/modelo-projeto/build.py +4828 -0
  151. package/editor/modelo-projeto/compositions/cenas/2d/k2d_antes_depois.html +199 -0
  152. package/editor/modelo-projeto/compositions/cenas/2d/k2d_arquivo.html +232 -0
  153. package/editor/modelo-projeto/compositions/cenas/2d/k2d_busca.html +315 -0
  154. package/editor/modelo-projeto/compositions/cenas/2d/k2d_comando.html +304 -0
  155. package/editor/modelo-projeto/compositions/cenas/2d/k2d_conversa.html +217 -0
  156. package/editor/modelo-projeto/compositions/cenas/2d/k2d_esquema.html +289 -0
  157. package/editor/modelo-projeto/compositions/cenas/2d/k2d_medidor.html +249 -0
  158. package/editor/modelo-projeto/compositions/cenas/2d/k2d_notas.html +233 -0
  159. package/editor/modelo-projeto/compositions/cenas/3d/k3d_caminho.html +197 -0
  160. package/editor/modelo-projeto/compositions/cenas/3d/k3d_explodida.html +152 -0
  161. package/editor/modelo-projeto/compositions/cenas/3d/k3d_tela.html +167 -0
  162. package/editor/modelo-projeto/compositions/cenas/3d/k3d_volume.html +124 -0
  163. package/editor/modelo-projeto/compositions/cenas/3d/motor-three.js +728 -0
  164. package/editor/modelo-projeto/compositions/cenas/LEIA.md +177 -0
  165. package/editor/modelo-projeto/ferramentas/medir_fontes.py +65 -0
  166. package/editor/modelo-projeto/ferramentas/pessoa_recortada.py +176 -0
  167. package/editor/modelo-projeto/ferramentas/rastrear_maos.py +189 -0
  168. package/editor/modelo-projeto/hyperframes.json +12 -0
  169. package/editor/modelo-projeto/package.json +11 -0
  170. package/editor/modelo-projeto/projeto.json +16 -0
  171. package/editor/preview/app.css +1009 -0
  172. package/editor/preview/app.js +2122 -0
  173. package/editor/preview/index.html +307 -0
  174. package/editor/pyproject.toml +23 -0
  175. package/editor/references/3d.md +236 -0
  176. package/editor/references/animacao-catalogo.md +672 -0
  177. package/editor/references/animacao.md +498 -0
  178. package/editor/references/comandos.md +92 -0
  179. package/editor/references/corte-seco-como-funciona.md +50 -0
  180. package/editor/references/corte-seco.md +88 -0
  181. package/editor/references/corte.md +290 -0
  182. package/editor/references/direcao-por-blocos.md +218 -0
  183. package/editor/references/enquadramento.md +654 -0
  184. package/editor/references/estilos-prontos.md +355 -0
  185. package/editor/references/estudio.md +100 -0
  186. package/editor/references/exemplo-eventos.json +67 -0
  187. package/editor/references/lettering.md +252 -0
  188. package/editor/references/modelos.md +494 -0
  189. package/editor/references/phase2.md +1007 -0
  190. package/editor/references/referencia-aplicar.md +203 -0
  191. package/editor/references/referencia-medir.md +375 -0
  192. package/editor/references/revisao.md +335 -0
  193. package/editor/references/som-e-trilha.md +146 -0
  194. package/editor/references/tabela-de-sons.md +130 -0
  195. package/editor/references/variacoes.md +234 -0
  196. package/editor/uv.lock +1141 -0
  197. package/lib/act.js +36 -8
  198. package/lib/catalogo.js +4 -0
  199. package/lib/chamada-torta.js +81 -0
  200. package/lib/editor-pro.js +786 -0
  201. package/lib/entrega.js +58 -0
  202. package/lib/estudio/conferencia-visual.js +76 -0
  203. package/lib/estudio/diretor.js +6 -1
  204. package/lib/estudio/exportar.js +3 -1
  205. package/lib/estudio/gosto.js +45 -4
  206. package/lib/estudio/index.js +8 -5
  207. package/lib/estudio/kit-ae/base.jsx +119 -13
  208. package/lib/estudio/kit-ae/cenas.jsx +47 -15
  209. package/lib/estudio/kit-ae/guarda.jsx +274 -0
  210. package/lib/estudio/kit-ae/primitivas.jsx +180 -24
  211. package/lib/estudio/maquina-diretor.js +61 -7
  212. package/lib/estudio/maquina-foto.js +177 -0
  213. package/lib/estudio/maquina-guarda.js +207 -0
  214. package/lib/estudio/maquina-layout.js +22 -1
  215. package/lib/estudio/maquina.js +60 -11
  216. package/lib/estudio/referencias.js +1 -1
  217. package/lib/estudio/visao/visao.swift +97 -0
  218. package/lib/estudio/visao.js +60 -0
  219. package/lib/local/cerebro.json +192 -6
  220. package/lib/local/motor.js +5 -2
  221. package/lib/mcp.js +105 -7
  222. package/lib/nuvem.js +11 -1
  223. package/lib/outra-pasta.js +1 -1
  224. package/lib/passagem.js +50 -0
  225. package/lib/perigo.js +29 -12
  226. package/lib/protecao.js +134 -0
  227. package/lib/sandbox.js +11 -4
  228. package/lib/titulo-conversa.js +46 -0
  229. package/lib/tools.js +3 -0
  230. package/lib/ui.js +1 -1
  231. package/package.json +3 -2
  232. package/skills/editar-meu-video/SKILL.md +6 -2
  233. package/skills/editar-video/SKILL.md +113 -0
  234. package/studio/pessoa.py +52 -0
  235. package/voz/primo_voz/app.py +43 -4
  236. package/voz/primo_voz/chat.html +17 -6
  237. package/voz/primo_voz/painel_dados.py +134 -0
package/lib/act.js CHANGED
@@ -10,6 +10,15 @@
10
10
 
11
11
  'use strict';
12
12
 
13
+ /* A EDIÇÃO COMPLETA de vídeo falado (20/10/2026): o motor do EDIT IA PRO, pela
14
+ ferramenta editor_pro ou, com servidor antigo, pelo `primocode editor` no
15
+ run_shell. É o caminho SE a pessoa quer o vídeo editado; quem decide é o modelo. */
16
+ const EDICAO_DE_VIDEO_FALADO = 'SE ELA QUER A GRAVAÇÃO DELA FALANDO EDITADA DE VERDADE (a edição completa: "edita meu vídeo", "faz um reels disso", '
17
+ + '"coloca legenda e efeitos", corte + legenda + gancho + efeitos + sons + trilha), o caminho é o editor_pro (motor EDIT IA PRO; a skill editar-video explica): '
18
+ + 'acao:"cortar" {video} → leia a fala que volta, com os tempos → acao:"montar" {pasta, plano:{gancho, pecas, broll}} → entregue <pasta>/final.mp4 só com o portão PASSOU '
19
+ + '(atalho sem plano: acao:"editar"). Se editor_pro não estiver na sua lista de ferramentas, rode o mesmo pelo run_shell: '
20
+ + '`primocode editor cortar --json \'{"video":"<arquivo>"}\'` (montar e editar do mesmo jeito; a saída é uma linha de JSON).\n';
21
+
13
22
  const { c, Spinner, PENSANDO } = require('./ui');
14
23
  const fala = require('./fala');
15
24
  const especialistas = require('./especialistas');
@@ -31,6 +40,7 @@ const tempos = require('./tempos');
31
40
  const preLeitura = require('./pre-leitura');
32
41
  const travado = require('./travado');
33
42
  const auditoria = require('./auditoria');
43
+ const chamadaTorta = require('./chamada-torta');
34
44
 
35
45
  // 40, não 15: com o freio de repetição (repeticao.js) e o de rodada parada,
36
46
  // volta a mais não é volta em círculo — é trabalho. Quinze acabavam no meio
@@ -939,13 +949,18 @@ async function runAct(userPrompt, opts) {
939
949
  // Vídeo que o Estúdio fez se edita no Remotion Studio, não no editor por linha do tempo.
940
950
  const EDITAR_DO_ESTUDIO = 'SE ELA QUER EDITAR UM VÍDEO QUE O ESTÚDIO FEZ (não uma gravação dela): '
941
951
  + 'estudio_projeto acao:"editar" com o id do projeto abre o Remotion Studio no navegador; diga a pasta a ela e pare.\n';
952
+ const EDICAO_COMPLETA = EDICAO_DE_VIDEO_FALADO;
942
953
  const producao = diretor.precisaDeProducao(userPrompt);
943
954
  if (ehEdicaoDaGravacao) {
944
- // A gravação da pessoa: o editor por linha do tempo (lib/video/), pelo run_shell.
945
- messages.push({ role: 'system', content: EDITAR_DO_ESTUDIO + 'PARA EDITAR A GRAVAÇÃO DA PESSOA use o editor por linha do tempo via run_shell: '
946
- + 'SE A PESSOA SÓ DISSE "edite esse vídeo" (sem dizer o quê), O VÍDEO É O PEDIDO: `primocode video import --json \'{"path":"<arquivo>"}\'`, '
955
+ /* A gravação da pessoa FALANDO: a edição completa é do motor do EDIT IA PRO
956
+ (lib/editor-pro.js), decisão do Joel em 20/10 depois de comparar os dois no
957
+ mesmo vídeo. O editor por linha do tempo (lib/video/) fica para as operações
958
+ soltas. Quem escolhe entre os dois é o modelo, pelo que a pessoa pediu. */
959
+ messages.push({ role: 'system', content: EDITAR_DO_ESTUDIO + EDICAO_COMPLETA
960
+ + 'SE ela pediu UMA operação solta na gravação (cortar um trecho, juntar, exportar, trocar o fundo, um efeito que segue a mão), use o editor por linha do tempo via run_shell: '
961
+ + 'SE A GRAVAÇÃO TRAZ PEDIDOS FALADOS ("separe em camadas", "me coloca numa praia"): `primocode video import --json \'{"path":"<arquivo>"}\'`, '
947
962
  + 'depois `primocode video auto --json \'{}\'` (lê o que ela FALA na gravação e aplica cada efeito no momento em que diz), inspect, export e abra o mp4. '
948
- + 'Senão: '
963
+ + 'Nos outros casos: '
949
964
  + 'rode `primocode video help` UMA vez (lista as operações), depois import → remove_silence/remove_words → add_captions → inspect (olhe o png) → export. '
950
965
  + 'Cada edição devolve um delta curto e tem undo: edite sem pedir licença a cada passo.\n'
951
966
  /* "deixar os vídeos cinematográficos… fazer um color grading sozinha" (13/10). */
@@ -979,7 +994,7 @@ async function runAct(userPrompt, opts) {
979
994
  resposta é o modelo. Então isto é o caminho SE for produzir, e não
980
995
  mais uma ordem de produzir. */
981
996
  messages.push({ role: 'system', content:
982
- EDITAR_DO_ESTUDIO + 'VOCÊ DECIDE o que entregar, pelo que a pessoa pediu: se ela quer só o roteiro, a ideia, um texto ou uma resposta, ESCREVA isso e pare — não produza vídeo. '
997
+ EDITAR_DO_ESTUDIO + EDICAO_COMPLETA + 'VOCÊ DECIDE o que entregar, pelo que a pessoa pediu: se ela quer só o roteiro, a ideia, um texto ou uma resposta, ESCREVA isso e pare — não produza vídeo. '
983
998
  + `SE ela quer a peça pronta (formato "${producao.formato === 'apresentacao' ? 'slides' : 'video'}"), faça em três passos: `
984
999
  + `estudio_projeto acao:"criar" com formato "${producao.formato === 'apresentacao' ? 'slides' : 'video'}" → `
985
1000
  + 'estudio_plano com "roteiro" (partes com tipo e fala; o PrimoCode faz layout, voz, ícones, música e sons) → '
@@ -1356,6 +1371,7 @@ async function runAct(userPrompt, opts) {
1356
1371
  const chavesDoLote = new Set();
1357
1372
  const leituras = toolCalls.filter(ehLeitura).filter((tc) => {
1358
1373
  if (tc.name === 'pesquisar_referencia' && pesquisasSecas >= 3) return false;
1374
+ if (chamadaTorta.ehTorta(tc.arguments)) return false;
1359
1375
  const { repetida, chave } = repeticao.espiar(jaChamado, tc.name, tc.arguments);
1360
1376
  if (repetida || chavesDoLote.has(chave)) return false;
1361
1377
  chavesDoLote.add(chave);
@@ -1373,6 +1389,14 @@ async function runAct(userPrompt, opts) {
1373
1389
 
1374
1390
  let motivoTravou = null;
1375
1391
  for (const tc of toolCalls) {
1392
+ /* O JSON da chamada veio quebrado (lib/chamada-torta.js): a
1393
+ ferramenta não roda, e o modelo recebe o erro com os argumentos
1394
+ crus para se corrigir — em vez de rodar com `{}` e repetir. */
1395
+ if (chamadaTorta.ehTorta(tc.arguments)) {
1396
+ anotar(tc, 'recusada', 'argumentos não são JSON válido');
1397
+ messages.push({ role: 'tool', tool_call_id: tc.id, content: chamadaTorta.erroParaOModelo(tc.name, tc.arguments) });
1398
+ continue;
1399
+ }
1376
1400
  if (PARAR) break;
1377
1401
  prova.ver(tc);
1378
1402
  if (tc.name === 'finish') {
@@ -1769,9 +1793,12 @@ async function runAct(userPrompt, opts) {
1769
1793
  // que "parou sem concluir" não pode virar fato para o passo seguinte.
1770
1794
  const concluiu = Boolean(finalText) && !PARAR;
1771
1795
 
1796
+ let passagemDaParada = null;
1772
1797
  if (paradoPorTravar && !finalText) {
1773
1798
  finalText = paradoPorTravar;
1774
1799
  if (!subagent) fala.aviso(finalText);
1800
+ // Parou sem terminar: a memória leva o estado, não só "parei" (lib/passagem.js).
1801
+ passagemDaParada = require('./passagem').montar({ pedido: userPrompt, motivo: finalText, registro: livro, falhasPendentes });
1775
1802
  }
1776
1803
 
1777
1804
  if (PARAR && !finalText) {
@@ -1786,6 +1813,7 @@ async function runAct(userPrompt, opts) {
1786
1813
  if (!finalText) {
1787
1814
  finalText = motivoDaParada({ voltas, voltasEmFalso, falhasPendentes, travou: rodadasParadas >= MAX_RODADAS_PARADAS, teto });
1788
1815
  if (!subagent) fala.aviso(finalText);
1816
+ passagemDaParada = require('./passagem').montar({ pedido: userPrompt, motivo: finalText, registro: livro, falhasPendentes });
1789
1817
  }
1790
1818
 
1791
1819
  // Nada de arquivo mexido = nada para lembrar. E grava em `pastaAtual`, não em
@@ -1799,7 +1827,7 @@ async function runAct(userPrompt, opts) {
1799
1827
  // A raiz de trabalho não é projeto: um memory.md solto em ~/primocode
1800
1828
  // era o que um pedido de vídeo (que trabalha na raiz) deixava para trás.
1801
1829
  if (!subagent && temPasta && require('path').resolve(pastaAtual) !== require('path').resolve(cfg.ROOT_DIR)) {
1802
- cfg.appendProjectMemory(pastaAtual, `**Pedido:** ${userPrompt.slice(0, 300)}\n**Resultado:** ${finalText.slice(0, 500)}`);
1830
+ cfg.appendProjectMemory(pastaAtual, passagemDaParada || `**Pedido:** ${userPrompt.slice(0, 300)}\n**Resultado:** ${finalText.slice(0, 500)}`);
1803
1831
  }
1804
1832
 
1805
1833
  // A memória GERAL é gravada sempre, tenha havido pasta ou não.
@@ -1892,7 +1920,7 @@ function lembreteDeParalelo(todos, naRodada) {
1892
1920
  dele, e é o que deixa o pai mandar a falha de volta para conserto (o laço
1893
1921
  do Qwen: planeja → despacha → confere → conserta). Pura, para o teste. */
1894
1922
  function entregaDoAgente(quem, texto, reg) {
1895
- const linhas = [`ENTREGA DO ${String(quem).toUpperCase()}`, String(texto).trim().slice(0, 4000)];
1923
+ const linhas = [`ENTREGA DO ${String(quem).toUpperCase()}`, require('./entrega').limitar(texto, { quem }).texto];
1896
1924
  if (reg) {
1897
1925
  const lista = (nome, xs) => { if (xs && xs.length) linhas.push(`${nome}: ${xs.slice(0, 15).join(', ')}`); };
1898
1926
  lista('criou', reg.criados);
@@ -2042,5 +2070,5 @@ function novoPortaoDeProva() {
2042
2070
  };
2043
2071
  }
2044
2072
 
2045
- module.exports = { novoPortaoDeProva, runAct, videoForaDeEdicao, entregaDoAgente, lembreteDeParalelo, buildMemoryContext, leituraPeloShell, historicoEnxuto, interromper, mandarDuranteATarefa, trabalhando, sobrasDaCaixa, entregarRecados, compactar, motivoDaParada, pareceParadaNoMeio, ehTetoDeToken, ehTransitorio, esperaDoErro,
2073
+ module.exports = { EDICAO_DE_VIDEO_FALADO, novoPortaoDeProva, runAct, videoForaDeEdicao, entregaDoAgente, lembreteDeParalelo, buildMemoryContext, leituraPeloShell, historicoEnxuto, interromper, mandarDuranteATarefa, trabalhando, sobrasDaCaixa, entregarRecados, compactar, motivoDaParada, pareceParadaNoMeio, ehTetoDeToken, ehTransitorio, esperaDoErro,
2046
2074
  anotacaoDoQueJaFoi, encolherParaContinuar, MAX_ITERATIONS };
package/lib/catalogo.js CHANGED
@@ -152,6 +152,10 @@ const GRUPOS = [
152
152
  + 'vozes: true lista as vozes. '
153
153
  + 'Use os tempos que voltam para a duração das cenas — estimar por número de palavras erra em segundos.' },
154
154
 
155
+ { tool: 'editor_pro', escreve: true, faz: 'a EDIÇÃO COMPLETA de um vídeo falado da pessoa (o motor do EDIT IA PRO): corte da melhor tomada sem respiro, voz limpa e no volume, legenda animada, gancho, câmera viva, peças, b-roll, sons, trilha com ducking e portão de qualidade',
156
+ args: 'acao: editar | cortar | montar | preparar | estado. video (a gravação; o original nunca é tocado). pasta (a da edição, devolvida por cortar). prompt (nomes difíceis da fala). '
157
+ + 'cortar devolve a fala do corte com os tempos; com ela, montar recebe plano {gancho:"Texto *destaque*", pecas:[lettering|lista_check|passo_a_passo|contador|rotulo|carimbo...], broll:[{busca,de,ate,rotulo}], blocos?, estilo?, legenda?, correcoes?} e trilha (auto | arquivo | false). '
158
+ + 'Sai em <pasta>/final.mp4, só com o portão PASSOU. Leia a skill editar-video.' },
155
159
  { tool: 'estudio_video', escreve: true, faz: 'o que se faz com a gravação do usuário: importar, medir, cortar silêncio, transcrever, recortar a pessoa',
156
160
  args: 'id. acao: editar | camadas | importar | medir | silencio | cortar-silencio | quadro | legendas | recortar-pessoa. '
157
161
  + 'editar: FAZ A EDIÇÃO INTEIRA sozinho — corta o silêncio, transcreve palavra por palavra e monta o plano '
@@ -0,0 +1,81 @@
1
+ /**
2
+ * chamada-torta.js — o JSON da chamada de ferramenta veio quebrado.
3
+ *
4
+ * Visto no goose (AAIF, Apache-2.0; só a ideia, código nosso): em vez de
5
+ * jogar fora a chamada mal formada, 1) tenta recuperar o objeto por uma
6
+ * cascata (JSON → cerca de markdown → objeto achado por chaves balanceadas →
7
+ * vírgula sobrando) e 2) se não der, DEVOLVE O ERRO AO MODELO, com os
8
+ * argumentos crus, para ele se corrigir na volta seguinte.
9
+ *
10
+ * Antes, o motor local fazia `catch { /* o loop pede de novo *​/ }` e rodava a
11
+ * ferramenta com `{}`: o `write_file` sem path respondia "path é obrigatório",
12
+ * o modelo não sabia que o problema era a sintaxe, e repetia o mesmo JSON.
13
+ *
14
+ * Puro, sem I/O: o teste mede a cascata inteira.
15
+ */
16
+
17
+ 'use strict';
18
+
19
+ const MARCA = '__json_torto';
20
+ const MAX_CRU = 600;
21
+
22
+ /** Primeiro objeto `{…}` com chaves balanceadas (respeita aspas e escapes). */
23
+ function objetoBalanceado(s) {
24
+ const ini = s.indexOf('{');
25
+ if (ini < 0) return null;
26
+ let fundo = 0, aspa = false, esc = false;
27
+ for (let i = ini; i < s.length; i++) {
28
+ const ch = s[i];
29
+ if (aspa) { if (esc) esc = false; else if (ch === '\\') esc = true; else if (ch === '"') aspa = false; continue; }
30
+ if (ch === '"') aspa = true;
31
+ else if (ch === '{') fundo++;
32
+ else if (ch === '}' && --fundo === 0) return s.slice(ini, i + 1);
33
+ }
34
+ return null;
35
+ }
36
+
37
+ const semVirgulaSobrando = (s) => s.replace(/,\s*([}\]])/g, '$1');
38
+
39
+ function comoObjeto(v) {
40
+ if (typeof v === 'string') { try { return comoObjeto(JSON.parse(v)); } catch { return null; } } // JSON dentro de JSON
41
+ if (Array.isArray(v)) return v.length === 1 ? comoObjeto(v[0]) : null;
42
+ return v && typeof v === 'object' ? v : null;
43
+ }
44
+
45
+ /** @returns {{ok: true, args: object, como: string} | {ok: false}} */
46
+ function recuperar(bruto) {
47
+ if (bruto && typeof bruto === 'object') return { ok: true, args: bruto, como: 'objeto' };
48
+ const s = String(bruto == null ? '' : bruto).trim();
49
+ if (!s) return { ok: true, args: {}, como: 'vazio' };
50
+ const tentativas = [['json', s]];
51
+ const cerca = s.match(/```(?:json)?\s*([\s\S]*?)```/i);
52
+ if (cerca) tentativas.push(['cerca', cerca[1].trim()]);
53
+ const solto = objetoBalanceado(s);
54
+ if (solto && !s.startsWith('[')) tentativas.push(['chaves balanceadas', solto]);
55
+ for (const [como, t] of [...tentativas]) tentativas.push([como + ' sem vírgula sobrando', semVirgulaSobrando(t)]);
56
+ for (const [como, t] of tentativas) {
57
+ try {
58
+ const o = comoObjeto(JSON.parse(t));
59
+ if (o) return { ok: true, args: o, como };
60
+ } catch { /* próxima */ }
61
+ }
62
+ return { ok: false };
63
+ }
64
+
65
+ /** Os argumentos que o motor entrega quando nem a cascata salvou. */
66
+ function marcar(bruto) { return { [MARCA]: String(bruto == null ? '' : bruto) }; }
67
+ function ehTorta(args) { return !!args && typeof args === 'object' && typeof args[MARCA] === 'string'; }
68
+
69
+ /** O texto que volta ao modelo no lugar do resultado da ferramenta. */
70
+ function erroParaOModelo(nome, args) {
71
+ const cru = String(args[MARCA] || '');
72
+ const parte = cru.length > MAX_CRU ? cru.slice(0, MAX_CRU) + `…(+${cru.length - MAX_CRU} caracteres)` : cru;
73
+ return JSON.stringify({
74
+ ok: false,
75
+ error: `A chamada de "${nome}" NÃO rodou: os argumentos não são um JSON válido (aspas sem fechar, vírgula no lugar errado ou texto em volta).`,
76
+ argumentosRecebidos: parte,
77
+ comoCorrigir: 'Chame a ferramenta de novo com UM objeto JSON válido. Em texto longo, escape as aspas (\\") e as quebras de linha (\\n). Se o conteúdo é grande, divida em arquivos menores.',
78
+ });
79
+ }
80
+
81
+ module.exports = { recuperar, marcar, ehTorta, erroParaOModelo, objetoBalanceado, MARCA };