terminal-smart-cli 0.97.5 → 0.97.6

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 +58 -3
  2. package/lib/api.js +2 -2
  3. package/package.json +1 -1
package/bin/ts.js CHANGED
@@ -202,7 +202,7 @@ async function imageCmd(args) {
202
202
  C.bold(en ? 'This action can generate an image' : 'Esta ação pode gerar uma imagem'),
203
203
  C.dim(en ? 'Choose before spending credits. There is no silent paid fallback.' : 'Escolha antes de gastar créditos. Não existe fallback pago silencioso.'),
204
204
  '',
205
- ` ${C.cyan('1')} ${C.bold(premium.label || 'Premium · GPT Image 2')} ${C.dim('~' + (premium.estimatedCredits || '?') + ' créditos')}${premium.allowed === false ? C.warn(en ? ' · requires Pro/Ultra' : ' · requer Pro/Ultra') : ''}`,
205
+ ` ${C.cyan('1')} ${C.bold(premium.label || 'Premium · GPT Image 2')} ${C.dim('~' + (premium.estimatedCredits || '?') + ' créditos')}${premium.allowed === false ? C.warn(en ? ' · requires Basic/Pro' : ' · requer Básico/Pro') : ''}`,
206
206
  ` ${C.cyan('2')} ${C.bold(economy.label || 'Econômica · Gemini')} ${C.dim('~' + (economy.estimatedCredits || '?') + ' créditos')}`,
207
207
  ` ${C.cyan('3')} ${C.bold(en ? 'Continue without images' : 'Continuar sem imagens')} ${C.dim(en ? 'no charge' : 'sem cobrança')}`,
208
208
  '',
@@ -214,7 +214,7 @@ async function imageCmd(args) {
214
214
  const selected = options.find(o => o.id === choice);
215
215
  if (!selected || selected.allowed === false) {
216
216
  throw new ApiError((selected && selected.upgradeRequired)
217
- ? (en ? 'GPT Image 2 requires Pro or Ultra.' : 'GPT Image 2 requer plano Pro ou Ultra.')
217
+ ? (en ? 'GPT Image 2 requires Basic or Pro.' : 'GPT Image 2 requer plano Básico ou Pro.')
218
218
  : (en ? 'Invalid image option.' : 'Opção de imagem inválida.'), { code: 'plan_limit' });
219
219
  }
220
220
  if (choice === 'none') {
@@ -2651,6 +2651,60 @@ function perfilCmd(args) {
2651
2651
  ], { title: 'ts perfil' }));
2652
2652
  }
2653
2653
 
2654
+ // ── ts site — cria e publica sites estáticos em *.tsite1.com ────────────────
2655
+ async function siteCmd(args) {
2656
+ const token = needToken();
2657
+ const sub = String(args[0] || 'listar').toLowerCase();
2658
+ const rest = args.slice(1);
2659
+ try {
2660
+ if (['listar', 'list', 'ls', 'status'].includes(sub)) {
2661
+ const r = await api('/api/sites', { token });
2662
+ if (JSON_OUT) return console.log(JSON.stringify(r));
2663
+ if (!r.sites || !r.sites.length) return console.log(ui.infoLine('Nenhum site criado. Use: ts site criar <nome> "<descrição>"'));
2664
+ console.log('\n' + ui.box(r.sites.map(s =>
2665
+ C.bold(s.slug) + C.dim(' · ') + (s.status === 'active' ? C.ok('online') : C.dim(s.status)) +
2666
+ C.dim(s.preview ? ' · prévia grátis' : '') + '\n ' + C.cyan(s.url)
2667
+ ), { title: `ts site · ${r.plan} · limite ${r.siteLimit || 'demo'}` }) + '\n');
2668
+ return;
2669
+ }
2670
+ if (['criar', 'create', 'gerar', 'generate'].includes(sub)) {
2671
+ const slug = String(rest.shift() || '').trim();
2672
+ const prompt = rest.join(' ').trim();
2673
+ if (!slug || !prompt) return console.log(ui.errLine('uso: ts site criar <nome> "<descreva o site em linguagem natural>"'));
2674
+ console.log(C.dim('criando e publicando o site…'));
2675
+ const r = await api('/api/sites/generate', { token, method: 'POST', body: { slug, prompt }, timeoutMs: 240000 });
2676
+ if (!r.ok) return console.log(ui.errLine(r.error || r.message || 'não foi possível criar o site'));
2677
+ if (JSON_OUT) return console.log(JSON.stringify(r));
2678
+ console.log('\n' + ui.box([
2679
+ C.ok('Site online!'),
2680
+ C.dim('URL: ') + C.bold(r.url),
2681
+ C.dim('modelo: ') + (r.model || 'smart'),
2682
+ C.dim('tokens: ') + `${r.tokens?.input || 0} entrada · ${r.tokens?.output || 0} saída`,
2683
+ C.dim('créditos: ') + String(r.credits || 0),
2684
+ ...(r.preview ? [C.warn('Prévia Free: expira em 24h e é removida em 48h.')] : []),
2685
+ ], { title: 'ts site' }) + '\n');
2686
+ return;
2687
+ }
2688
+ if (['publicar', 'publish', 'deploy'].includes(sub)) {
2689
+ const slug = String(rest[0] || '').trim(), file = String(rest[1] || '').trim();
2690
+ if (!slug || !file) return console.log(ui.errLine('uso: ts site publicar <nome> <arquivo.html>'));
2691
+ const html = require('fs').readFileSync(require('path').resolve(file), 'utf8');
2692
+ const r = await api('/api/sites/publish', { token, method: 'POST', body: { slug, html }, timeoutMs: 120000 });
2693
+ if (!r.ok) return console.log(ui.errLine(r.error || 'não foi possível publicar'));
2694
+ return console.log(ui.okLine('site online: ' + r.url));
2695
+ }
2696
+ if (['apagar', 'delete', 'rm', 'remover'].includes(sub)) {
2697
+ const id = Number(rest[0]);
2698
+ if (!id) return console.log(ui.errLine('uso: ts site apagar <id> (veja em: ts site listar --json)'));
2699
+ const r = await api('/api/sites/' + id, { token, method: 'DELETE' });
2700
+ return console.log(r.ok ? ui.okLine('site removido') : ui.errLine(r.error || 'falha'));
2701
+ }
2702
+ console.log(ui.infoLine('Comandos: ts site listar | criar <nome> "<descrição>" | publicar <nome> <arquivo.html> | apagar <id>'));
2703
+ } catch (e) {
2704
+ console.log(ui.errLine(e.code === 'auth' ? T.need_login : (e.message || 'falha')));
2705
+ }
2706
+ }
2707
+
2654
2708
  // ── ts cloud — caixa de dev na nuvem (Fase 1) ────────────────────────────────
2655
2709
  async function cloudCmd(args) {
2656
2710
  const token = needToken();
@@ -2688,7 +2742,7 @@ async function cloudCmd(args) {
2688
2742
  console.log(C.dim(en ? 'provisioning your cloud box…' : 'provisionando sua caixa na nuvem…'));
2689
2743
  try {
2690
2744
  const r = await call('up', { method: 'POST', body: requestedSlug ? { slug: requestedSlug } : {}, timeoutMs: 120000 });
2691
- if (!r.ok) { console.log(ui.errLine(r.error || 'falha')); if (r.code === 'plan_required') console.log(C.dim(en ? 'Get Ultra at terminalsmart.com.br/planos' : 'Assine o Ultra em terminalsmart.com.br/planos')); return; }
2745
+ if (!r.ok) { console.log(ui.errLine(r.error || 'falha')); if (r.code === 'plan_required') console.log(C.dim(en ? 'Get Pro at terminalsmart.com.br/planos' : 'Assine o Pro em terminalsmart.com.br/planos')); return; }
2692
2746
  if (JSON_OUT) { console.log(JSON.stringify(r)); return; }
2693
2747
  console.log('\n' + ui.box([
2694
2748
  C.ok(en ? 'Cloud box is up!' : 'Caixa na nuvem no ar!'), '',
@@ -2926,6 +2980,7 @@ function recallCmd(args) {
2926
2980
  case 'memoria': case 'memória': case 'memory': return memoriaCmd(POS.slice(1));
2927
2981
  case 'recall': case 'lembrei': case 'sessoes': case 'sessões': return recallCmd(POS.slice(1));
2928
2982
  case 'vps': case 'servidor': return vpsCmd(POS.slice(1));
2983
+ case 'site': case 'sites': case 'pagina': return siteCmd(POS.slice(1));
2929
2984
  case 'cloud': case 'nuvem': return cloudCmd(POS.slice(1));
2930
2985
  case 'diagnosticar': case 'diagnose': case 'investigar': case 'debug': return diagnosticarCmd(POS.slice(1));
2931
2986
  case 'sentinela': case 'sentinel': case 'vigia': case 'monitor': return sentinelaCmd(POS.slice(1));
package/lib/api.js CHANGED
@@ -61,8 +61,8 @@ async function api(path, { method = 'GET', body, token, timeoutMs = 60000, retry
61
61
  let j = null;
62
62
  try { j = await res.json(); } catch (_) {}
63
63
  if (res.status === 401) throw new ApiError((j && j.message) || 'unauthorized', { status: 401, code: 'auth' });
64
- if (res.status === 402) throw new ApiError((j && j.message) || 'no credits', { status: 402, code: (j && j.code) || 'no_credits' });
65
- if (!res.ok) throw new ApiError((j && j.message) || ('HTTP ' + res.status), { status: res.status });
64
+ if (res.status === 402) throw new ApiError((j && (j.message || j.error)) || 'no credits', { status: 402, code: (j && j.code) || 'no_credits' });
65
+ if (!res.ok) throw new ApiError((j && (j.message || j.error)) || ('HTTP ' + res.status), { status: res.status, code: (j && j.code) || '' });
66
66
  return j;
67
67
  };
68
68
  return withRetry(doFetch, { tries, baseMs: 500, onRetry, connOnly: !idempotent });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminal-smart-cli",
3
- "version": "0.97.5",
3
+ "version": "0.97.6",
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"