terminal-smart-cli 0.91.0 → 0.92.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.
package/lib/agent.js CHANGED
@@ -71,6 +71,8 @@ REGRAS:
71
71
  - NÃO DESISTA sem TENTAR: é PROIBIDO responder "não tenho acesso" / "não consigo" / "preciso que você me passe X" enquanto houver uma ferramenta que você ainda não usou pra tentar. Antes de declarar que algo é impossível, AJA: conecte (conectar_vps), procure (buscar_arquivos, ou grep/find via executar_comando/executar_remoto), leia (ler_arquivo). Ex.: pediram pra ler um código-fonte que "você não tem"? Se há uma VPS/pasta onde ele pode estar, CONECTE e procure (grep -rn "<símbolo>" <dir>) ANTES de dizer que não tem. Só afirme que não conseguiu DEPOIS de ter tentado de fato e mostre o erro/saída REAL que te barrou.
72
72
  - NUNCA pergunte "onde está o arquivo X?" / "há um diretório com Y?" / "posso gerar Z?" sem ANTES ter PROCURADO de fato: rode find/buscar_arquivos por ele em TODOS os lugares plausíveis — na VPS conectada (find / -name "arquivo" 2>/dev/null, e nas pastas do projeto) E na máquina local do usuário (buscar_arquivos, incluindo o pack/instalação de origem que ele citou). Se um config/arquivo obrigatório faltar mesmo depois de procurar, tente ACHAR um exemplo/modelo (outro .conf parecido, o default no código-fonte) e GERAR a partir dele — só peça ajuda ao usuário como ÚLTIMO recurso, dizendo exatamente onde já procurou e não achou.
73
73
  - BINÁRIO NATIVO: ao subir/instalar um executável numa máquina, valide com file (arquitetura: 32 vs 64-bit) E ldd (as bibliotecas resolvem?) ANTES de declarar "pronto/instalado" — "está no lugar" NÃO é "roda". Se ldd mostrar "not found", instale a lib faltante e revalide.
74
+ - WINDOWS / SHELL BASH: o shell aqui é o bash do Git, NÃO o cmd. (a) "node -e"/"python -c" com várias linhas ou com import() FALHA — escreva um arquivo .mjs/.py e rode "node arquivo.mjs"/"python arquivo.py". (b) pra ESPERAR use "sleep N" (NUNCA "timeout /t", que é do cmd e quebra no bash). (c) comandos que só existem no cmd (dir, type, if exist) rode via "cmd /c \"...\"". (d) pra matar um servidor/processo de teste, ache o PID pela PORTA ("netstat -ano | findstr :PORTA" → "taskkill /PID <pid> /F") — NUNCA por imagem ("taskkill /IM node.exe" mata processos não relacionados, inclusive os do usuário).
75
+ - PROVE O CAMINHO REAL antes de declarar "pronto/corrigido": "testes de API passando" NÃO é "o app funciona". Se há UI ou rotas condicionais (por papel/role, por filtro), rode o FLUXO EXATO do usuário afetado — a tela/rota que quebrava — e veja o resultado; numa entrega WEB, verifique com olhos (navegador). Em fix de código com ramos (SQL com subqueries/parâmetros, condicional por role): conte placeholder-a-placeholder e rode de novo o caminho que falhava. Só diga "corrigido" COM a prova verde do caminho real — e NÃO peça pro usuário rodar a prova que você mesmo consegue rodar. Se subir um server de teste, ENCERRE-o (por PID) ao terminar — não deixe processo órfão na porta.
74
76
  - ESTILO DA RESPOSTA (importante): escreva em linguagem NATURAL e direta, como explicando pra uma pessoa — evite jargão e detalhe técnico interno que não interessa a quem só quer o resultado. NÃO use emojis decorativos (nada de 🎮📡🔬🌿✅❌ etc.); pra marcar certo/errado use SÓ os símbolos ✓ (deu certo) ou ✗ (falhou). Frases curtas; comando/código/caminho sempre em bloco de código. Não repita o que já apareceu nos passos acima.
75
77
  - Termine SEMPRE com um resumo curto: o que foi feito, resultado e caminhos de arquivos criados/alterados.
76
78
  - Responda no idioma do usuário (padrão: português do Brasil).`
@@ -97,6 +99,8 @@ RULES:
97
99
  - DON'T GIVE UP without TRYING: it is FORBIDDEN to answer "I don't have access" / "I can't" / "I need you to give me X" while there's a tool you haven't used yet to try. Before declaring something impossible, ACT: connect (conectar_vps), search (buscar_arquivos, or grep/find via executar_comando/executar_remoto), read (ler_arquivo). E.g. asked to read source code you "don't have"? If there's a VPS/folder where it might live, CONNECT and search (grep -rn "<symbol>" <dir>) BEFORE saying you don't have it. Only claim you couldn't do it AFTER actually trying, and show the REAL error/output that blocked you.
98
100
  - NEVER ask "where is file X?" / "is there a folder with Y?" / "may I generate Z?" without having actually SEARCHED first: run find/buscar_arquivos for it in EVERY plausible place — on the connected VPS (find / -name "file" 2>/dev/null, and the project folders) AND on the user's local machine (buscar_arquivos, including the source pack/install they mentioned). If a required config/file is still missing after searching, try to FIND a template/example (a similar .conf, the default in the source) and GENERATE from it — only ask the user as a LAST resort, stating exactly where you already looked and didn't find it.
99
101
  - NATIVE BINARY: when uploading/installing an executable on a machine, validate with file (architecture: 32 vs 64-bit) AND ldd (do the libraries resolve?) BEFORE declaring "done/installed" — "it's in place" is NOT "it runs". If ldd shows "not found", install the missing lib and re-validate.
102
+ - WINDOWS / BASH SHELL: the shell here is Git bash, NOT cmd. (a) "node -e"/"python -c" with multiple lines or with import() FAILS — write a .mjs/.py file and run "node file.mjs"/"python file.py". (b) to WAIT use "sleep N" (NEVER "timeout /t", which is cmd and breaks in bash). (c) cmd-only commands (dir, type, if exist) run via "cmd /c \"...\"". (d) to kill a test server/process, find the PID by PORT ("netstat -ano | findstr :PORT" → "taskkill /PID <pid> /F") — NEVER by image ("taskkill /IM node.exe" kills unrelated processes, including the user's).
103
+ - PROVE THE REAL PATH before declaring "done/fixed": "API tests passing" is NOT "the app works". If there's UI or conditional routes (by role, by filter), run the EXACT flow of the affected user — the screen/route that was breaking — and see the result; on a WEB deliverable, verify with eyes (browser). In a code fix with branches (SQL with subqueries/params, role conditionals): count placeholder-by-placeholder and re-run the path that was failing. Only say "fixed" WITH green proof of the real path — and do NOT ask the user to run a proof you can run yourself. If you start a test server, SHUT IT DOWN (by PID) when done — don't leave an orphan process on the port.
100
104
  - RESPONSE STYLE (important): write in NATURAL, plain language, like explaining to a person — avoid jargon and internal technical detail that doesn't matter to someone who just wants the result. NO decorative emojis (no 🎮📡🔬✅❌ etc.); to mark pass/fail use ONLY the symbols ✓ (worked) or ✗ (failed). Short sentences; commands/code/paths always in a code block. Don't repeat what already showed up in the steps above.
101
105
  - ALWAYS end with a short summary: what was done, the result, and paths of created/changed files.
102
106
  - Answer in the user's language.`);
package/lib/ssh.js CHANGED
@@ -88,10 +88,22 @@ function connect(opts = {}) {
88
88
  function exec(cmd, { timeoutMs = 120000 } = {}) {
89
89
  return new Promise((resolve, reject) => {
90
90
  if (!_conn) return reject(new Error('Não conectado. Rode "ts vps" ou conectar_vps primeiro.'));
91
- _conn.exec(cmd, (err, stream) => {
92
- if (err) return reject(err);
93
- let stdout = '', stderr = '', done = false;
94
- const to = setTimeout(() => { if (!done) { done = true; try { stream.close(); } catch (_) {} resolve({ code: 124, stdout, stderr: stderr + '\n[timeout]' }); } }, timeoutMs);
91
+ let stdout = '', stderr = '', done = false, stream = null;
92
+ // Timeout GLOBAL da chamada — armado ANTES do exec, então dispara MESMO se _conn.exec
93
+ // nunca chamar o callback. Numa conexão meia-morta (TCP vivo, sshd travado) o exec ficava
94
+ // pendurado pra SEMPRE (bug do hang de 40min). Ao estourar, derruba a conexão pra a PRÓXIMA
95
+ // chamada reconectar do zero (via _lastGood) em vez de pendurar de novo.
96
+ const to = setTimeout(() => {
97
+ if (done) return; done = true;
98
+ try { if (stream) stream.close(); } catch (_) {}
99
+ try { if (_conn) _conn.end(); } catch (_) {}
100
+ _conn = null; _info = null;
101
+ resolve({ code: 124, stdout, stderr: (stderr || '') + '\n[timeout: sem resposta em ' + Math.round(timeoutMs / 1000) + 's — a conexão pode ter travado; reconecte e tente de novo, e rode tarefas longas em background com setsid]' });
102
+ }, timeoutMs);
103
+ _conn.exec(cmd, (err, s) => {
104
+ if (done) { try { s && s.close(); } catch (_) {} return; }
105
+ if (err) { done = true; clearTimeout(to); return reject(err); }
106
+ stream = s;
95
107
  stream.on('close', (code) => { if (done) return; done = true; clearTimeout(to); resolve({ code: code == null ? 0 : code, stdout, stderr }); });
96
108
  stream.on('data', (d) => { stdout += d.toString(); if (stdout.length > 200000) stdout = stdout.slice(-120000); });
97
109
  stream.stderr.on('data', (d) => { stderr += d.toString(); if (stderr.length > 60000) stderr = stderr.slice(-40000); });
package/lib/tools.js CHANGED
@@ -381,7 +381,14 @@ async function execute(name, input, opts = {}) {
381
381
  }
382
382
  case 'executar_remoto': {
383
383
  const ssh = require('./ssh');
384
- if (!ssh.isConnected()) return { erro: 'Não conectado a nenhum servidor. Chame conectar_vps primeiro.' };
384
+ // Conexão caiu (ou um exec anterior estourou o timeout e a derrubou)? Reconecta 1x
385
+ // SOZINHO com a última que funcionou (_lastGood: mesmo host/user/chave) — sem pedir
386
+ // nada ao usuário. Assim um SSH que travou não pendura a missão: o timeout do exec
387
+ // devolve o controle, e a próxima chamada se reconecta e segue.
388
+ if (!ssh.isConnected()) {
389
+ if (ssh.lastGood()) { try { await ssh.connect(); } catch (_) {} }
390
+ if (!ssh.isConnected()) return { erro: 'Não conectado a nenhum servidor. Chame conectar_vps primeiro.' };
391
+ }
385
392
  const comando = String(input.comando || '');
386
393
  const out = await ssh.exec(comando, { timeoutMs: 180000 });
387
394
  const c = compactor.compact(comando, out.stdout || '', { codigo: out.code });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminal-smart-cli",
3
- "version": "0.91.0",
3
+ "version": "0.92.0",
4
4
  "description": "Terminal Smart no seu terminal — pergunte, analise logs por pipe e orquestre agentes de IA. Comando: ts",
5
5
  "bin": {
6
6
  "ts": "bin/ts.js"