nex-framework-cli 1.0.6 → 1.0.9
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/cli/nex-cli.js +100 -11
- package/package.json +1 -1
- package/src/services/nex-marketplace/NEXMarketplace.js +122 -32
package/cli/nex-cli.js
CHANGED
|
@@ -15,17 +15,51 @@ const __dirname = path.dirname(__filename)
|
|
|
15
15
|
|
|
16
16
|
const program = new Command()
|
|
17
17
|
|
|
18
|
+
// Custom help formatting
|
|
19
|
+
program.configureHelp({
|
|
20
|
+
helpWidth: 100,
|
|
21
|
+
sortSubcommands: true,
|
|
22
|
+
subcommandTerm: (cmd) => {
|
|
23
|
+
const aliases = cmd.aliases().length > 0 ? `|${cmd.aliases().join('|')}` : ''
|
|
24
|
+
return chalk.cyan(`${cmd.name()}${aliases}`)
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
18
28
|
program
|
|
19
29
|
.name('nex')
|
|
20
30
|
.description('NEX Framework - Framework completo de agentes AI')
|
|
21
|
-
.version('1.0.
|
|
31
|
+
.version('1.0.8', '-v, --version', 'Mostra a versão')
|
|
32
|
+
.addHelpText('before', chalk.bold.cyan(`
|
|
33
|
+
╔════════════════════════════════════════════════════════════════╗
|
|
34
|
+
║ NEX Framework - CLI v1.0.8 ║
|
|
35
|
+
║ Framework completo de agentes AI ║
|
|
36
|
+
╚════════════════════════════════════════════════════════════════╝
|
|
37
|
+
`))
|
|
38
|
+
.addHelpText('after', chalk.gray(`
|
|
39
|
+
📚 Exemplos rápidos:
|
|
40
|
+
${chalk.cyan('nex agent list --all')} Lista todos os agentes disponíveis
|
|
41
|
+
${chalk.cyan('nex agent search planning')} Busca agentes por termo
|
|
42
|
+
${chalk.cyan('nex agent install anx')} Instala um agente
|
|
43
|
+
${chalk.cyan('nex agent info anx')} Mostra informações de um agente
|
|
44
|
+
|
|
45
|
+
📖 Para mais informações sobre um comando:
|
|
46
|
+
${chalk.cyan('nex <comando> --help')} Ex: nex agent --help
|
|
47
|
+
|
|
48
|
+
🔗 Documentação: https://github.com/INOSX/nex-store
|
|
49
|
+
`))
|
|
22
50
|
|
|
23
51
|
// Comando: init
|
|
24
52
|
program
|
|
25
53
|
.command('init')
|
|
26
54
|
.description('Inicializa um novo projeto NEX')
|
|
27
55
|
.option('-n, --name <name>', 'Nome do projeto')
|
|
28
|
-
.option('-t, --template <template>', 'Template a usar')
|
|
56
|
+
.option('-t, --template <template>', 'Template a usar (blank, full-stack, api-only, mobile)')
|
|
57
|
+
.addHelpText('after', chalk.gray(`
|
|
58
|
+
Exemplos:
|
|
59
|
+
${chalk.cyan('nex init')} Inicializa projeto interativamente
|
|
60
|
+
${chalk.cyan('nex init -n meu-projeto')} Inicializa com nome específico
|
|
61
|
+
${chalk.cyan('nex init -t full-stack')} Usa template full-stack
|
|
62
|
+
`))
|
|
29
63
|
.action(async (options) => {
|
|
30
64
|
console.log(chalk.blue('🚀 Inicializando projeto NEX...'))
|
|
31
65
|
|
|
@@ -60,6 +94,14 @@ program
|
|
|
60
94
|
program
|
|
61
95
|
.command('plan')
|
|
62
96
|
.description('Gera plano completo do projeto (PRD, arquitetura, etc.)')
|
|
97
|
+
.option('-r, --requirements <file>', 'Arquivo de requisitos JSON')
|
|
98
|
+
.option('-o, --output <dir>', 'Diretório de saída')
|
|
99
|
+
.addHelpText('after', chalk.gray(`
|
|
100
|
+
Exemplos:
|
|
101
|
+
${chalk.cyan('nex plan')} Gera plano interativamente
|
|
102
|
+
${chalk.cyan('nex plan -r requirements.json')} Usa arquivo de requisitos
|
|
103
|
+
${chalk.cyan('nex plan -o ./docs')} Salva em diretório específico
|
|
104
|
+
`))
|
|
63
105
|
.option('-r, --requirements <file>', 'Arquivo de requisitos')
|
|
64
106
|
.option('-o, --output <dir>', 'Diretório de saída')
|
|
65
107
|
.action(async (options) => {
|
|
@@ -104,14 +146,24 @@ program
|
|
|
104
146
|
const agentCmd = program
|
|
105
147
|
.command('agent')
|
|
106
148
|
.description('Gerencia agentes do NEX Marketplace')
|
|
149
|
+
.addHelpText('before', chalk.bold('\n📦 Marketplace de Agentes\n'))
|
|
150
|
+
.addHelpText('after', chalk.gray(`
|
|
151
|
+
💡 Dica: Use ${chalk.cyan('nex agent list --all')} para ver todos os agentes disponíveis
|
|
152
|
+
`))
|
|
107
153
|
|
|
108
154
|
// agent search
|
|
109
155
|
agentCmd
|
|
110
156
|
.command('search <query>')
|
|
111
|
-
.description('Busca agentes no marketplace')
|
|
112
|
-
.option('-c, --category <category>', 'Filtrar por categoria')
|
|
157
|
+
.description('Busca agentes no marketplace por termo')
|
|
158
|
+
.option('-c, --category <category>', 'Filtrar por categoria (planning, execution, community)')
|
|
113
159
|
.option('--official', 'Apenas agentes oficiais')
|
|
114
160
|
.option('-l, --limit <number>', 'Limitar resultados', '50')
|
|
161
|
+
.addHelpText('after', chalk.gray(`
|
|
162
|
+
Exemplos:
|
|
163
|
+
${chalk.cyan('nex agent search planning')} Busca por "planning"
|
|
164
|
+
${chalk.cyan('nex agent search "análise" --official')} Busca apenas oficiais
|
|
165
|
+
${chalk.cyan('nex agent search "" --category planning')} Lista todos de planejamento
|
|
166
|
+
`))
|
|
115
167
|
.action(async (query, options) => {
|
|
116
168
|
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
117
169
|
const marketplace = new NEXMarketplace()
|
|
@@ -121,9 +173,15 @@ agentCmd
|
|
|
121
173
|
// agent install
|
|
122
174
|
agentCmd
|
|
123
175
|
.command('install <agentId>')
|
|
124
|
-
.description('Instala um agente')
|
|
176
|
+
.description('Instala um agente no projeto atual')
|
|
125
177
|
.option('-v, --version <version>', 'Versão específica')
|
|
126
178
|
.option('-m, --method <method>', 'Método de instalação (symlink|copy)')
|
|
179
|
+
.addHelpText('after', chalk.gray(`
|
|
180
|
+
Exemplos:
|
|
181
|
+
${chalk.cyan('nex agent install anx')} Instala o agente ANX
|
|
182
|
+
${chalk.cyan('nex agent install anx -v 1.0.0')} Instala versão específica
|
|
183
|
+
${chalk.cyan('nex agent install anx -m copy')} Instala usando cópia
|
|
184
|
+
`))
|
|
127
185
|
.action(async (agentId, options) => {
|
|
128
186
|
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
129
187
|
const marketplace = new NEXMarketplace()
|
|
@@ -134,10 +192,17 @@ agentCmd
|
|
|
134
192
|
agentCmd
|
|
135
193
|
.command('list')
|
|
136
194
|
.alias('ls')
|
|
137
|
-
.description('Lista agentes instalados')
|
|
138
|
-
.option('-a, --all', '
|
|
139
|
-
.option('-c, --category <category>', 'Filtrar por categoria')
|
|
195
|
+
.description('Lista agentes instalados ou todos os agentes disponíveis no marketplace')
|
|
196
|
+
.option('-a, --all', 'Listar todos os agentes disponíveis no marketplace')
|
|
197
|
+
.option('-c, --category <category>', 'Filtrar por categoria (planning, execution, community)')
|
|
140
198
|
.option('--official', 'Apenas agentes oficiais')
|
|
199
|
+
.addHelpText('after', chalk.gray(`
|
|
200
|
+
Exemplos:
|
|
201
|
+
${chalk.cyan('nex agent list --all')} Lista todos os agentes disponíveis
|
|
202
|
+
${chalk.cyan('nex agent list')} Lista apenas agentes instalados
|
|
203
|
+
${chalk.cyan('nex agent list --all --category planning')} Lista agentes de planejamento
|
|
204
|
+
${chalk.cyan('nex agent list --all --official')} Lista apenas agentes oficiais
|
|
205
|
+
`))
|
|
141
206
|
.action(async (options) => {
|
|
142
207
|
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
143
208
|
const marketplace = new NEXMarketplace()
|
|
@@ -155,6 +220,11 @@ agentCmd
|
|
|
155
220
|
agentCmd
|
|
156
221
|
.command('info <agentId>')
|
|
157
222
|
.description('Mostra informações detalhadas do agente')
|
|
223
|
+
.addHelpText('after', chalk.gray(`
|
|
224
|
+
Exemplos:
|
|
225
|
+
${chalk.cyan('nex agent info anx')} Informações do agente ANX
|
|
226
|
+
${chalk.cyan('nex agent info pmx')} Informações do agente PMX
|
|
227
|
+
`))
|
|
158
228
|
.action(async (agentId) => {
|
|
159
229
|
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
160
230
|
const marketplace = new NEXMarketplace()
|
|
@@ -165,7 +235,12 @@ agentCmd
|
|
|
165
235
|
agentCmd
|
|
166
236
|
.command('uninstall <agentId>')
|
|
167
237
|
.alias('remove')
|
|
168
|
-
.description('Remove um agente instalado')
|
|
238
|
+
.description('Remove um agente instalado do projeto')
|
|
239
|
+
.addHelpText('after', chalk.gray(`
|
|
240
|
+
Exemplos:
|
|
241
|
+
${chalk.cyan('nex agent uninstall anx')} Remove o agente ANX
|
|
242
|
+
${chalk.cyan('nex agent remove anx')} Alias para uninstall
|
|
243
|
+
`))
|
|
169
244
|
.action(async (agentId) => {
|
|
170
245
|
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
171
246
|
const marketplace = new NEXMarketplace()
|
|
@@ -175,8 +250,13 @@ agentCmd
|
|
|
175
250
|
// agent update
|
|
176
251
|
agentCmd
|
|
177
252
|
.command('update [agentId]')
|
|
178
|
-
.description('Atualiza agente(s)')
|
|
179
|
-
.option('-a, --all', 'Atualizar todos os agentes')
|
|
253
|
+
.description('Atualiza agente(s) para a versão mais recente')
|
|
254
|
+
.option('-a, --all', 'Atualizar todos os agentes instalados')
|
|
255
|
+
.addHelpText('after', chalk.gray(`
|
|
256
|
+
Exemplos:
|
|
257
|
+
${chalk.cyan('nex agent update anx')} Atualiza o agente ANX
|
|
258
|
+
${chalk.cyan('nex agent update --all')} Atualiza todos os agentes
|
|
259
|
+
`))
|
|
180
260
|
.action(async (agentId, options) => {
|
|
181
261
|
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
182
262
|
const marketplace = new NEXMarketplace()
|
|
@@ -197,6 +277,10 @@ agentCmd
|
|
|
197
277
|
agentCmd
|
|
198
278
|
.command('register <agentId>')
|
|
199
279
|
.description('Registra um agente no NEX Hub para uso')
|
|
280
|
+
.addHelpText('after', chalk.gray(`
|
|
281
|
+
Exemplos:
|
|
282
|
+
${chalk.cyan('nex agent register anx')} Registra o agente ANX no Hub
|
|
283
|
+
`))
|
|
200
284
|
.action(async (agentId) => {
|
|
201
285
|
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
202
286
|
const marketplace = new NEXMarketplace()
|
|
@@ -208,6 +292,11 @@ agentCmd
|
|
|
208
292
|
.command('my-agents')
|
|
209
293
|
.alias('registered')
|
|
210
294
|
.description('Lista agentes registrados no NEX Hub')
|
|
295
|
+
.addHelpText('after', chalk.gray(`
|
|
296
|
+
Exemplos:
|
|
297
|
+
${chalk.cyan('nex agent my-agents')} Lista seus agentes registrados
|
|
298
|
+
${chalk.cyan('nex agent registered')} Alias para my-agents
|
|
299
|
+
`))
|
|
211
300
|
.action(async () => {
|
|
212
301
|
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
213
302
|
const marketplace = new NEXMarketplace()
|
package/package.json
CHANGED
|
@@ -102,28 +102,46 @@ export default class NEXMarketplace {
|
|
|
102
102
|
|
|
103
103
|
try {
|
|
104
104
|
let results = []
|
|
105
|
+
let apiError = null
|
|
105
106
|
|
|
106
|
-
//
|
|
107
|
-
if (this.supabase) {
|
|
108
|
-
|
|
107
|
+
// Try remote search first
|
|
108
|
+
if (this.apiUrl || this.supabase) {
|
|
109
|
+
try {
|
|
110
|
+
results = await this.searchRemote(query, options)
|
|
111
|
+
} catch (error) {
|
|
112
|
+
apiError = error
|
|
113
|
+
// Continue with local search only
|
|
114
|
+
console.warn(chalk.yellow(`\n⚠️ Could not connect to marketplace: ${error.message}`))
|
|
115
|
+
console.log(chalk.gray(' Searching local registry only...\n'))
|
|
116
|
+
}
|
|
109
117
|
}
|
|
110
118
|
|
|
111
|
-
//
|
|
119
|
+
// Always search local registry
|
|
112
120
|
const localResults = await this.searchLocal(query, options)
|
|
113
121
|
|
|
114
122
|
// Merge results (deduplicate by agent_id)
|
|
115
123
|
const merged = this.mergeResults(results, localResults)
|
|
116
124
|
|
|
117
|
-
|
|
125
|
+
if (merged.length > 0) {
|
|
126
|
+
spinner.succeed(`Found ${merged.length} agents`)
|
|
127
|
+
} else {
|
|
128
|
+
spinner.warn('No agents found')
|
|
129
|
+
}
|
|
118
130
|
|
|
119
131
|
// Display results
|
|
120
132
|
this.displaySearchResults(merged)
|
|
121
133
|
|
|
134
|
+
// Show warning if API failed
|
|
135
|
+
if (apiError && localResults.length > 0) {
|
|
136
|
+
console.log(chalk.yellow('\n💡 Tip: Some results may be missing. Check your connection.\n'))
|
|
137
|
+
}
|
|
138
|
+
|
|
122
139
|
return merged
|
|
123
140
|
|
|
124
141
|
} catch (error) {
|
|
125
142
|
spinner.fail('Search failed')
|
|
126
|
-
console.error(chalk.red(
|
|
143
|
+
console.error(chalk.red(`\nError: ${error.message}`))
|
|
144
|
+
console.log(chalk.gray('\n💡 Try searching locally or check your connection.\n'))
|
|
127
145
|
throw error
|
|
128
146
|
}
|
|
129
147
|
}
|
|
@@ -149,20 +167,38 @@ export default class NEXMarketplace {
|
|
|
149
167
|
* Search via Edge Function API (SEGURO - sem anon key)
|
|
150
168
|
*/
|
|
151
169
|
async searchViaAPI(query, options = {}) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
170
|
+
try {
|
|
171
|
+
const params = new URLSearchParams()
|
|
172
|
+
if (query) params.append('q', query)
|
|
173
|
+
if (options.category) params.append('category', options.category)
|
|
174
|
+
if (options.official) params.append('official', 'true')
|
|
175
|
+
if (options.limit) params.append('limit', options.limit.toString())
|
|
176
|
+
|
|
177
|
+
// Timeout de 10 segundos
|
|
178
|
+
const controller = new AbortController()
|
|
179
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000)
|
|
180
|
+
|
|
181
|
+
const response = await fetch(`${this.apiUrl}/search?${params}`, {
|
|
182
|
+
signal: controller.signal
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
clearTimeout(timeoutId)
|
|
186
|
+
|
|
187
|
+
if (!response.ok) {
|
|
188
|
+
throw new Error(`API error: ${response.statusText}`)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const { agents } = await response.json()
|
|
192
|
+
return agents || []
|
|
193
|
+
} catch (error) {
|
|
194
|
+
if (error.name === 'AbortError') {
|
|
195
|
+
throw new Error('Connection timeout. The marketplace API is not responding.')
|
|
196
|
+
}
|
|
197
|
+
if (error.code === 'UND_ERR_CONNECT_TIMEOUT' || error.message.includes('timeout')) {
|
|
198
|
+
throw new Error('Connection timeout. Please check your internet connection or try again later.')
|
|
199
|
+
}
|
|
200
|
+
throw error
|
|
162
201
|
}
|
|
163
|
-
|
|
164
|
-
const { agents } = await response.json()
|
|
165
|
-
return agents || []
|
|
166
202
|
}
|
|
167
203
|
|
|
168
204
|
/**
|
|
@@ -173,30 +209,66 @@ export default class NEXMarketplace {
|
|
|
173
209
|
|
|
174
210
|
try {
|
|
175
211
|
let results = []
|
|
212
|
+
let apiError = null
|
|
176
213
|
|
|
177
|
-
//
|
|
214
|
+
// Try API/Remote first
|
|
178
215
|
if (this.apiUrl) {
|
|
179
|
-
|
|
216
|
+
try {
|
|
217
|
+
results = await this.listAllViaAPI(options)
|
|
218
|
+
} catch (error) {
|
|
219
|
+
apiError = error
|
|
220
|
+
console.warn(chalk.yellow(`\n⚠️ Could not connect to marketplace API: ${error.message}`))
|
|
221
|
+
console.log(chalk.gray(' Falling back to local registry...\n'))
|
|
222
|
+
|
|
223
|
+
// Try Supabase client as fallback
|
|
224
|
+
if (this.supabase) {
|
|
225
|
+
try {
|
|
226
|
+
results = await this.listAllViaClient(options)
|
|
227
|
+
} catch (clientError) {
|
|
228
|
+
// If both fail, continue with local only
|
|
229
|
+
results = []
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
180
233
|
} else if (this.supabase) {
|
|
181
|
-
|
|
234
|
+
try {
|
|
235
|
+
results = await this.listAllViaClient(options)
|
|
236
|
+
} catch (error) {
|
|
237
|
+
apiError = error
|
|
238
|
+
results = []
|
|
239
|
+
}
|
|
182
240
|
}
|
|
183
241
|
|
|
184
|
-
//
|
|
242
|
+
// Always include local registry
|
|
185
243
|
const localResults = await this.searchLocal('', options)
|
|
186
244
|
|
|
187
245
|
// Merge results
|
|
188
246
|
const merged = this.mergeResults(results, localResults)
|
|
189
247
|
|
|
190
|
-
|
|
248
|
+
if (merged.length > 0) {
|
|
249
|
+
spinner.succeed(`Found ${merged.length} available agents`)
|
|
250
|
+
} else {
|
|
251
|
+
spinner.warn('No agents found')
|
|
252
|
+
}
|
|
191
253
|
|
|
192
254
|
// Display results
|
|
193
255
|
this.displaySearchResults(merged)
|
|
194
256
|
|
|
257
|
+
// Show warning if API failed but we have local results
|
|
258
|
+
if (apiError && localResults.length > 0) {
|
|
259
|
+
console.log(chalk.yellow('\n💡 Tip: Some agents may be missing. Check your connection or configure NEX_MARKETPLACE_API_URL\n'))
|
|
260
|
+
}
|
|
261
|
+
|
|
195
262
|
return merged
|
|
196
263
|
|
|
197
264
|
} catch (error) {
|
|
198
265
|
spinner.fail('Failed to load agents')
|
|
199
|
-
console.error(chalk.red(
|
|
266
|
+
console.error(chalk.red(`\nError: ${error.message}`))
|
|
267
|
+
console.log(chalk.gray('\n💡 Troubleshooting:'))
|
|
268
|
+
console.log(chalk.gray(' 1. Check your internet connection'))
|
|
269
|
+
console.log(chalk.gray(' 2. Verify the API URL: ' + (this.apiUrl || 'not configured')))
|
|
270
|
+
console.log(chalk.gray(' 3. Try: nex agent list (shows only installed agents)'))
|
|
271
|
+
console.log(chalk.gray(' 4. Configure custom API: export NEX_MARKETPLACE_API_URL=<your-url>\n'))
|
|
200
272
|
throw error
|
|
201
273
|
}
|
|
202
274
|
}
|
|
@@ -205,14 +277,32 @@ export default class NEXMarketplace {
|
|
|
205
277
|
* List all agents via Edge Function API
|
|
206
278
|
*/
|
|
207
279
|
async listAllViaAPI(options = {}) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
280
|
+
try {
|
|
281
|
+
// Timeout de 10 segundos
|
|
282
|
+
const controller = new AbortController()
|
|
283
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000)
|
|
284
|
+
|
|
285
|
+
const response = await fetch(`${this.apiUrl}/list`, {
|
|
286
|
+
signal: controller.signal
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
clearTimeout(timeoutId)
|
|
290
|
+
|
|
291
|
+
if (!response.ok) {
|
|
292
|
+
throw new Error(`API error: ${response.statusText}`)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const { agents } = await response.json()
|
|
296
|
+
return agents || []
|
|
297
|
+
} catch (error) {
|
|
298
|
+
if (error.name === 'AbortError') {
|
|
299
|
+
throw new Error('Connection timeout. The marketplace API is not responding.')
|
|
300
|
+
}
|
|
301
|
+
if (error.code === 'UND_ERR_CONNECT_TIMEOUT' || error.message.includes('timeout')) {
|
|
302
|
+
throw new Error('Connection timeout. Please check your internet connection or try again later.')
|
|
303
|
+
}
|
|
304
|
+
throw error
|
|
212
305
|
}
|
|
213
|
-
|
|
214
|
-
const { agents } = await response.json()
|
|
215
|
-
return agents || []
|
|
216
306
|
}
|
|
217
307
|
|
|
218
308
|
/**
|