primocode 10.15.2 → 10.17.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.
Files changed (245) 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 +74 -9
  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 +38 -8
  198. package/lib/app-chat.js +97 -0
  199. package/lib/catalogo.js +7 -1
  200. package/lib/chamada-torta.js +81 -0
  201. package/lib/editor-pro.js +786 -0
  202. package/lib/entrega.js +58 -0
  203. package/lib/estudio/conferencia-visual.js +76 -0
  204. package/lib/estudio/diretor.js +6 -1
  205. package/lib/estudio/exportar.js +3 -1
  206. package/lib/estudio/gosto/tela.html +1349 -0
  207. package/lib/estudio/gosto.js +305 -0
  208. package/lib/estudio/index.js +12 -1
  209. package/lib/estudio/kit-ae/base.jsx +119 -13
  210. package/lib/estudio/kit-ae/cenas.jsx +47 -15
  211. package/lib/estudio/kit-ae/guarda.jsx +274 -0
  212. package/lib/estudio/kit-ae/primitivas.jsx +180 -24
  213. package/lib/estudio/maquina-diretor.js +70 -12
  214. package/lib/estudio/maquina-foto.js +177 -0
  215. package/lib/estudio/maquina-guarda.js +207 -0
  216. package/lib/estudio/maquina-layout.js +22 -1
  217. package/lib/estudio/maquina.js +64 -11
  218. package/lib/estudio/referencias.js +1 -1
  219. package/lib/estudio/visao/visao.swift +97 -0
  220. package/lib/estudio/visao.js +60 -0
  221. package/lib/headless.js +15 -3
  222. package/lib/local/cerebro.json +285 -7
  223. package/lib/local/motor.js +5 -2
  224. package/lib/memoria-usuario.js +164 -0
  225. package/lib/nuvem.js +33 -2
  226. package/lib/passagem.js +50 -0
  227. package/lib/perigo.js +19 -11
  228. package/lib/protecao.js +134 -0
  229. package/lib/repeticao.js +1 -1
  230. package/lib/sandbox.js +57 -9
  231. package/lib/titulo-conversa.js +46 -0
  232. package/lib/tools.js +23 -4
  233. package/lib/ui.js +2 -2
  234. package/package.json +3 -2
  235. package/skills/editar-meu-video/SKILL.md +6 -2
  236. package/skills/editar-video/SKILL.md +113 -0
  237. package/studio/pessoa.py +52 -0
  238. package/voz/primo_voz/__main__.py +55 -40
  239. package/voz/primo_voz/app.py +500 -4
  240. package/voz/primo_voz/chat.html +1773 -0
  241. package/voz/primo_voz/conversa.py +0 -26
  242. package/voz/primo_voz/hud.html +8 -2
  243. package/voz/primo_voz/hud.py +129 -5
  244. package/voz/primo_voz/identidade.py +1 -1
  245. package/voz/primo_voz/painel_dados.py +134 -0
package/lib/entrega.js ADDED
@@ -0,0 +1,58 @@
1
+ /**
2
+ * entrega.js — relatório grande não se perde: corta e guarda o resto.
3
+ *
4
+ * Visto no pi-desktop (vastsa, LGPL-3.0; só a ideia, código nosso): o relatório
5
+ * do subagente tem teto, e o que passa do teto vai para um arquivo, com o
6
+ * caminho no fim do texto. Antes, o `entregaDoAgente` fazia `.slice(0, 4000)`
7
+ * e o resto sumia: o especialista escrevia 9 mil caracteres de achados e o
8
+ * agente principal lia a metade, sem saber que faltava metade.
9
+ *
10
+ * O corte cai no fim de um parágrafo (ou de uma linha), nunca no meio de uma
11
+ * palavra. O arquivo mora na pasta temporária e é liberado para leitura, então
12
+ * o `read_file` do agente principal alcança.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ const fs = require('fs');
18
+ const os = require('os');
19
+ const path = require('path');
20
+
21
+ const TETO = 4000;
22
+
23
+ function pontoDeCorte(texto, teto) {
24
+ const trecho = texto.slice(0, teto);
25
+ for (const sep of ['\n\n', '\n', '. ']) {
26
+ const i = trecho.lastIndexOf(sep);
27
+ if (i > teto * 0.6) return i + (sep === '. ' ? 1 : 0);
28
+ }
29
+ return teto;
30
+ }
31
+
32
+ /**
33
+ * @returns {{texto: string, arquivo: string|null, cortado: boolean}}
34
+ * `gravar(texto, quem)` devolve o caminho do arquivo (injetável no teste).
35
+ */
36
+ function limitar(texto, { teto = TETO, quem = 'agente', gravar = gravarNaTemp } = {}) {
37
+ const t = String(texto == null ? '' : texto).trim();
38
+ if (t.length <= teto) return { texto: t, arquivo: null, cortado: false };
39
+ const corte = pontoDeCorte(t, teto);
40
+ let arquivo = null;
41
+ try { arquivo = gravar(t, quem); } catch { /* sem disco: corta e avisa mesmo assim */ }
42
+ const aviso = arquivo
43
+ ? `\n\n(…relatório cortado: ${t.length} caracteres, faltam ${t.length - corte}. O texto inteiro está em ${arquivo} — leia com read_file se precisar do resto.)`
44
+ : `\n\n(…relatório cortado: ${t.length} caracteres, faltam ${t.length - corte}. Não deu para guardar o resto; peça de novo ao agente, mais curto.)`;
45
+ return { texto: t.slice(0, corte).trimEnd() + aviso, arquivo, cortado: true };
46
+ }
47
+
48
+ function gravarNaTemp(texto, quem) {
49
+ const dir = path.join(os.tmpdir(), 'primocode-entregas');
50
+ fs.mkdirSync(dir, { recursive: true });
51
+ const nome = `${Date.now()}-${String(quem).toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 30) || 'agente'}.md`;
52
+ const arquivo = path.join(dir, nome);
53
+ fs.writeFileSync(arquivo, texto, 'utf8');
54
+ try { require('./tools').liberarLeitura(dir); } catch { /* sem tools: o arquivo existe do mesmo jeito */ }
55
+ return arquivo;
56
+ }
57
+
58
+ module.exports = { limitar, TETO };
@@ -0,0 +1,76 @@
1
+ /**
2
+ * conferencia-visual.js — o olho DEPOIS do render: o quadro de cada cena, lido de verdade.
3
+ *
4
+ * conferir({quadros, pl, guarda, visao}) → {olho: 'vision'|'caixas', problemas: [{cena, tipo, texto}], leituras}
5
+ *
6
+ * Com o Vision do macOS (lib/estudio/visao.js): o texto que aparece no quadro (OCR) e os rostos. Reprova:
7
+ * borda texto a menos de 3% da beira do quadro (colado na borda)
8
+ * rosto texto em cima de um rosto
9
+ * encavalado duas linhas de texto uma em cima da outra
10
+ * Sempre (com ou sem o Vision): as caixas finais da guarda do kit (linhas "GUARDA {json}") conferidas de novo
11
+ * (maquina-guarda.verificarCaixas): sobreposição e fora da zona segura. Sem Vision, é só isso ("caixas").
12
+ * Puro na decisão (julgarLeitura): testável sem quadro nem Vision.
13
+ */
14
+ 'use strict';
15
+
16
+ const G = require('./maquina-guarda.js');
17
+
18
+ const LIM = { borda: 0.03, conf: 0.5, alturaMin: 0.012, rostoMin: 0.004 };
19
+ const area = (c) => Math.max(0, c[2] - c[0]) * Math.max(0, c[3] - c[1]);
20
+ const inter = (a, b) => Math.max(0, Math.min(a[2], b[2]) - Math.max(a[0], b[0])) * Math.max(0, Math.min(a[3], b[3]) - Math.max(a[1], b[1]));
21
+
22
+ /** Os problemas de UM quadro lido pelo Vision ({w, h, textos:[{texto, conf, caixa}], rostos:[caixa]}). */
23
+ function julgarLeitura(q, cena, { foto = null } = {}) {
24
+ const out = [];
25
+ if (!q || !q.ok || !q.w || !q.h) return out;
26
+ const W = q.w, H = q.h;
27
+ const textos = (q.textos || []).filter((t) => t.conf >= LIM.conf && (t.caixa[3] - t.caixa[1]) >= H * LIM.alturaMin && String(t.texto).replace(/[^A-Za-zÀ-ÿ0-9]/g, '').length >= 2);
28
+ // com a caixa da foto (já na escala do quadro), só vale rosto DENTRO dela: o fundo desfocado é a mesma foto ampliada e também tem rosto
29
+ const naFoto = (r) => !foto || ((r[0] + r[2]) / 2 >= foto[0] && (r[0] + r[2]) / 2 <= foto[2] && (r[1] + r[3]) / 2 >= foto[1] && (r[1] + r[3]) / 2 <= foto[3]);
30
+ const rostos = (q.rostos || []).filter((r) => area(r) >= W * H * LIM.rostoMin && naFoto(r));
31
+ for (const t of textos) {
32
+ const c = t.caixa;
33
+ if (c[0] < W * LIM.borda || c[2] > W * (1 - LIM.borda) || c[1] < H * LIM.borda || c[3] > H * (1 - LIM.borda)) out.push({ cena, tipo: 'borda', texto: `texto colado na borda: "${t.texto}"` });
34
+ for (const r of rostos) if (inter(c, r) > 0.15 * area(c)) out.push({ cena, tipo: 'rosto', texto: `texto sobre o rosto: "${t.texto}"` });
35
+ }
36
+ for (let i = 0; i < textos.length; i++) for (let j = i + 1; j < textos.length; j++) {
37
+ const a = textos[i].caixa, b = textos[j].caixa;
38
+ if (inter(a, b) > 0.3 * Math.min(area(a), area(b))) out.push({ cena, tipo: 'encavalado', texto: `textos encavalados: "${textos[i].texto}" × "${textos[j].texto}"` });
39
+ }
40
+ return out;
41
+ }
42
+
43
+ /** As linhas "GUARDA {json}" que o kit escreveu (uma por cena). */
44
+ function lerGuarda(saida) {
45
+ return String(saida || '').split('\n').filter((l) => /^GUARDA \{/.test(l)).map((l) => { try { return JSON.parse(l.slice(7)); } catch { return null; } }).filter(Boolean);
46
+ }
47
+
48
+ /** `quadros[i]` é o quadro da cena i. `guarda` = lerGuarda(saida). `visao` injetável (testes); null = sem olho. */
49
+ function conferir({ quadros = [], pl = {}, guarda = [], visao } = {}) {
50
+ const problemas = [];
51
+ const legenda = !!(pl.legenda && pl.legenda.chunks && pl.legenda.chunks.length);
52
+ for (const g of guarda) {
53
+ for (const v of G.verificarCaixas(g.caixas, g.w || pl.w, g.h || pl.h, { legenda })) problemas.push({ cena: g.cena, tipo: /fora|trilho/.test(v) ? 'zona' : 'sobreposicao', texto: v });
54
+ }
55
+ let V = visao;
56
+ if (V === undefined) { try { V = require('./visao.js'); } catch { V = null; } }
57
+ let olho = 'caixas', leituras = null;
58
+ if (V && V.disponivel() && quadros.length) {
59
+ const r = V.ler(quadros);
60
+ if (r && r.ok) {
61
+ olho = 'vision'; leituras = r.quadros;
62
+ r.quadros.forEach((q) => {
63
+ const i = quadros.indexOf(q.arquivo);
64
+ if (i < 0) return;
65
+ // a caixa da foto (layout) levada pro quadro: escala do quadro, câmera ~0,94 em volta do centro, 20% de folga
66
+ const g = guarda.find((x) => x.cena === i), fc = g && (g.caixas || []).find((c) => c.tipo === 'foto');
67
+ let foto = null;
68
+ if (fc && q.w) { const W0 = g.w || pl.w, H0 = g.h || pl.h, k = q.w / W0, cx = W0 / 2, cy = H0 / 2, e = (x, c0) => (c0 + (x - c0) * 0.94) * k; const fw = (fc.c[2] - fc.c[0]) * 0.1 * k, fh = (fc.c[3] - fc.c[1]) * 0.1 * k; foto = [e(fc.c[0], cx) - fw, e(fc.c[1], cy) - fh, e(fc.c[2], cx) + fw, e(fc.c[3], cy) + fh]; }
69
+ problemas.push(...julgarLeitura(q, i, { foto }));
70
+ });
71
+ }
72
+ }
73
+ return { olho, problemas, leituras };
74
+ }
75
+
76
+ module.exports = { conferir, julgarLeitura, lerGuarda, LIM };
@@ -77,9 +77,14 @@ const PEDE_EFEITO = /\b(tir[ae]r?|remov\w*|troc\w*)\s+(o\s+)?fundo\b|\bsepar\w*\
77
77
  arquivo de vídeo em qualquer lugar da frase é edição. */
78
78
  const EDITA_ARQUIVO = /\b(edit\w*|edi[cç][aã]o|p[oõ]e\s+(ele\s+)?pra\s+editar)\b[\s\S]*\.(mp4|mov|mkv|webm|m4v)\b|\.(mp4|mov|mkv|webm|m4v)\b[\s\S]*\b(edit\w*|edi[cç][aã]o)\b/i;
79
79
 
80
+ /* A gravação da pessoa FALANDO, sem caminho de arquivo na frase (20/10, a edição completa do
81
+ editor_pro): "edita meu vídeo", "faz um reels disso", "coloca legenda e efeitos nele". Fala de
82
+ uma gravação que JÁ existe ("disso", "meu vídeo", "nele"), não de criar um vídeo do zero. */
83
+ const PEDE_EDICAO_FALADA = /\bedit\w*\s+(o\s+|esse\s+|este\s+)?(meu\s+)?(v[ií]deo|grava[cç][aã]o)\s+(meu|que\s+eu\s+gravei)\b|\bedit\w*\s+(o\s+)?meu\s+v[ií]deo\b|\b(faz|fa[cç]a|transform\w*|vir\w*)\s+(um\s+|uma\s+|em\s+)?(reels?|tiktok|shorts?|criativo|corte)\s+(disso|desse|dessa|deste|desta|com\s+(esse|essa|este|esta|a\s+minha|o\s+meu))\b|\bcoloc\w*\s+(uma\s+)?legendas?\s+e\s+(uns\s+)?efeitos?\b|\b(legend\w*|efeitos?)\b[\s\S]{0,30}\b(no\s+meu\s+v[ií]deo|na\s+minha\s+grava[cç][aã]o|nele|nessa\s+grava[cç][aã]o)\b/i;
84
+
80
85
  function precisaDeEdicao(texto) {
81
86
  const t = String(texto || '');
82
- return PEDE_EDICAO.test(t) || PEDE_EFEITO.test(t) || EDITA_ARQUIVO.test(t);
87
+ return PEDE_EDICAO.test(t) || PEDE_EFEITO.test(t) || EDITA_ARQUIVO.test(t) || PEDE_EDICAO_FALADA.test(t);
83
88
  }
84
89
 
85
90
  // ── 2. as decisões que não são do modelo ─────────────────────────────────
@@ -154,7 +154,9 @@ function registrar({ id, assunto, caminho, formato, duracao, assinatura, entrega
154
154
  try { fs.mkdirSync(path.dirname(arq), { recursive: true }); fs.writeFileSync(arq, JSON.stringify(l.slice(-200), null, 2)); } catch { /* sem disco: segue */ }
155
155
  return item;
156
156
  }
157
- const listar = (arq) => ler(arq).filter((v) => v.caminho && fs.existsSync(v.caminho)).sort((a, b) => String(b.data).localeCompare(String(a.data)));
157
+ // mais novo primeiro; no empate de data (dois no mesmo milissegundo), vale a ordem de gravação: o último registrado vem antes
158
+ const listar = (arq) => ler(arq).map((v, i) => ({ v, i })).filter(({ v }) => v.caminho && fs.existsSync(v.caminho))
159
+ .sort((a, b) => String(b.v.data).localeCompare(String(a.v.data)) || b.i - a.i).map(({ v }) => v);
158
160
  function abrirNoSistema(alvo) {
159
161
  if (process.env.PRIMOCODE_SEM_NAVEGADOR === '1') return false; // app do Primo (voz): navegador só com clique explícito
160
162
  const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'cmd' : 'xdg-open';