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.
- package/bin/ts.js +58 -3
- package/lib/api.js +2 -2
- 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
|
|
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
|
|
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
|
|
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 });
|