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.
Files changed (3) hide show
  1. package/README.md +107 -0
  2. package/index.js +289 -0
  3. 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
+ }