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 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.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', 'Mostrar todos os agentes disponíveis no marketplace')
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nex-framework-cli",
3
- "version": "1.0.6",
3
+ "version": "1.0.9",
4
4
  "description": "NEX CLI - Command-line interface for NEX Framework and Agent Marketplace",
5
5
  "type": "module",
6
6
  "main": "cli/nex-cli.js",
@@ -102,28 +102,46 @@ export default class NEXMarketplace {
102
102
 
103
103
  try {
104
104
  let results = []
105
+ let apiError = null
105
106
 
106
- // Search in Supabase if available
107
- if (this.supabase) {
108
- results = await this.searchRemote(query, options)
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
- // Also search local registry
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
- spinner.succeed(`Found ${merged.length} agents`)
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(`Error: ${error.message}`))
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
- const params = new URLSearchParams()
153
- if (query) params.append('q', query)
154
- if (options.category) params.append('category', options.category)
155
- if (options.official) params.append('official', 'true')
156
- if (options.limit) params.append('limit', options.limit.toString())
157
-
158
- const response = await fetch(`${this.apiUrl}/search?${params}`)
159
-
160
- if (!response.ok) {
161
- throw new Error(`API error: ${response.statusText}`)
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
- // List from API/Remote if available
214
+ // Try API/Remote first
178
215
  if (this.apiUrl) {
179
- results = await this.listAllViaAPI(options)
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
- results = await this.listAllViaClient(options)
234
+ try {
235
+ results = await this.listAllViaClient(options)
236
+ } catch (error) {
237
+ apiError = error
238
+ results = []
239
+ }
182
240
  }
183
241
 
184
- // Also include local registry
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
- spinner.succeed(`Found ${merged.length} available agents`)
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(`Error: ${error.message}`))
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
- const response = await fetch(`${this.apiUrl}/list`)
209
-
210
- if (!response.ok) {
211
- throw new Error(`API error: ${response.statusText}`)
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
  /**