terminal-smart-cli 0.97.3 → 0.97.5
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/cloud-slug.js +30 -0
- package/lib/i18n.js +2 -2
- package/package.json +2 -2
package/bin/ts.js
CHANGED
|
@@ -2658,12 +2658,38 @@ async function cloudCmd(args) {
|
|
|
2658
2658
|
const sub = String(args[0] || 'status').toLowerCase();
|
|
2659
2659
|
const rest = args.slice(1).filter(a => !a.startsWith('-'));
|
|
2660
2660
|
const call = (path, opts = {}) => api('/api/cloud/' + path, { token, ...opts });
|
|
2661
|
+
const cloudSlug = require('../lib/cloud-slug');
|
|
2662
|
+
const chooseSlug = async (provided) => {
|
|
2663
|
+
let value = String(provided || '').trim();
|
|
2664
|
+
if (!value && process.stdin.isTTY && !JSON_OUT && !YES) {
|
|
2665
|
+
value = String(await ui.ask(en
|
|
2666
|
+
? ' Choose the public name (<name>.tsbox1.com): '
|
|
2667
|
+
: ' Escolha o endereço público (<nome>.tsbox1.com): ')).trim();
|
|
2668
|
+
}
|
|
2669
|
+
const checked = cloudSlug.validate(value);
|
|
2670
|
+
if (!checked.ok) {
|
|
2671
|
+
if (JSON_OUT) console.log(JSON.stringify(checked));
|
|
2672
|
+
else console.log(ui.errLine(checked.error));
|
|
2673
|
+
return null;
|
|
2674
|
+
}
|
|
2675
|
+
return checked.slug;
|
|
2676
|
+
};
|
|
2661
2677
|
|
|
2662
2678
|
if (sub === 'up' || sub === 'start' || sub === 'ligar') {
|
|
2679
|
+
let requestedSlug = rest[0] || '';
|
|
2680
|
+
const current = await call('status');
|
|
2681
|
+
if (requestedSlug) {
|
|
2682
|
+
requestedSlug = await chooseSlug(requestedSlug);
|
|
2683
|
+
if (!requestedSlug) return;
|
|
2684
|
+
} else if (!current.exists || current.needsSlug) {
|
|
2685
|
+
requestedSlug = await chooseSlug('');
|
|
2686
|
+
if (!requestedSlug) return;
|
|
2687
|
+
}
|
|
2663
2688
|
console.log(C.dim(en ? 'provisioning your cloud box…' : 'provisionando sua caixa na nuvem…'));
|
|
2664
2689
|
try {
|
|
2665
|
-
const r = await call('up', { method: 'POST', body: {}, timeoutMs: 120000 });
|
|
2690
|
+
const r = await call('up', { method: 'POST', body: requestedSlug ? { slug: requestedSlug } : {}, timeoutMs: 120000 });
|
|
2666
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; }
|
|
2692
|
+
if (JSON_OUT) { console.log(JSON.stringify(r)); return; }
|
|
2667
2693
|
console.log('\n' + ui.box([
|
|
2668
2694
|
C.ok(en ? 'Cloud box is up!' : 'Caixa na nuvem no ar!'), '',
|
|
2669
2695
|
C.dim('URL: ') + C.bold(r.url),
|
|
@@ -2677,6 +2703,15 @@ async function cloudCmd(args) {
|
|
|
2677
2703
|
if (sub === 'status' || sub === 'url') {
|
|
2678
2704
|
const r = await call('status');
|
|
2679
2705
|
if (!r.exists) { console.log(ui.infoLine(en ? 'No cloud box yet. Run: ts cloud up' : 'Nenhuma caixa ainda. Rode: ts cloud up')); return; }
|
|
2706
|
+
if (JSON_OUT) { console.log(JSON.stringify(r)); return; }
|
|
2707
|
+
if (r.needsSlug || !r.url) {
|
|
2708
|
+
console.log('\n' + ui.box([
|
|
2709
|
+
C.warn(en ? 'Public name not chosen yet.' : 'Endereço público ainda não escolhido.'),
|
|
2710
|
+
C.dim(en ? 'Choose one: ' : 'Escolha um nome: ') + C.cyan('ts cloud nome <nome>'),
|
|
2711
|
+
C.dim(en ? 'Example: ' : 'Exemplo: ') + C.cyan('ts cloud nome minhaempresa'),
|
|
2712
|
+
], { title: 'ts cloud' }) + '\n');
|
|
2713
|
+
return;
|
|
2714
|
+
}
|
|
2680
2715
|
if (sub === 'url') { console.log(r.url); return; }
|
|
2681
2716
|
const lines = [
|
|
2682
2717
|
C.dim('status: ') + (r.running ? C.ok(en ? 'running' : 'no ar') : C.dim(en ? 'suspended (idle) — wakes on next use' : 'suspensa (ociosa) — acorda no próximo uso')),
|
|
@@ -2688,6 +2723,19 @@ async function cloudCmd(args) {
|
|
|
2688
2723
|
return;
|
|
2689
2724
|
}
|
|
2690
2725
|
|
|
2726
|
+
if (sub === 'nome' || sub === 'name' || sub === 'slug' || sub === 'renomear' || sub === 'rename') {
|
|
2727
|
+
const slug = await chooseSlug(rest[0]);
|
|
2728
|
+
if (!slug) return;
|
|
2729
|
+
const r = await call('slug', { method: 'POST', body: { slug } });
|
|
2730
|
+
if (JSON_OUT) { console.log(JSON.stringify(r)); return; }
|
|
2731
|
+
if (!r.ok) { console.log(ui.errLine(r.error || 'falha')); return; }
|
|
2732
|
+
console.log('\n' + ui.box([
|
|
2733
|
+
C.ok(en ? 'Public address saved!' : 'Endereço público salvo!'),
|
|
2734
|
+
C.dim('URL: ') + C.bold(r.url),
|
|
2735
|
+
], { title: 'ts cloud' }) + '\n');
|
|
2736
|
+
return;
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2691
2739
|
if (sub === 'exec' || sub === 'sh' || sub === 'run') {
|
|
2692
2740
|
const cmd = rest.join(' ').trim();
|
|
2693
2741
|
if (!cmd) { console.log(ui.errLine(en ? 'usage: ts cloud exec "<command>"' : 'uso: ts cloud exec "<comando>"')); return; }
|
|
@@ -2708,7 +2756,13 @@ async function cloudCmd(args) {
|
|
|
2708
2756
|
const goal = rest.join(' ').trim();
|
|
2709
2757
|
if (!goal) { console.log(ui.errLine(en ? 'usage: ts cloud meta "<goal>"' : 'uso: ts cloud meta "<objetivo>"')); return; }
|
|
2710
2758
|
let st = await call('status');
|
|
2711
|
-
if (!st.exists
|
|
2759
|
+
if (!st.exists || st.needsSlug) {
|
|
2760
|
+
const slug = await chooseSlug('');
|
|
2761
|
+
if (!slug) return;
|
|
2762
|
+
console.log(C.dim(en ? 'creating box…' : 'criando caixa…'));
|
|
2763
|
+
const up = await call('up', { method: 'POST', body: { slug }, timeoutMs: 120000 });
|
|
2764
|
+
if (!up.ok) { console.log(ui.errLine(up.error || 'falha')); if (up.code === 'plan_required') console.log(C.dim('terminalsmart.com.br/planos')); return; }
|
|
2765
|
+
}
|
|
2712
2766
|
console.log(C.dim(en ? 'running ts meta inside the cloud box (may take a while)…' : 'rodando ts meta dentro da caixa (pode demorar)…'));
|
|
2713
2767
|
const safe = goal.replace(/(["\\$`])/g, '\\$1');
|
|
2714
2768
|
const cmdMeta = 'cd /workspace && ts meta "' + safe + '" --yes 2>&1';
|
|
@@ -2742,7 +2796,8 @@ async function cloudCmd(args) {
|
|
|
2742
2796
|
|
|
2743
2797
|
console.log('\n' + ui.box([
|
|
2744
2798
|
C.bold('ts cloud') + C.dim(en ? ' — your dev box in the cloud' : ' — sua caixa de dev na nuvem'), '',
|
|
2745
|
-
C.dim('up') + '
|
|
2799
|
+
C.dim('up [nome]') + ' ' + (en ? 'create/start your box with a chosen URL' : 'cria/liga sua caixa com endereço escolhido'),
|
|
2800
|
+
C.dim('nome <nome>') + ' ' + (en ? 'choose or change <name>.tsbox1.com' : 'escolhe ou altera <nome>.tsbox1.com'),
|
|
2746
2801
|
C.dim('meta "…"') + ' ' + (en ? 'the agent builds your app in the cloud' : 'o agente constrói seu app na nuvem'),
|
|
2747
2802
|
C.dim('exec "…"') + ' ' + (en ? 'run a shell command in the box' : 'roda um comando na caixa'),
|
|
2748
2803
|
C.dim('url') + ' ' + (en ? 'print the public URL' : 'mostra a URL pública'),
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RESERVED = new Set([
|
|
4
|
+
'www', 'api', 'app', 'admin', 'mail', 'email', 'ftp', 'smtp', 'imap',
|
|
5
|
+
'pop', 'ns1', 'ns2', 'cdn', 'assets', 'static', 'status', 'suporte',
|
|
6
|
+
'support', 'help', 'billing', 'checkout', 'teste', 'test', 'terminalsmart',
|
|
7
|
+
'terminal-smart', 'cloudflare', 'cloud', 'box', 'site', 'ts',
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
function normalize(value) {
|
|
11
|
+
return String(value || '')
|
|
12
|
+
.normalize('NFD')
|
|
13
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.trim()
|
|
16
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
17
|
+
.replace(/^-+|-+$/g, '')
|
|
18
|
+
.replace(/-+/g, '-');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function validate(value) {
|
|
22
|
+
const slug = normalize(value);
|
|
23
|
+
if (!slug || slug.length < 3 || slug.length > 40) return { ok: false, code: 'invalid_slug', error: 'O nome deve ter entre 3 e 40 caracteres.' };
|
|
24
|
+
if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(slug)) return { ok: false, code: 'invalid_slug', error: 'Use letras, números e hífens.' };
|
|
25
|
+
if (RESERVED.has(slug)) return { ok: false, code: 'reserved_slug', error: 'Esse nome é reservado pelo Terminal Smart.' };
|
|
26
|
+
return { ok: true, slug };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = { RESERVED, normalize, validate };
|
|
30
|
+
|
package/lib/i18n.js
CHANGED
|
@@ -151,7 +151,7 @@ const STR = {
|
|
|
151
151
|
lang_invalid: 'Idioma não suportado. Use: ts idioma pt ou ts idioma en',
|
|
152
152
|
err_conn: 'Não consegui falar com o servidor. Verifique sua internet e tente de novo.',
|
|
153
153
|
err_generic: 'Algo deu errado',
|
|
154
|
-
no_credits: '
|
|
154
|
+
no_credits: 'Seu limite de IA acabou. O Free renova diariamente; planos pagos renovam por ciclo. Continue agora em terminalsmart.com.br/planos',
|
|
155
155
|
ask_empty: 'Diga o que você precisa. Ex.: ts "como liberar a porta 443 no ufw?"',
|
|
156
156
|
chat_hint: 'digite sua mensagem · "sair" encerra · "/nova" zera o contexto',
|
|
157
157
|
chat_prompt: 'Você › ',
|
|
@@ -315,7 +315,7 @@ const STR = {
|
|
|
315
315
|
lang_invalid: 'Unsupported language. Use: ts idioma pt or ts idioma en',
|
|
316
316
|
err_conn: 'Could not reach the server. Check your connection and retry.',
|
|
317
317
|
err_generic: 'Something went wrong',
|
|
318
|
-
no_credits: '
|
|
318
|
+
no_credits: 'Your AI limit is over. Free renews daily; paid plans renew each cycle. Continue now at terminalsmart.com.br/planos',
|
|
319
319
|
ask_empty: 'Tell me what you need. E.g.: ts "how do I open port 443 on ufw?"',
|
|
320
320
|
chat_hint: 'type your message · "exit" quits · "/new" resets context',
|
|
321
321
|
chat_prompt: 'You › ',
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminal-smart-cli",
|
|
3
|
-
"version": "0.97.
|
|
3
|
+
"version": "0.97.5",
|
|
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"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
-
"test": "node test/core.test.js && node test/intelligence-core.test.js && node test/eval-model.test.js && node test/project-cache.test.js && node test/memory-bus.test.js && node test/capabilities.test.js && node test/mcp-e2e.test.js && node test/erros.test.js && node test/capability-pack.test.js && node test/byok.test.js && node test/conhecimento.test.js && node test/policy.test.js && node test/temas.test.js && node test/skill-index.test.js"
|
|
9
|
+
"test": "node test/core.test.js && node test/intelligence-core.test.js && node test/cloud-slug.test.js && node test/eval-model.test.js && node test/project-cache.test.js && node test/memory-bus.test.js && node test/capabilities.test.js && node test/mcp-e2e.test.js && node test/erros.test.js && node test/capability-pack.test.js && node test/byok.test.js && node test/conhecimento.test.js && node test/policy.test.js && node test/temas.test.js && node test/skill-index.test.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"bin",
|