nex-framework-cli 1.0.1 → 1.0.6
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
|
@@ -135,11 +135,20 @@ agentCmd
|
|
|
135
135
|
.command('list')
|
|
136
136
|
.alias('ls')
|
|
137
137
|
.description('Lista agentes instalados')
|
|
138
|
-
.option('-a, --all', 'Mostrar todos os agentes')
|
|
138
|
+
.option('-a, --all', 'Mostrar todos os agentes disponíveis no marketplace')
|
|
139
|
+
.option('-c, --category <category>', 'Filtrar por categoria')
|
|
140
|
+
.option('--official', 'Apenas agentes oficiais')
|
|
139
141
|
.action(async (options) => {
|
|
140
142
|
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
141
143
|
const marketplace = new NEXMarketplace()
|
|
142
|
-
|
|
144
|
+
|
|
145
|
+
if (options.all) {
|
|
146
|
+
// Listar todos os agentes disponíveis no marketplace
|
|
147
|
+
await marketplace.listAll(options)
|
|
148
|
+
} else {
|
|
149
|
+
// Listar apenas agentes instalados
|
|
150
|
+
await marketplace.list(options)
|
|
151
|
+
}
|
|
143
152
|
})
|
|
144
153
|
|
|
145
154
|
// agent info
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nex-framework-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
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",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"prepublishOnly": "npm run test",
|
|
20
|
-
"test": "node cli/nex-cli.js --version"
|
|
20
|
+
"test": "node cli/nex-cli.js --version",
|
|
21
|
+
"publish:cli": "node scripts/publish-cli.js",
|
|
22
|
+
"publish:cli:dry": "node scripts/publish-cli.js --dry-run"
|
|
21
23
|
},
|
|
22
24
|
"keywords": [
|
|
23
25
|
"nex",
|
|
@@ -31,14 +31,26 @@ export default class NEXMarketplace {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* Initialize Supabase client
|
|
34
|
+
* Initialize Supabase client and API URL
|
|
35
35
|
*/
|
|
36
36
|
initializeSupabase() {
|
|
37
37
|
const supabaseUrl = process.env.VITE_SUPABASE_URL
|
|
38
38
|
const supabaseKey = process.env.VITE_SUPABASE_ANON_KEY
|
|
39
39
|
|
|
40
|
+
// URL padrão da Edge Function (funciona sem configuração)
|
|
41
|
+
const DEFAULT_API_URL = 'https://jsazeeeqxxebydghsiad.supabase.co/functions/v1/nex-marketplace-api'
|
|
42
|
+
|
|
43
|
+
// API URL da Edge Function (preferida - sem expor anon key)
|
|
44
|
+
// Prioridade: 1) NEX_MARKETPLACE_API_URL, 2) Construída a partir de VITE_SUPABASE_URL, 3) Default
|
|
45
|
+
this.apiUrl = process.env.NEX_MARKETPLACE_API_URL ||
|
|
46
|
+
(supabaseUrl ? `${supabaseUrl}/functions/v1/nex-marketplace-api` : DEFAULT_API_URL)
|
|
47
|
+
|
|
48
|
+
// Cliente Supabase (apenas para operações que requerem autenticação)
|
|
40
49
|
if (supabaseUrl && supabaseKey) {
|
|
41
50
|
this.supabase = createClient(supabaseUrl, supabaseKey)
|
|
51
|
+
} else if (this.apiUrl) {
|
|
52
|
+
// Se tiver API URL mas não tiver anon key, ainda funciona para leitura
|
|
53
|
+
// Não mostra mensagem para não poluir o output
|
|
42
54
|
} else {
|
|
43
55
|
console.warn(chalk.yellow('⚠️ Supabase not configured. Marketplace will work in local-only mode.'))
|
|
44
56
|
}
|
|
@@ -117,9 +129,124 @@ export default class NEXMarketplace {
|
|
|
117
129
|
}
|
|
118
130
|
|
|
119
131
|
/**
|
|
120
|
-
* Search in Supabase
|
|
132
|
+
* Search in Supabase (via Edge Function ou cliente direto)
|
|
121
133
|
*/
|
|
122
134
|
async searchRemote(query, options = {}) {
|
|
135
|
+
// Preferir Edge Function (mais seguro - sem anon key)
|
|
136
|
+
if (this.apiUrl) {
|
|
137
|
+
return await this.searchViaAPI(query, options)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Fallback para cliente direto (se anon key disponível)
|
|
141
|
+
if (this.supabase) {
|
|
142
|
+
return await this.searchViaClient(query, options)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return []
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Search via Edge Function API (SEGURO - sem anon key)
|
|
150
|
+
*/
|
|
151
|
+
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}`)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const { agents } = await response.json()
|
|
165
|
+
return agents || []
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* List all available agents (browse marketplace)
|
|
170
|
+
*/
|
|
171
|
+
async listAll(options = {}) {
|
|
172
|
+
const spinner = ora('Loading available agents...').start()
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
let results = []
|
|
176
|
+
|
|
177
|
+
// List from API/Remote if available
|
|
178
|
+
if (this.apiUrl) {
|
|
179
|
+
results = await this.listAllViaAPI(options)
|
|
180
|
+
} else if (this.supabase) {
|
|
181
|
+
results = await this.listAllViaClient(options)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Also include local registry
|
|
185
|
+
const localResults = await this.searchLocal('', options)
|
|
186
|
+
|
|
187
|
+
// Merge results
|
|
188
|
+
const merged = this.mergeResults(results, localResults)
|
|
189
|
+
|
|
190
|
+
spinner.succeed(`Found ${merged.length} available agents`)
|
|
191
|
+
|
|
192
|
+
// Display results
|
|
193
|
+
this.displaySearchResults(merged)
|
|
194
|
+
|
|
195
|
+
return merged
|
|
196
|
+
|
|
197
|
+
} catch (error) {
|
|
198
|
+
spinner.fail('Failed to load agents')
|
|
199
|
+
console.error(chalk.red(`Error: ${error.message}`))
|
|
200
|
+
throw error
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* List all agents via Edge Function API
|
|
206
|
+
*/
|
|
207
|
+
async listAllViaAPI(options = {}) {
|
|
208
|
+
const response = await fetch(`${this.apiUrl}/list`)
|
|
209
|
+
|
|
210
|
+
if (!response.ok) {
|
|
211
|
+
throw new Error(`API error: ${response.statusText}`)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const { agents } = await response.json()
|
|
215
|
+
return agents || []
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* List all agents via Supabase client (fallback)
|
|
220
|
+
*/
|
|
221
|
+
async listAllViaClient(options = {}) {
|
|
222
|
+
let query = this.supabase
|
|
223
|
+
.from('nex_marketplace_agents')
|
|
224
|
+
.select('*')
|
|
225
|
+
.eq('is_active', true)
|
|
226
|
+
.order('total_installs', { ascending: false })
|
|
227
|
+
|
|
228
|
+
if (options.category) {
|
|
229
|
+
query = query.eq('category', options.category)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (options.official) {
|
|
233
|
+
query = query.eq('is_official', true)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const limit = options.limit || 100
|
|
237
|
+
query = query.limit(limit)
|
|
238
|
+
|
|
239
|
+
const { data, error } = await query
|
|
240
|
+
|
|
241
|
+
if (error) throw error
|
|
242
|
+
|
|
243
|
+
return data || []
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Search via Supabase client (fallback - requer anon key)
|
|
248
|
+
*/
|
|
249
|
+
async searchViaClient(query, options = {}) {
|
|
123
250
|
let dbQuery = this.supabase
|
|
124
251
|
.from('nex_marketplace_agents')
|
|
125
252
|
.select('*')
|
|
@@ -275,10 +402,20 @@ export default class NEXMarketplace {
|
|
|
275
402
|
const spinner = ora(`Loading info for ${agentId}...`).start()
|
|
276
403
|
|
|
277
404
|
try {
|
|
278
|
-
// Try to load from
|
|
405
|
+
// Try to load from API/Remote first (prefer API)
|
|
279
406
|
let agent = null
|
|
280
407
|
|
|
281
|
-
if (this.
|
|
408
|
+
if (this.apiUrl) {
|
|
409
|
+
try {
|
|
410
|
+
const response = await fetch(`${this.apiUrl}/info/${agentId}`)
|
|
411
|
+
if (response.ok) {
|
|
412
|
+
const { agent: apiAgent } = await response.json()
|
|
413
|
+
agent = apiAgent
|
|
414
|
+
}
|
|
415
|
+
} catch (error) {
|
|
416
|
+
// Silently fallback
|
|
417
|
+
}
|
|
418
|
+
} else if (this.supabase) {
|
|
282
419
|
const { data } = await this.supabase
|
|
283
420
|
.from('nex_marketplace_agents')
|
|
284
421
|
.select('*')
|