nex-framework-cli 1.0.7 → 1.0.10
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
|
@@ -28,10 +28,10 @@ program.configureHelp({
|
|
|
28
28
|
program
|
|
29
29
|
.name('nex')
|
|
30
30
|
.description('NEX Framework - Framework completo de agentes AI')
|
|
31
|
-
.version('1.0.
|
|
31
|
+
.version('1.0.9', '-v, --version', 'Mostra a versão')
|
|
32
32
|
.addHelpText('before', chalk.bold.cyan(`
|
|
33
33
|
╔════════════════════════════════════════════════════════════════╗
|
|
34
|
-
║ NEX Framework - CLI v1.0.
|
|
34
|
+
║ NEX Framework - CLI v1.0.9 ║
|
|
35
35
|
║ Framework completo de agentes AI ║
|
|
36
36
|
╚════════════════════════════════════════════════════════════════╝
|
|
37
37
|
`))
|
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,77 @@ 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 if (apiError && localResults.length === 0) {
|
|
251
|
+
spinner.warn('No agents found (API unavailable and no local registry)')
|
|
252
|
+
} else {
|
|
253
|
+
spinner.warn('No agents found')
|
|
254
|
+
}
|
|
191
255
|
|
|
192
256
|
// Display results
|
|
193
257
|
this.displaySearchResults(merged)
|
|
194
258
|
|
|
259
|
+
// Show helpful messages
|
|
260
|
+
if (apiError) {
|
|
261
|
+
if (localResults.length > 0) {
|
|
262
|
+
console.log(chalk.yellow('\n💡 Tip: Some agents may be missing. Check your connection or configure NEX_MARKETPLACE_API_URL\n'))
|
|
263
|
+
} else {
|
|
264
|
+
console.log(chalk.yellow('\n💡 Troubleshooting:'))
|
|
265
|
+
console.log(chalk.gray(' • The marketplace API is not responding'))
|
|
266
|
+
console.log(chalk.gray(' • No local registry found in this project'))
|
|
267
|
+
console.log(chalk.gray(' • Try: nex agent list (shows only installed agents)'))
|
|
268
|
+
console.log(chalk.gray(' • Or configure: export NEX_MARKETPLACE_API_URL=<your-url>'))
|
|
269
|
+
console.log(chalk.gray(' • Check your internet connection and try again later\n'))
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
195
273
|
return merged
|
|
196
274
|
|
|
197
275
|
} catch (error) {
|
|
198
276
|
spinner.fail('Failed to load agents')
|
|
199
|
-
console.error(chalk.red(
|
|
277
|
+
console.error(chalk.red(`\nError: ${error.message}`))
|
|
278
|
+
console.log(chalk.gray('\n💡 Troubleshooting:'))
|
|
279
|
+
console.log(chalk.gray(' 1. Check your internet connection'))
|
|
280
|
+
console.log(chalk.gray(' 2. Verify the API URL: ' + (this.apiUrl || 'not configured')))
|
|
281
|
+
console.log(chalk.gray(' 3. Try: nex agent list (shows only installed agents)'))
|
|
282
|
+
console.log(chalk.gray(' 4. Configure custom API: export NEX_MARKETPLACE_API_URL=<your-url>\n'))
|
|
200
283
|
throw error
|
|
201
284
|
}
|
|
202
285
|
}
|
|
@@ -205,14 +288,32 @@ export default class NEXMarketplace {
|
|
|
205
288
|
* List all agents via Edge Function API
|
|
206
289
|
*/
|
|
207
290
|
async listAllViaAPI(options = {}) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
291
|
+
try {
|
|
292
|
+
// Timeout de 10 segundos
|
|
293
|
+
const controller = new AbortController()
|
|
294
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000)
|
|
295
|
+
|
|
296
|
+
const response = await fetch(`${this.apiUrl}/list`, {
|
|
297
|
+
signal: controller.signal
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
clearTimeout(timeoutId)
|
|
301
|
+
|
|
302
|
+
if (!response.ok) {
|
|
303
|
+
throw new Error(`API error: ${response.statusText}`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const { agents } = await response.json()
|
|
307
|
+
return agents || []
|
|
308
|
+
} catch (error) {
|
|
309
|
+
if (error.name === 'AbortError') {
|
|
310
|
+
throw new Error('Connection timeout. The marketplace API is not responding.')
|
|
311
|
+
}
|
|
312
|
+
if (error.code === 'UND_ERR_CONNECT_TIMEOUT' || error.message.includes('timeout')) {
|
|
313
|
+
throw new Error('Connection timeout. Please check your internet connection or try again later.')
|
|
314
|
+
}
|
|
315
|
+
throw error
|
|
212
316
|
}
|
|
213
|
-
|
|
214
|
-
const { agents } = await response.json()
|
|
215
|
-
return agents || []
|
|
216
317
|
}
|
|
217
318
|
|
|
218
319
|
/**
|
|
@@ -287,6 +388,11 @@ export default class NEXMarketplace {
|
|
|
287
388
|
async searchLocal(query, options = {}) {
|
|
288
389
|
const results = []
|
|
289
390
|
|
|
391
|
+
// Check if registry path exists
|
|
392
|
+
if (!await fs.pathExists(this.registryPath)) {
|
|
393
|
+
return results
|
|
394
|
+
}
|
|
395
|
+
|
|
290
396
|
const categories = ['planning', 'execution', 'community']
|
|
291
397
|
|
|
292
398
|
for (const category of categories) {
|
|
@@ -294,36 +400,49 @@ export default class NEXMarketplace {
|
|
|
294
400
|
|
|
295
401
|
if (!await fs.pathExists(categoryPath)) continue
|
|
296
402
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
for (const agentId of agents) {
|
|
300
|
-
const manifestPath = path.join(categoryPath, agentId, 'manifest.yaml')
|
|
301
|
-
|
|
302
|
-
if (!await fs.pathExists(manifestPath)) continue
|
|
403
|
+
try {
|
|
404
|
+
const agents = await fs.readdir(categoryPath)
|
|
303
405
|
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (query) {
|
|
309
|
-
const searchable = [
|
|
310
|
-
manifest.name,
|
|
311
|
-
manifest.description,
|
|
312
|
-
manifest.tagline,
|
|
313
|
-
...(manifest.tags || [])
|
|
314
|
-
].join(' ').toLowerCase()
|
|
406
|
+
for (const agentId of agents) {
|
|
407
|
+
const manifestPath = path.join(categoryPath, agentId, 'manifest.yaml')
|
|
408
|
+
|
|
409
|
+
if (!await fs.pathExists(manifestPath)) continue
|
|
315
410
|
|
|
316
|
-
|
|
411
|
+
try {
|
|
412
|
+
const manifestFile = await fs.readFile(manifestPath, 'utf8')
|
|
413
|
+
const manifest = yaml.parse(manifestFile)
|
|
414
|
+
|
|
415
|
+
// Filter by query
|
|
416
|
+
if (query) {
|
|
417
|
+
const searchable = [
|
|
418
|
+
manifest.name,
|
|
419
|
+
manifest.description,
|
|
420
|
+
manifest.tagline,
|
|
421
|
+
...(manifest.tags || [])
|
|
422
|
+
].join(' ').toLowerCase()
|
|
423
|
+
|
|
424
|
+
if (!searchable.includes(query.toLowerCase())) {
|
|
425
|
+
continue
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Filter by category
|
|
430
|
+
if (options.category && manifest.category !== options.category) {
|
|
431
|
+
continue
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
results.push({
|
|
435
|
+
agent_id: agentId,
|
|
436
|
+
...manifest
|
|
437
|
+
})
|
|
438
|
+
} catch (error) {
|
|
439
|
+
// Skip invalid manifests
|
|
317
440
|
continue
|
|
318
441
|
}
|
|
319
442
|
}
|
|
320
|
-
|
|
321
|
-
//
|
|
322
|
-
|
|
323
|
-
continue
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
results.push(manifest)
|
|
443
|
+
} catch (error) {
|
|
444
|
+
// Skip categories that can't be read
|
|
445
|
+
continue
|
|
327
446
|
}
|
|
328
447
|
}
|
|
329
448
|
|