@danhachuel/leadmaster 0.1.16 → 0.1.18
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 +56 -0
- package/backend/__pycache__/main.cpython-311.pyc +0 -0
- 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/tests/__pycache__/conftest.cpython-311-pytest-8.4.2.pyc +0 -0
- package/backend/tests/__pycache__/test_campaigns_routes.cpython-311-pytest-8.4.2.pyc +0 -0
- package/backend/tests/__pycache__/test_cnpj_extractor.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_metrics.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_launcher_protections.py +13 -0
- package/backend/tests/test_metrics.py +112 -0
- package/frontend/dist/assets/{index-BTNs0Fhp.js → index-DFVTLg-7.js} +4 -4
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
- package/scripts/cli.mjs +66 -5
package/frontend/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
7
|
<title>LeadMaster — Painel</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DFVTLg-7.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-BKo_OphM.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body class="bg-gray-100 min-h-screen">
|
package/package.json
CHANGED
package/scripts/cli.mjs
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import { spawn, spawnSync, execSync } from 'node:child_process';
|
|
26
|
-
import { existsSync, mkdirSync, readFileSync, appendFileSync } from 'node:fs';
|
|
26
|
+
import { existsSync, mkdirSync, readFileSync, appendFileSync, rmSync, cpSync } from 'node:fs';
|
|
27
27
|
import { homedir, platform } from 'node:os';
|
|
28
28
|
import net from 'node:net';
|
|
29
29
|
import path from 'node:path';
|
|
@@ -87,6 +87,41 @@ function ensureHome(home) {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Runtime permanente (regra inviolável do AGENTS.md)
|
|
92
|
+
//
|
|
93
|
+
// O servidor NUNCA executa a partir do cache do npx (`_npx\...`): um processo
|
|
94
|
+
// rodando de lá segura o diretório e o npx falha com EBUSY na próxima
|
|
95
|
+
// instalação — antes mesmo de qualquer código do launcher rodar (por isso o
|
|
96
|
+
// kill switch sozinho não resolvia). Solução: `install` copia backend/ e
|
|
97
|
+
// frontend/dist/ para <home>/.runtime e `start` executa de lá. O cache do npx
|
|
98
|
+
// nunca é tocado por processos nossos.
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
|
|
101
|
+
function runtimeDir(home) {
|
|
102
|
+
return path.join(home, '.runtime');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function runtimePronto(home) {
|
|
106
|
+
return existsSync(path.join(runtimeDir(home), 'backend', 'main.py'));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Copia backend/ e frontend/dist/ do pacote para o runtime permanente. */
|
|
110
|
+
function copiarParaRuntime(home) {
|
|
111
|
+
const runtime = runtimeDir(home);
|
|
112
|
+
rmSync(runtime, { recursive: true, force: true });
|
|
113
|
+
mkdirSync(runtime, { recursive: true });
|
|
114
|
+
cpSync(path.join(PKG_ROOT, 'backend'), path.join(runtime, 'backend'), {
|
|
115
|
+
recursive: true,
|
|
116
|
+
filter: (src) => !src.includes('__pycache__') && !src.endsWith('.pyc') && !src.includes(`${path.sep}.venv`),
|
|
117
|
+
});
|
|
118
|
+
const dist = path.join(PKG_ROOT, 'frontend', 'dist');
|
|
119
|
+
if (existsSync(path.join(dist, 'index.html'))) {
|
|
120
|
+
cpSync(dist, path.join(runtime, 'frontend', 'dist'), { recursive: true });
|
|
121
|
+
}
|
|
122
|
+
return runtime;
|
|
123
|
+
}
|
|
124
|
+
|
|
90
125
|
// ---------------------------------------------------------------------------
|
|
91
126
|
// Python
|
|
92
127
|
// ---------------------------------------------------------------------------
|
|
@@ -471,6 +506,14 @@ async function cmdInstall(args) {
|
|
|
471
506
|
// Frontend (modo repositório): idempotente, só instala o que faltar.
|
|
472
507
|
instalarModoFonte();
|
|
473
508
|
|
|
509
|
+
// Runtime permanente: reutiliza a porta inicial já validada pelo kill switch
|
|
510
|
+
// acima, apaga o .runtime anterior (arquivos liberados) e copia esta versão
|
|
511
|
+
// do pacote para lá. Daqui em diante o servidor NUNCA roda de dentro do
|
|
512
|
+
// cache do npx — o EBUSY acaba.
|
|
513
|
+
await encerrarInstanciaAnterior(portaInicial);
|
|
514
|
+
const runtime = copiarParaRuntime(home);
|
|
515
|
+
console.log(`✓ Runtime permanente preparado: ${runtime}`);
|
|
516
|
+
|
|
474
517
|
console.log('');
|
|
475
518
|
console.log('Instalação concluída. Para usar (comando único):');
|
|
476
519
|
console.log(' npx --yes @danhachuel/leadmaster@latest');
|
|
@@ -524,20 +567,28 @@ function cmdStart(args) {
|
|
|
524
567
|
|
|
525
568
|
// Comando único (estilo Thunderbolt): o start também se auto-prepara.
|
|
526
569
|
// Modo fonte sem deps/build? Instala só o que faltar antes de subir.
|
|
527
|
-
// Pacote npx: UI já vem pronta (dist) e nada disto roda.
|
|
528
570
|
if (existsSync(path.join(PKG_ROOT, 'frontend', 'package.json'))) {
|
|
529
571
|
instalarModoFonte();
|
|
530
|
-
} else if (!existsSync(path.join(PKG_ROOT, 'frontend', 'dist', 'index.html'))) {
|
|
531
|
-
console.warn('⚠ Interface construída não encontrada (frontend/dist).');
|
|
532
572
|
}
|
|
533
573
|
|
|
574
|
+
// Kill switch: se uma instância ANTIGA (runtime anterior) ainda ocupar a
|
|
575
|
+
// porta, ela é encerrada antes da nova assumir — nunca reutilizamos.
|
|
576
|
+
await encerrarInstanciaAnterior(portaInicial);
|
|
577
|
+
|
|
578
|
+
// Runtime permanente (regra inviolável): o servidor NUNCA roda de dentro
|
|
579
|
+
// do cache do npx (EBUSY na próxima instalação). Sem runtime pronto, o
|
|
580
|
+
// start se auto-aprovisiona copiando para <home>/.runtime; com runtime
|
|
581
|
+
// pronto, reutiliza (sem recopiar nada).
|
|
582
|
+
const runtime = runtimePronto(home) ? runtimeDir(home) : copiarParaRuntime(home);
|
|
583
|
+
console.log(`✓ Executando a partir do runtime permanente: ${runtime}`);
|
|
584
|
+
|
|
534
585
|
// Workers nascem em grupo de processos próprio (detached: true =
|
|
535
586
|
// CREATE_NEW_PROCESS_GROUP no Windows): sinais de Ctrl+C do terminal
|
|
536
587
|
// (MobaXterm, VS Code, perda de foco) matam apenas o launcher — o
|
|
537
588
|
// servidor Python continua rodando e só é encerrado pelo kill()
|
|
538
589
|
// controlado abaixo (ou sobrevive para a próxima execução detectar).
|
|
539
590
|
const child = spawn(python.cmd, [...python.args, '-m', 'uvicorn', 'main:app', '--host', '127.0.0.1', '--port', String(porta), '--no-access-log'], {
|
|
540
|
-
cwd: path.join(
|
|
591
|
+
cwd: path.join(runtime, 'backend'),
|
|
541
592
|
env: {
|
|
542
593
|
...process.env,
|
|
543
594
|
LEADMASTER_HOME: home,
|
|
@@ -674,6 +725,7 @@ async function cmdDoctor(args) {
|
|
|
674
725
|
console.log(`Servidor UI ........ ${ativaEm ? `rodando em http://127.0.0.1:${ativaEm}` : `parado (porta inicial ${portaInicial})`}`);
|
|
675
726
|
const hasDist = existsSync(path.join(PKG_ROOT, 'frontend', 'dist', 'index.html'));
|
|
676
727
|
console.log(`Interface (dist) ... ${hasDist ? 'presente' : 'ausente (modo dev ou rebuild necessário)'}`);
|
|
728
|
+
console.log(`Runtime permanente . ${runtimePronto(home) ? `pronto (${runtimeDir(home)})` : 'ausente — rode install'}`);
|
|
677
729
|
console.log('');
|
|
678
730
|
console.log('Diagnóstico concluído.');
|
|
679
731
|
}
|
|
@@ -721,6 +773,15 @@ mkdirSync(LOG_DIR, { recursive: true });
|
|
|
721
773
|
const CONSOLE_LOG = path.join(LOG_DIR, 'launcher_console.log');
|
|
722
774
|
[process.stdout, process.stderr].forEach((stream) => guardConsoleStream(stream, CONSOLE_LOG));
|
|
723
775
|
|
|
776
|
+
// Nunca manter o cwd dentro do cache do npx: o launcher nasce com o cwd de
|
|
777
|
+
// onde o usuário rodou o comando; assim que sabemos o home, saímos de lá —
|
|
778
|
+
// nenhum processo nosso segura diretório do cache (fim do EBUSY no npx).
|
|
779
|
+
try {
|
|
780
|
+
process.chdir(homeLauncher);
|
|
781
|
+
} catch {
|
|
782
|
+
/* melhor esforço */
|
|
783
|
+
}
|
|
784
|
+
|
|
724
785
|
switch (command) {
|
|
725
786
|
case 'install':
|
|
726
787
|
// cmdInstall é async (kill switch): a promise mantém o evento vivo até o
|