nex-framework-cli 1.0.18 → 1.0.20
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,7 +28,7 @@ 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.19', '-v, --version', 'Mostra a versão')
|
|
32
32
|
.addHelpText('before', chalk.bold.cyan(`
|
|
33
33
|
╔════════════════════════════════════════════════════════════════╗
|
|
34
34
|
║ NEX Framework - CLI v1.0.9 ║
|
|
@@ -64,12 +64,26 @@ Exemplos:
|
|
|
64
64
|
console.log(chalk.blue('🚀 Inicializando projeto NEX...'))
|
|
65
65
|
console.log()
|
|
66
66
|
|
|
67
|
+
// Detectar nome do projeto atual (da pasta ou package.json)
|
|
68
|
+
let currentProjectName = path.basename(process.cwd())
|
|
69
|
+
try {
|
|
70
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json')
|
|
71
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
72
|
+
const packageJson = await fs.readJSON(packageJsonPath)
|
|
73
|
+
if (packageJson.name) {
|
|
74
|
+
currentProjectName = packageJson.name
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} catch (error) {
|
|
78
|
+
// Ignore errors
|
|
79
|
+
}
|
|
80
|
+
|
|
67
81
|
const answers = await inquirer.prompt([
|
|
68
82
|
{
|
|
69
83
|
type: 'input',
|
|
70
84
|
name: 'projectName',
|
|
71
85
|
message: 'Nome do projeto:',
|
|
72
|
-
default: options.name ||
|
|
86
|
+
default: options.name || currentProjectName,
|
|
73
87
|
when: !options.name
|
|
74
88
|
},
|
|
75
89
|
{
|
|
@@ -85,10 +99,10 @@ Exemplos:
|
|
|
85
99
|
const projectName = options.name || answers.projectName
|
|
86
100
|
const template = options.template || answers.template
|
|
87
101
|
|
|
88
|
-
// Criar estrutura do projeto (
|
|
89
|
-
await createProjectStructure(projectName, template)
|
|
102
|
+
// Criar estrutura do projeto no diretório atual (não criar nova pasta)
|
|
103
|
+
await createProjectStructure(projectName, template, true)
|
|
90
104
|
|
|
91
|
-
console.log(chalk.green(`\n✅ Projeto ${projectName}
|
|
105
|
+
console.log(chalk.green(`\n✅ Projeto ${projectName} inicializado com sucesso!`))
|
|
92
106
|
console.log()
|
|
93
107
|
})
|
|
94
108
|
|
|
@@ -342,25 +356,42 @@ program
|
|
|
342
356
|
})
|
|
343
357
|
|
|
344
358
|
// Comando: config
|
|
345
|
-
program
|
|
359
|
+
const configCmd = program
|
|
346
360
|
.command('config')
|
|
347
|
-
.description('Gerencia configurações')
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
.
|
|
351
|
-
.
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
361
|
+
.description('Gerencia configurações do NEX CLI')
|
|
362
|
+
|
|
363
|
+
configCmd
|
|
364
|
+
.command('reset')
|
|
365
|
+
.description('Reconfigura o NEX CLI (nome, idiomas, integração Cursor)')
|
|
366
|
+
.action(async () => {
|
|
367
|
+
const { runSetup } = await import('../scripts/postinstall.js')
|
|
368
|
+
await runSetup(true) // Force reconfiguration
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
configCmd
|
|
372
|
+
.command('show')
|
|
373
|
+
.alias('list')
|
|
374
|
+
.description('Mostra a configuração atual')
|
|
375
|
+
.action(async () => {
|
|
376
|
+
const { default: NEXMarketplace } = await import('../src/services/nex-marketplace/NEXMarketplace.js')
|
|
377
|
+
const marketplace = new NEXMarketplace()
|
|
378
|
+
const config = marketplace.getGlobalConfig()
|
|
379
|
+
|
|
380
|
+
console.log(chalk.blue('\n⚙️ Configuração do NEX CLI\n'))
|
|
381
|
+
console.log(chalk.gray('Usuário:'))
|
|
382
|
+
console.log(chalk.white(` Nome: ${config.user.name}`))
|
|
383
|
+
console.log(chalk.white(` Idioma de conversação: ${config.user.conversationLanguage}`))
|
|
384
|
+
console.log(chalk.white(` Idioma de documentos: ${config.user.documentLanguage}`))
|
|
385
|
+
console.log(chalk.gray('\nCursor:'))
|
|
386
|
+
console.log(chalk.white(` Integração: ${config.cursor.enabled ? chalk.green('Habilitada') : chalk.red('Desabilitada')}`))
|
|
387
|
+
|
|
388
|
+
const configPath = marketplace.getGlobalConfigPath()
|
|
389
|
+
console.log(chalk.gray(`\nArquivo: ${configPath}\n`))
|
|
359
390
|
})
|
|
360
391
|
|
|
361
392
|
// Funções auxiliares
|
|
362
|
-
async function createProjectStructure(projectName, template) {
|
|
363
|
-
const projectDir = path.join(process.cwd(), projectName)
|
|
393
|
+
async function createProjectStructure(projectName, template, useCurrentDir = false) {
|
|
394
|
+
const projectDir = useCurrentDir ? process.cwd() : path.join(process.cwd(), projectName)
|
|
364
395
|
await fs.ensureDir(projectDir)
|
|
365
396
|
|
|
366
397
|
// Criar estrutura básica
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -15,7 +15,7 @@ const __filename = fileURLToPath(import.meta.url)
|
|
|
15
15
|
const __dirname = path.dirname(__filename)
|
|
16
16
|
|
|
17
17
|
// Get global config path
|
|
18
|
-
function getGlobalConfigPath() {
|
|
18
|
+
export function getGlobalConfigPath() {
|
|
19
19
|
const homeDir = os.homedir()
|
|
20
20
|
|
|
21
21
|
if (process.platform === 'win32') {
|
|
@@ -27,20 +27,30 @@ function getGlobalConfigPath() {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
async function runSetup() {
|
|
30
|
+
export async function runSetup(force = false) {
|
|
31
31
|
// Check if config already exists
|
|
32
32
|
const configPath = getGlobalConfigPath()
|
|
33
33
|
const configDir = path.dirname(configPath)
|
|
34
34
|
|
|
35
|
-
if (await fs.pathExists(configPath)) {
|
|
35
|
+
if (!force && await fs.pathExists(configPath)) {
|
|
36
36
|
try {
|
|
37
37
|
const existingConfig = await fs.readJSON(configPath)
|
|
38
|
-
// If config exists and is valid,
|
|
38
|
+
// If config exists and is valid, ask if user wants to reconfigure
|
|
39
39
|
if (existingConfig.user && existingConfig.user.name) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
const { overwrite } = await inquirer.prompt([
|
|
41
|
+
{
|
|
42
|
+
type: 'confirm',
|
|
43
|
+
name: 'overwrite',
|
|
44
|
+
message: 'NEX CLI já está configurado. Deseja reconfigurar?',
|
|
45
|
+
default: false
|
|
46
|
+
}
|
|
47
|
+
])
|
|
48
|
+
|
|
49
|
+
if (!overwrite) {
|
|
50
|
+
console.log(chalk.green('\n✅ Configuração mantida.'))
|
|
51
|
+
console.log(chalk.gray(` Config: ${configPath}\n`))
|
|
52
|
+
return
|
|
53
|
+
}
|
|
44
54
|
}
|
|
45
55
|
} catch (error) {
|
|
46
56
|
// Config file exists but is invalid, continue with setup
|
|
@@ -106,7 +116,7 @@ async function runSetup() {
|
|
|
106
116
|
enabled: answers.cursorIntegration
|
|
107
117
|
},
|
|
108
118
|
installedAt: new Date().toISOString(),
|
|
109
|
-
version: '1.0.
|
|
119
|
+
version: '1.0.19'
|
|
110
120
|
}
|
|
111
121
|
|
|
112
122
|
// Save config
|
|
@@ -122,8 +132,16 @@ async function runSetup() {
|
|
|
122
132
|
console.log(chalk.cyan('\n💡 Dica: Para reconfigurar, execute: nex config reset\n'))
|
|
123
133
|
}
|
|
124
134
|
|
|
125
|
-
//
|
|
126
|
-
|
|
135
|
+
// Check if running in interactive mode (TTY available)
|
|
136
|
+
const isInteractive = process.stdin.isTTY && process.stdout.isTTY && process.stderr.isTTY
|
|
137
|
+
const isCI = process.env.CI === 'true'
|
|
138
|
+
const skipSetup = process.env.NEX_SKIP_SETUP === 'true'
|
|
139
|
+
|
|
140
|
+
// Only run interactive setup if:
|
|
141
|
+
// 1. Not in CI
|
|
142
|
+
// 2. Not explicitly skipped
|
|
143
|
+
// 3. Running in interactive mode (TTY)
|
|
144
|
+
if (!isCI && !skipSetup && isInteractive) {
|
|
127
145
|
runSetup().catch((error) => {
|
|
128
146
|
console.error(chalk.red('\n❌ Erro ao configurar NEX CLI:'))
|
|
129
147
|
console.error(chalk.red(error.message))
|
|
@@ -131,12 +149,12 @@ if (process.env.CI !== 'true' && process.env.NEX_SKIP_SETUP !== 'true') {
|
|
|
131
149
|
process.exit(0) // Don't fail the install
|
|
132
150
|
})
|
|
133
151
|
} else {
|
|
134
|
-
//
|
|
152
|
+
// Non-interactive mode: create default config silently
|
|
135
153
|
const configPath = getGlobalConfigPath()
|
|
136
154
|
const configDir = path.dirname(configPath)
|
|
137
155
|
const defaultConfig = {
|
|
138
156
|
user: {
|
|
139
|
-
name: 'Developer',
|
|
157
|
+
name: process.env.USER || process.env.USERNAME || 'Developer',
|
|
140
158
|
conversationLanguage: 'pt-BR',
|
|
141
159
|
documentLanguage: 'pt-BR'
|
|
142
160
|
},
|
|
@@ -144,12 +162,18 @@ if (process.env.CI !== 'true' && process.env.NEX_SKIP_SETUP !== 'true') {
|
|
|
144
162
|
enabled: false
|
|
145
163
|
},
|
|
146
164
|
installedAt: new Date().toISOString(),
|
|
147
|
-
version: '1.0.
|
|
165
|
+
version: '1.0.19'
|
|
148
166
|
}
|
|
149
167
|
|
|
150
168
|
fs.ensureDir(configDir)
|
|
151
169
|
.then(() => fs.writeJSON(configPath, defaultConfig, { spaces: 2 }))
|
|
170
|
+
.then(() => {
|
|
171
|
+
if (!isCI && isInteractive) {
|
|
172
|
+
console.log(chalk.green('\n✅ NEX CLI instalado com configuração padrão'))
|
|
173
|
+
console.log(chalk.gray(' Para configurar: nex config reset\n'))
|
|
174
|
+
}
|
|
175
|
+
})
|
|
152
176
|
.catch(() => {
|
|
153
|
-
// Silently fail in
|
|
177
|
+
// Silently fail in non-interactive mode
|
|
154
178
|
})
|
|
155
179
|
}
|
|
@@ -1087,8 +1087,8 @@ export default class NEXMarketplace {
|
|
|
1087
1087
|
const mainCursorRulesPath = path.join(this.projectRoot, '.cursorrules')
|
|
1088
1088
|
const importLine = `import .cursorrules/${rulesFile}`
|
|
1089
1089
|
const commentLine = `# ${manifest.name} - ${manifest.tagline || manifest.description?.substring(0, 50)}`
|
|
1090
|
-
const
|
|
1091
|
-
const agentComment = `# Use: ${
|
|
1090
|
+
const agentTrigger = manifest.bmad?.activation_trigger || `@${agentId}`
|
|
1091
|
+
const agentComment = `# Use: ${agentTrigger} <command>`
|
|
1092
1092
|
|
|
1093
1093
|
let cursorRulesContent = ''
|
|
1094
1094
|
if (await fs.pathExists(mainCursorRulesPath)) {
|
|
@@ -1112,8 +1112,7 @@ export default class NEXMarketplace {
|
|
|
1112
1112
|
|
|
1113
1113
|
console.log(chalk.green(`\n✅ Cursor integration complete!`))
|
|
1114
1114
|
console.log(chalk.gray(` Added ${rulesFile} to .cursorrules`))
|
|
1115
|
-
|
|
1116
|
-
console.log(chalk.gray(` Use: ${trigger} <command> in Cursor\n`))
|
|
1115
|
+
console.log(chalk.gray(` Use: ${agentTrigger} <command> in Cursor\n`))
|
|
1117
1116
|
|
|
1118
1117
|
} catch (error) {
|
|
1119
1118
|
console.log(chalk.yellow(`\n⚠️ Cursor integration failed: ${error.message}`))
|