aifeast 1.0.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/README.md +107 -0
- package/index.js +289 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# 🍽️ AI Feast Engine CLI
|
|
2
|
+
|
|
3
|
+
Interface de linha de comando oficial para interagir com o AI Feast Engine — descubra, configure e execute skills de IA diretamente do terminal.
|
|
4
|
+
|
|
5
|
+
## Instalação
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Via npx (sem instalação)
|
|
9
|
+
npx aifeast list
|
|
10
|
+
|
|
11
|
+
# Ou instalar globalmente
|
|
12
|
+
npm install -g aifeast
|
|
13
|
+
aifeast --help
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Requisitos
|
|
17
|
+
|
|
18
|
+
- Node.js 14+
|
|
19
|
+
- API Key do AI Feast Engine (obtida no dashboard)
|
|
20
|
+
|
|
21
|
+
## Configuração Inicial
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Salvar sua API Key
|
|
25
|
+
aifeast config --key af_xxxxxxxxxxxxx
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
A chave é salva em `~/.aifeast/config.json` e reutilizada automaticamente.
|
|
29
|
+
|
|
30
|
+
## Comandos
|
|
31
|
+
|
|
32
|
+
### `list` — Listar Skills
|
|
33
|
+
|
|
34
|
+
Lista todas as skills disponíveis no catálogo.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
aifeast list
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### `info <slug>` — Detalhes da Skill
|
|
41
|
+
|
|
42
|
+
Mostra informações detalhadas de uma skill específica.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
aifeast info summarize-article
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### `run <slug> --input "texto"` — Executar Skill
|
|
49
|
+
|
|
50
|
+
Executa uma skill com o input fornecido.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
aifeast run summarize-article --input "https://example.com/artigo"
|
|
54
|
+
aifeast run translate-text --input "Hello world" --lang pt
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### `config --key <valor>` — Configurar API Key
|
|
58
|
+
|
|
59
|
+
Salva sua API Key para uso em comandos autenticados.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
aifeast config --key af_xxxxxxxxxxxxx
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### `help` — Ajuda
|
|
66
|
+
|
|
67
|
+
Mostra a lista de comandos disponíveis.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
aifeast help
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Estrutura de Configuração
|
|
74
|
+
|
|
75
|
+
O arquivo de configuração é armazenado em `~/.aifeast/config.json`:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"apiKey": "af_xxxxxxxxxxxxx"
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## API Base
|
|
84
|
+
|
|
85
|
+
`https://api.aifeastengine.com`
|
|
86
|
+
|
|
87
|
+
## Troubleshooting
|
|
88
|
+
|
|
89
|
+
### "API Key não configurada"
|
|
90
|
+
Execute `aifeast config --key SUA_API_KEY` para salvar sua chave. A key é obtida no [Dashboard](https://www.aifeastengine.com).
|
|
91
|
+
|
|
92
|
+
### "Comando desconhecido"
|
|
93
|
+
Execute `aifeast help` para ver a lista de comandos válidos.
|
|
94
|
+
|
|
95
|
+
### Timeout ao listar skills
|
|
96
|
+
A API pode estar temporariamente indisponível. Verifique o status em [aifeastengine.com](https://www.aifeastengine.com) e tente novamente.
|
|
97
|
+
|
|
98
|
+
### Erro 402 — Limite atingido
|
|
99
|
+
Seu plano free atingiu o limite mensal de 100 requests. Faça upgrade para Pro ou aguarde o próximo ciclo.
|
|
100
|
+
|
|
101
|
+
## Licença
|
|
102
|
+
|
|
103
|
+
MIT
|
|
104
|
+
|
|
105
|
+
## Repositório
|
|
106
|
+
|
|
107
|
+
https://github.com/ademilsonls81-oss/AI-Feast-Engine
|
package/index.js
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const axios = require('axios');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
|
|
8
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
|
9
|
+
const API_BASE = 'https://api.aifeastengine.com';
|
|
10
|
+
const CONFIG_DIR = path.join(os.homedir(), '.aifeast');
|
|
11
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
12
|
+
|
|
13
|
+
// Cores para terminal
|
|
14
|
+
const colors = {
|
|
15
|
+
reset: '\x1b[0m',
|
|
16
|
+
bold: '\x1b[1m',
|
|
17
|
+
cyan: '\x1b[36m',
|
|
18
|
+
green: '\x1b[32m',
|
|
19
|
+
yellow: '\x1b[33m',
|
|
20
|
+
red: '\x1b[31m',
|
|
21
|
+
gray: '\x1b[90m',
|
|
22
|
+
purple: '\x1b[35m'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function log(msg, color = 'reset') {
|
|
26
|
+
console.log(`${colors[color]}${msg}${colors.reset}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getConfig() {
|
|
30
|
+
try {
|
|
31
|
+
const raw = fs.readFileSync(CONFIG_FILE, 'utf8');
|
|
32
|
+
return JSON.parse(raw);
|
|
33
|
+
} catch {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function saveConfig(config) {
|
|
39
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
40
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
43
|
+
// Proteger arquivo: apenas dono pode ler/escrever (0600)
|
|
44
|
+
try { fs.chmodSync(CONFIG_FILE, 0o600); } catch {}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function parseArgs(argv) {
|
|
48
|
+
const args = argv.slice(2);
|
|
49
|
+
const cmd = args[0];
|
|
50
|
+
const flags = {};
|
|
51
|
+
let positional = [];
|
|
52
|
+
|
|
53
|
+
for (let i = 1; i < args.length; i++) {
|
|
54
|
+
if (args[i].startsWith('--')) {
|
|
55
|
+
const key = args[i].replace('--', '');
|
|
56
|
+
const val = args[i + 1] && !args[i + 1].startsWith('--') ? args[++i] : true;
|
|
57
|
+
flags[key] = val;
|
|
58
|
+
} else {
|
|
59
|
+
positional.push(args[i]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const slug = positional[0] || null;
|
|
64
|
+
return { cmd, slug, flags, args, positional };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ============================================
|
|
68
|
+
// COMANDOS
|
|
69
|
+
// ============================================
|
|
70
|
+
|
|
71
|
+
async function cmdList() {
|
|
72
|
+
log('\n🔍 Buscando skills disponíveis...\n', 'cyan');
|
|
73
|
+
try {
|
|
74
|
+
const res = await axios.get(`${API_BASE}/api/skills`);
|
|
75
|
+
const { skills, total } = res.data;
|
|
76
|
+
|
|
77
|
+
if (!skills || skills.length === 0) {
|
|
78
|
+
log('Nenhuma skill disponível no momento.', 'yellow');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
log(`📦 Skills disponíveis (${total}):\n`, 'bold');
|
|
83
|
+
|
|
84
|
+
skills.forEach((skill, i) => {
|
|
85
|
+
const riskColor = skill.risk_level === 'low' ? 'green' : skill.risk_level === 'medium' ? 'yellow' : 'red';
|
|
86
|
+
log(` ${i + 1}. ${colors.bold}${skill.name}${colors.reset}`, 'cyan');
|
|
87
|
+
log(` Slug: ${colors.cyan}${skill.slug}${colors.reset}`);
|
|
88
|
+
log(` ${skill.description || 'Sem descrição'}`, 'gray');
|
|
89
|
+
log(` Categoria: ${skill.category} | Risco: ${colors[riskColor]}${skill.risk_level}${colors.reset}`, 'gray');
|
|
90
|
+
log(` Instalar: ${colors.green}npx aifeast info ${skill.slug}${colors.reset}`, 'gray');
|
|
91
|
+
log('');
|
|
92
|
+
});
|
|
93
|
+
} catch (err) {
|
|
94
|
+
log(`❌ Erro ao buscar skills: ${err.message}`, 'red');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function cmdInfo(slug) {
|
|
100
|
+
if (!slug) {
|
|
101
|
+
log('❌ Uso: npx aifeast info <skill-slug>', 'red');
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
log(`\n🔍 Buscando informações da skill: ${colors.bold}${slug}\n`, 'cyan');
|
|
106
|
+
try {
|
|
107
|
+
const res = await axios.get(`${API_BASE}/api/skills/${slug}`);
|
|
108
|
+
const skill = res.data;
|
|
109
|
+
|
|
110
|
+
log(` ${colors.bold}${colors.cyan}Nome:${colors.reset} ${skill.name}`, 'reset');
|
|
111
|
+
log(` ${colors.bold}Slug:${colors.reset} ${skill.slug}`);
|
|
112
|
+
log(` ${colors.bold}Descrição:${colors.reset} ${skill.description}`, 'gray');
|
|
113
|
+
log(` ${colors.bold}Detalhes:${colors.reset} ${skill.long_description}`, 'gray');
|
|
114
|
+
log(` ${colors.bold}Categoria:${colors.reset} ${skill.category}`);
|
|
115
|
+
log(` ${colors.bold}Tags:${colors.reset} ${(skill.tags || []).join(', ')}`);
|
|
116
|
+
log(` ${colors.bold}Risco:${colors.reset} ${skill.risk_level}`);
|
|
117
|
+
log(` ${colors.bold}Downloads:${colors.reset} ${skill.downloads || 0}`);
|
|
118
|
+
log(` ${colors.bold}Instalar:${colors.reset} ${colors.green}npx aifeast ${skill.install_command}${colors.reset}`);
|
|
119
|
+
log(` ${colors.bold}Executar:${colors.reset} ${colors.green}npx aifeast run ${skill.slug} --input "seu texto"${colors.reset}`);
|
|
120
|
+
log('');
|
|
121
|
+
} catch (err) {
|
|
122
|
+
if (err.response && err.response.status === 404) {
|
|
123
|
+
log(`❌ Skill "${slug}" não encontrada.`, 'red');
|
|
124
|
+
} else {
|
|
125
|
+
log(`❌ Erro: ${err.message}`, 'red');
|
|
126
|
+
}
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function cmdRun(slug, flags) {
|
|
132
|
+
if (!slug) {
|
|
133
|
+
log('❌ Uso: npx aifeast run <skill-slug> --input "texto aqui"', 'red');
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const config = getConfig();
|
|
138
|
+
if (!config.apiKey) {
|
|
139
|
+
log('❌ API Key não configurada.', 'red');
|
|
140
|
+
log(' Execute: npx aifeast config --key SUA_API_KEY', 'yellow');
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const input = flags.input || flags.i || flags.data;
|
|
145
|
+
if (!input) {
|
|
146
|
+
log('❌ Input não fornecido.', 'red');
|
|
147
|
+
log(' Uso: npx aifeast run ' + slug + ' --input "seu texto aqui"', 'yellow');
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
log(`\n🚀 Executando skill: ${colors.bold}${slug}\n`, 'cyan');
|
|
152
|
+
try {
|
|
153
|
+
const res = await axios.post(
|
|
154
|
+
`${API_BASE}/api/skills/${slug}/execute`,
|
|
155
|
+
{ input },
|
|
156
|
+
{
|
|
157
|
+
headers: {
|
|
158
|
+
'X-API-Key': config.apiKey,
|
|
159
|
+
'Content-Type': 'application/json'
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const result = res.data;
|
|
165
|
+
|
|
166
|
+
if (result.status === 'executed' || result.skill_id) {
|
|
167
|
+
log(` ${colors.bold}${colors.green}✅ Skill executada com sucesso!${colors.reset}`, 'green');
|
|
168
|
+
log(` ${colors.bold}Skill:${colors.reset} ${result.skill_name || slug}`);
|
|
169
|
+
log(` ${colors.bold}Nível de risco:${colors.reset} ${result.risk_level || 'N/A'}`);
|
|
170
|
+
log(` ${colors.bold}Requests restantes:${colors.reset} ${result.usage_remaining || 'N/A'}`);
|
|
171
|
+
log('');
|
|
172
|
+
|
|
173
|
+
if (result.message) {
|
|
174
|
+
log(` ${colors.bold}Mensagem:${colors.reset} ${result.message}`, 'gray');
|
|
175
|
+
}
|
|
176
|
+
if (result.input_received) {
|
|
177
|
+
log(` ${colors.bold}Input recebido:${colors.reset} ${result.input_received}`, 'gray');
|
|
178
|
+
}
|
|
179
|
+
log('');
|
|
180
|
+
} else {
|
|
181
|
+
log(` ${colors.yellow}Resposta:${colors.reset}`, 'yellow');
|
|
182
|
+
log(JSON.stringify(result, null, 2));
|
|
183
|
+
}
|
|
184
|
+
} catch (err) {
|
|
185
|
+
if (err.response) {
|
|
186
|
+
const status = err.response.status;
|
|
187
|
+
const data = err.response.data;
|
|
188
|
+
|
|
189
|
+
if (status === 401) {
|
|
190
|
+
log('❌ API Key inválida ou ausente.', 'red');
|
|
191
|
+
} else if (status === 402) {
|
|
192
|
+
log('❌ Limite mensal de requests atingido!', 'red');
|
|
193
|
+
log(` Plano: ${data.plan} | Uso: ${data.usage_count}/${data.limit}`, 'yellow');
|
|
194
|
+
log(' Faça upgrade para Pro ou aguarde o próximo mês.', 'yellow');
|
|
195
|
+
} else if (status === 404) {
|
|
196
|
+
log(`❌ Skill "${slug}" não encontrada.`, 'red');
|
|
197
|
+
} else {
|
|
198
|
+
log(`❌ Erro (${status}): ${data.error || err.message}`, 'red');
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
log(`❌ Erro: ${err.message}`, 'red');
|
|
202
|
+
}
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function cmdConfig(flags) {
|
|
208
|
+
const key = flags.key || flags.k;
|
|
209
|
+
if (!key) {
|
|
210
|
+
log('❌ Uso: npx aifeast config --key SUA_API_KEY', 'red');
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const config = getConfig();
|
|
215
|
+
config.apiKey = key;
|
|
216
|
+
saveConfig(config);
|
|
217
|
+
|
|
218
|
+
log(`\n✅ API Key salva com sucesso em: ${CONFIG_FILE}`, 'green');
|
|
219
|
+
log(` Chave: ${key.substring(0, 8)}...${key.substring(key.length - 4)}`, 'gray');
|
|
220
|
+
log('');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ============================================
|
|
224
|
+
// HELP
|
|
225
|
+
// ============================================
|
|
226
|
+
|
|
227
|
+
function showHelp() {
|
|
228
|
+
log(`\n${colors.bold}🍽️ AI Feast Engine CLI${colors.reset}\n`);
|
|
229
|
+
log('Comandos disponíveis:\n', 'bold');
|
|
230
|
+
log(' list Lista todas as skills disponíveis', 'cyan');
|
|
231
|
+
log(' info <skill-slug> Mostra detalhes de uma skill', 'cyan');
|
|
232
|
+
log(' run <skill-slug> --input "" Executa uma skill com input', 'cyan');
|
|
233
|
+
log(' config --key API_KEY Configura sua API Key', 'cyan');
|
|
234
|
+
log(' help Mostra esta ajuda', 'cyan');
|
|
235
|
+
log('\nExemplos:\n', 'bold');
|
|
236
|
+
log(' npx aifeast list', 'gray');
|
|
237
|
+
log(' npx aifeast info summarize-article', 'gray');
|
|
238
|
+
log(' npx aifeast run summarize-article --input "https://example.com/artigo"', 'gray');
|
|
239
|
+
log(' npx aifeast config --key af_xxxxxxxxxxxxx', 'gray');
|
|
240
|
+
log('');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ============================================
|
|
244
|
+
// MAIN
|
|
245
|
+
// ============================================
|
|
246
|
+
|
|
247
|
+
async function main() {
|
|
248
|
+
const { cmd, slug, flags } = parseArgs(process.argv);
|
|
249
|
+
|
|
250
|
+
switch (cmd) {
|
|
251
|
+
case 'list':
|
|
252
|
+
await cmdList();
|
|
253
|
+
break;
|
|
254
|
+
case 'info':
|
|
255
|
+
await cmdInfo(slug);
|
|
256
|
+
break;
|
|
257
|
+
case 'run':
|
|
258
|
+
await cmdRun(slug, flags);
|
|
259
|
+
break;
|
|
260
|
+
case 'config':
|
|
261
|
+
await cmdConfig(flags);
|
|
262
|
+
break;
|
|
263
|
+
case 'help':
|
|
264
|
+
case '--help':
|
|
265
|
+
case '-h':
|
|
266
|
+
showHelp();
|
|
267
|
+
break;
|
|
268
|
+
case '--version':
|
|
269
|
+
case '-v':
|
|
270
|
+
log(`${pkg.version}`, 'bold');
|
|
271
|
+
break;
|
|
272
|
+
case 'version':
|
|
273
|
+
log(`${pkg.name} v${pkg.version}`, 'bold');
|
|
274
|
+
break;
|
|
275
|
+
default:
|
|
276
|
+
if (cmd) {
|
|
277
|
+
log(`❌ Comando desconhecido: ${cmd}`, 'red');
|
|
278
|
+
log(' Execute: npx aifeast help\n', 'yellow');
|
|
279
|
+
} else {
|
|
280
|
+
showHelp();
|
|
281
|
+
}
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
main().catch(err => {
|
|
287
|
+
log(`❌ Erro inesperado: ${err.message}`, 'red');
|
|
288
|
+
process.exit(1);
|
|
289
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aifeast",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI oficial do AI Feast Engine — install and run AI skills",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"aifeast": "index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"ai",
|
|
15
|
+
"feast",
|
|
16
|
+
"engine",
|
|
17
|
+
"cli",
|
|
18
|
+
"llm",
|
|
19
|
+
"skills",
|
|
20
|
+
"automation"
|
|
21
|
+
],
|
|
22
|
+
"author": "AI Feast Engine",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/ademilsonls81-oss/AI-Feast-Engine.git",
|
|
27
|
+
"directory": "cli"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://www.aifeastengine.com",
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=14.0.0"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"axios": "^1.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|