@danhachuel/leadmaster 0.1.10 → 0.1.12
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/CHANGELOG.md +71 -0
- package/backend/__pycache__/main.cpython-311.pyc +0 -0
- package/backend/main.py +45 -10
- package/backend/services/__pycache__/__init__.cpython-311.pyc +0 -0
- package/backend/services/__pycache__/agents.cpython-311.pyc +0 -0
- package/backend/services/__pycache__/crm_agent.cpython-311.pyc +0 -0
- package/backend/services/__pycache__/extractors.cpython-311.pyc +0 -0
- package/backend/services/__pycache__/flags.cpython-311.pyc +0 -0
- package/backend/services/__pycache__/llm.cpython-311.pyc +0 -0
- package/backend/services/__pycache__/storage.cpython-311.pyc +0 -0
- package/backend/services/extractors.py +49 -0
- package/backend/tests/__pycache__/conftest.cpython-311-pytest-8.4.2.pyc +0 -0
- package/backend/tests/__pycache__/test_crm_routes.cpython-311-pytest-8.4.2.pyc +0 -0
- package/backend/tests/__pycache__/test_instagram_extractor.cpython-311-pytest-8.4.2.pyc +0 -0
- package/backend/tests/__pycache__/test_launcher_protections.cpython-311-pytest-8.4.2.pyc +0 -0
- package/backend/tests/__pycache__/test_maps_extractor.cpython-311-pytest-8.4.2.pyc +0 -0
- package/backend/tests/__pycache__/test_process_flags.cpython-311-pytest-8.4.2.pyc +0 -0
- package/backend/tests/test_instagram_extractor.py +51 -0
- package/backend/tests/test_launcher_protections.py +17 -3
- package/frontend/dist/assets/{index-lA_S1NDH.js → index-CLRV7oRl.js} +18 -18
- package/frontend/dist/assets/{index-D53_Dmef.css → index-D6u6-7Rs.css} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/scripts/cli.mjs +61 -2
package/scripts/cli.mjs
CHANGED
|
@@ -30,6 +30,21 @@ import path from 'node:path';
|
|
|
30
30
|
import { fileURLToPath } from 'node:url';
|
|
31
31
|
import http from 'node:http';
|
|
32
32
|
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Erros globais (blindagem anti-encerramento silencioso)
|
|
35
|
+
// Rejeições e exceções não tratadas são APENAS LOGADAS — nunca devem derrubar
|
|
36
|
+
// o launcher sem explicação (era assim que o MobaXterm perdia o processo sem
|
|
37
|
+
// deixar rastro). O launcher só termina pelo fluxo normal: erro acionável,
|
|
38
|
+
// parada legítima (SIGTERM/SIGBREAK) ou morte do servidor Python filho.
|
|
39
|
+
// NUNCA REMOVER (regra inviolável do AGENTS.md).
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
process.on('unhandledRejection', (reason) => {
|
|
42
|
+
console.error('Unhandled Rejection:', reason);
|
|
43
|
+
});
|
|
44
|
+
process.on('uncaughtException', (err) => {
|
|
45
|
+
console.error('Uncaught Exception:', err);
|
|
46
|
+
});
|
|
47
|
+
|
|
33
48
|
const PKG_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
34
49
|
|
|
35
50
|
// Porta padrão da UI/API local; se estiver ocupada, o launcher avança
|
|
@@ -372,6 +387,10 @@ function cmdStart(args) {
|
|
|
372
387
|
const url = `http://127.0.0.1:${porta}`;
|
|
373
388
|
if (jaRodando) {
|
|
374
389
|
console.log(`ℹ LeadMaster já está rodando em ${url} — abra o endereço no navegador.`);
|
|
390
|
+
// Saída INFORMATIVA (antes de qualquer inicialização própria): não há
|
|
391
|
+
// servidor filho para supervisionar nem terminal para prender — o
|
|
392
|
+
// launcher não deve chamar process.exit(0) no caminho de SUCESSO da
|
|
393
|
+
// inicialização (regra inviolável do AGENTS.md).
|
|
375
394
|
process.exit(0);
|
|
376
395
|
return;
|
|
377
396
|
}
|
|
@@ -438,6 +457,28 @@ function cmdStart(args) {
|
|
|
438
457
|
process.exit(code === null ? 1 : code);
|
|
439
458
|
});
|
|
440
459
|
|
|
460
|
+
// Ciclo de vida vinculado (regra inviolável do AGENTS.md): se o Python
|
|
461
|
+
// cai, o launcher cai junto — nunca fica preso ao terminal sem servidor.
|
|
462
|
+
// O worker nunca é desreferenciado do event loop: o pai não pode morrer
|
|
463
|
+
// sozinho enquanto o filho vive.
|
|
464
|
+
child.on('close', (code) => {
|
|
465
|
+
console.log('Servidor encerrado');
|
|
466
|
+
process.exit(code === null ? 1 : code);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// Launcher morrendo encerra o worker e vice-versa (regra inviolável):
|
|
470
|
+
// qualquer caminho de saída (erro inesperado, falha de health, sinais)
|
|
471
|
+
// leva o worker Python junto — nada de processos órfãos na máquina.
|
|
472
|
+
process.on('exit', () => {
|
|
473
|
+
if (child && child.pid) {
|
|
474
|
+
if (platform() === 'win32') {
|
|
475
|
+
spawnSync('taskkill', ['/pid', String(child.pid), '/T', '/F'], { windowsHide: true });
|
|
476
|
+
} else {
|
|
477
|
+
child.kill('SIGTERM');
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
|
|
441
482
|
const stop = () => {
|
|
442
483
|
console.log('\nEncerrando LeadMaster...');
|
|
443
484
|
if (platform() === 'win32' && child.pid) {
|
|
@@ -447,6 +488,16 @@ function cmdStart(args) {
|
|
|
447
488
|
}
|
|
448
489
|
};
|
|
449
490
|
|
|
491
|
+
// Morte do launcher → morte do filho (e vice-versa, via close acima):
|
|
492
|
+
// o uvicorn nunca fica órfão no terminal quando o Node é encerrado.
|
|
493
|
+
process.on('exit', () => {
|
|
494
|
+
try {
|
|
495
|
+
child.kill('SIGTERM');
|
|
496
|
+
} catch {
|
|
497
|
+
/* filho já encerrou — nada a fazer */
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
|
|
450
501
|
console.log(`→ Subindo servidor local em ${url} ...`);
|
|
451
502
|
const health = await waitForHealth(porta, 120000);
|
|
452
503
|
if (!health) {
|
|
@@ -476,10 +527,18 @@ function cmdStart(args) {
|
|
|
476
527
|
process.on('SIGBREAK', naoAbsorver);
|
|
477
528
|
}
|
|
478
529
|
|
|
479
|
-
// Keep-alive: mantém o event loop ativo
|
|
480
|
-
// minimizado / sem stream ativo)
|
|
530
|
+
// Keep-alive (regra inviolável do AGENTS.md): mantém o event loop ativo
|
|
531
|
+
// mesmo sem I/O de console (MobaXterm minimizado / sem stream ativo).
|
|
481
532
|
setInterval(() => {}, 1000);
|
|
482
533
|
|
|
534
|
+
// Terminal preso (regra inviolável do AGENTS.md) — SOLUÇÃO DEFINITIVA:
|
|
535
|
+
// ao retomar a entrada padrão IMEDIATAMENTE antes das mensagens finais
|
|
536
|
+
// de sucesso, o Node permanece vivo indefinidamente aguardando qualquer
|
|
537
|
+
// digitação do usuário. O prompt do MobaXterm NUNCA é devolvido e a PTY
|
|
538
|
+
// (e com ela o uvicorn) não é fechada. Esta linha NÃO depende de timers
|
|
539
|
+
// nem de npx — NUNCA REMOVER.
|
|
540
|
+
process.stdin.resume();
|
|
541
|
+
|
|
483
542
|
console.log(`✓ LeadMaster no ar em ${url} (dados: ${home})`);
|
|
484
543
|
console.log('');
|
|
485
544
|
console.log(`ℹ Abra ${url} no navegador quando quiser — o LeadMaster nunca abre janelas sozinho.`);
|