terminal-smart-cli 0.42.0 → 0.44.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 (3) hide show
  1. package/bin/ts.js +5 -2
  2. package/lib/meta.js +14 -3
  3. package/package.json +1 -1
package/bin/ts.js CHANGED
@@ -1142,14 +1142,17 @@ function _metaChecklistBox(itens) {
1142
1142
  async function metaCmd() {
1143
1143
  const token = needToken();
1144
1144
  const metaMod = require('../lib/meta');
1145
- const dir = process.cwd();
1145
+ // --dir/--pasta/-C: pasta do projeto (absoluta ou relativa; criada se não existir). Sem ela, usa o cwd.
1146
+ const _dirArg = (() => { const i = rawArgs.findIndex(a => a === '--dir' || a === '--pasta' || a === '-C'); return i >= 0 ? rawArgs[i + 1] : null; })();
1147
+ const dir = _dirArg ? require('path').resolve(_dirArg) : process.cwd();
1148
+ if (_dirArg) { try { require('fs').mkdirSync(dir, { recursive: true }); } catch (_) {} }
1146
1149
 
1147
1150
  // objetivo = args após "meta", pulando flags e seus valores (--budget 300 não entra no texto)
1148
1151
  const mi = rawArgs.findIndex(a => ['meta', 'missao', 'mission'].includes(String(a).toLowerCase()));
1149
1152
  const parts = [];
1150
1153
  for (let i = mi + 1; i < rawArgs.length; i++) {
1151
1154
  const a = rawArgs[i];
1152
- if (a.startsWith('-')) { if (['--budget', '--rodadas', '--rounds', '--modelo', '--model', '--pensador', '--thinker', '--maxmin', '--designer', '--design', '--olho', '--eye', '--mockup', '--arquivo', '--file', '-f', '--budget-total', '--max-janelas', '--max-windows', '--max-horas', '--intervalo'].includes(a)) i++; continue; }
1155
+ if (a.startsWith('-')) { if (['--budget', '--rodadas', '--rounds', '--modelo', '--model', '--pensador', '--thinker', '--maxmin', '--designer', '--design', '--olho', '--eye', '--mockup', '--arquivo', '--file', '-f', '--budget-total', '--max-janelas', '--max-windows', '--max-horas', '--intervalo', '--dir', '--pasta', '-C'].includes(a)) i++; continue; }
1153
1156
  parts.push(a);
1154
1157
  }
1155
1158
  // objetivo pode vir de um ARQUIVO (--arquivo/-f caminho.txt) — evita a dor de passar
package/lib/meta.js CHANGED
@@ -224,14 +224,25 @@ function _pngFramesDiff(frames) {
224
224
  // a página, captura ERROS DE CONSOLE (ex: "Invalid Date") e tira PRINT pro olho criticar o
225
225
  // visual. Se a home for uma TELA DE LOGIN, LOGA com o seed e verifica as telas AUTENTICADAS
226
226
  // (senão dashboard/kanban quebrados passariam batido). Dá pra web a MESMA verificação real que apps têm.
227
+ // escolhe uma porta: usa a preferida se estiver LIVRE, senão pega uma efêmera livre.
228
+ // robustez do gate: se a porta do código está ocupada (órfão/outro processo), NÃO trava —
229
+ // passa a porta escolhida ao servidor via PORT env e é ELA que o gate polla (o app respeita
230
+ // process.env.PORT). Neutraliza também o bug de "log com porta hardcoded".
231
+ function _pickPort(preferred) {
232
+ const net = require('net');
233
+ const testFree = (p) => new Promise(res => { const s = net.createServer(); s.once('error', () => res(false)); s.once('listening', () => s.close(() => res(true))); try { s.listen(p, '127.0.0.1'); } catch (_) { res(false); } });
234
+ const ephemeral = () => new Promise(res => { const s = net.createServer(); s.listen(0, '127.0.0.1', () => { const p = s.address().port; s.close(() => res(p)); }); s.once('error', () => res(preferred)); });
235
+ return testFree(preferred).then(free => free ? preferred : ephemeral());
236
+ }
237
+
227
238
  async function webRunGate(b, opts = {}) {
228
- const cwd = b.cwd, port = b.port || 3000, url = 'http://localhost:' + port + '/';
239
+ const cwd = b.cwd, port = await _pickPort(b.port || 3000), url = 'http://localhost:' + port + '/';
229
240
  // instala deps se faltarem
230
241
  try { if (!fs.existsSync(path.join(cwd, 'node_modules'))) { try { cp.execSync('npm install', { cwd, stdio: 'ignore', timeout: 240000 }); } catch (_) {} } } catch (_) {}
231
242
  // sobe o servidor (shell:true resolve npm.cmd no Windows; detached pra matar a árvore)
232
243
  let srv, srvlog = '';
233
244
  try {
234
- srv = cp.spawn(b.startCmd, { cwd, detached: process.platform !== 'win32', shell: true, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
245
+ srv = cp.spawn(b.startCmd, { cwd, env: { ...process.env, PORT: String(port) }, detached: process.platform !== 'win32', shell: true, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
235
246
  srv.stdout && srv.stdout.on('data', d => { srvlog += d.toString(); });
236
247
  srv.stderr && srv.stderr.on('data', d => { srvlog += d.toString(); });
237
248
  } catch (e) { return { ok: false, crash: 'não consegui iniciar o servidor: ' + e.message }; }
@@ -1143,7 +1154,7 @@ async function run(goal, opts = {}) {
1143
1154
  }
1144
1155
  st.lastBuildSig = sig;
1145
1156
  let fixItem = st.checklist.find(it => it.id === 'build_fix');
1146
- if (!fixItem) { fixItem = { id: 'build_fix', desc: (lang === 'en' ? 'Fix compile errors until the build succeeds and the APK is generated' : 'Corrigir os erros de compilação até o build passar e o APK ser gerado'), passes: false, attempts: 0, isBuild: true }; st.checklist.push(fixItem); }
1157
+ if (!fixItem) { const _webk = !!(b && b.kind === 'web'); fixItem = { id: 'build_fix', desc: (lang === 'en' ? (_webk ? 'Fix errors until the server starts and responds cleanly (web gate)' : 'Fix compile errors until the build succeeds and the APK is generated') : (_webk ? 'Corrigir os erros até o servidor subir e responder limpo (gate web)' : 'Corrigir os erros de compilação até o build passar e o APK ser gerado')), passes: false, attempts: 0, isBuild: true }; st.checklist.push(fixItem); }
1147
1158
  fixItem.passes = false; fixItem.blocked = false;
1148
1159
  save(st, dir);
1149
1160
  onRoundDone({ checklist: st.checklist, spent: st.creditsSpent, buildFailed: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminal-smart-cli",
3
- "version": "0.42.0",
3
+ "version": "0.44.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"