bimmo-cli 2.1.3 → 2.1.4
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/package.json +1 -1
- package/src/interface.js +59 -29
package/package.json
CHANGED
package/src/interface.js
CHANGED
|
@@ -21,12 +21,18 @@ const __dirname = path.dirname(__filename);
|
|
|
21
21
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8'));
|
|
22
22
|
const version = pkg.version;
|
|
23
23
|
|
|
24
|
-
// Configuração do renderizador
|
|
24
|
+
// Configuração do renderizador - Forçamos o escape de HTML para garantir que tags não apareçam
|
|
25
25
|
marked.use(new TerminalRenderer({
|
|
26
26
|
heading: chalk.hex('#c084fc').bold,
|
|
27
27
|
code: chalk.hex('#00ff9d'),
|
|
28
28
|
}));
|
|
29
29
|
|
|
30
|
+
marked.setOptions({
|
|
31
|
+
sanitize: true, // Depreciado mas ajuda em versões antigas
|
|
32
|
+
headerIds: false,
|
|
33
|
+
mangle: false
|
|
34
|
+
});
|
|
35
|
+
|
|
30
36
|
const green = chalk.hex('#00ff9d');
|
|
31
37
|
const lavender = chalk.hex('#c084fc');
|
|
32
38
|
const gray = chalk.gray;
|
|
@@ -98,21 +104,27 @@ function getModeStyle() {
|
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
/**
|
|
101
|
-
* LIMPEZA
|
|
102
|
-
* Remove tags
|
|
107
|
+
* LIMPEZA ABSOLUTA DE HTML
|
|
108
|
+
* Remove tags HTML antes da renderização Markdown.
|
|
103
109
|
*/
|
|
104
110
|
function cleanAIResponse(text) {
|
|
105
111
|
if (!text) return "";
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
.replace(
|
|
109
|
-
.replace(/<\/
|
|
110
|
-
.replace(
|
|
111
|
-
.replace(
|
|
112
|
-
.replace(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
|
|
113
|
+
let cleaned = text
|
|
114
|
+
.replace(/<br\s*\/?>/gi, '\n')
|
|
115
|
+
.replace(/<\/p>/gi, '\n\n')
|
|
116
|
+
.replace(/<\/div>/gi, '\n')
|
|
117
|
+
.replace(/<li>/gi, '* ')
|
|
118
|
+
.replace(/<\/li>/gi, '\n');
|
|
119
|
+
|
|
120
|
+
// Regex extremamente agressiva para remover qualquer tag restante
|
|
121
|
+
cleaned = cleaned.replace(/<[^>]*>?/gm, '');
|
|
122
|
+
|
|
123
|
+
// Decodifica entidades comuns
|
|
124
|
+
const entities = {
|
|
125
|
+
' ': ' ', '<': '<', '>': '>', '&': '&', '"': '"', ''': "'"
|
|
126
|
+
};
|
|
127
|
+
return cleaned.replace(/&[a-z0-9#]+;/gi, (match) => entities[match] || match).trim();
|
|
116
128
|
}
|
|
117
129
|
|
|
118
130
|
export async function startInteractive() {
|
|
@@ -179,13 +191,33 @@ export async function startInteractive() {
|
|
|
179
191
|
const rawInput = input.trim();
|
|
180
192
|
const cmd = rawInput.toLowerCase();
|
|
181
193
|
|
|
182
|
-
|
|
194
|
+
// COMANDOS CLI (Tratados antes de enviar para IA)
|
|
195
|
+
if (cmd === '/exit' || cmd === 'exit' || cmd === 'sair') { process.exit(0); }
|
|
196
|
+
|
|
183
197
|
if (cmd === '/chat') { currentMode = 'chat'; console.log(lavender('✓ Modo CHAT.\n')); continue; }
|
|
184
198
|
if (cmd === '/plan') { currentMode = 'plan'; console.log(yellow('✓ Modo PLAN.\n')); continue; }
|
|
199
|
+
|
|
185
200
|
if (cmd === '/edit') { currentMode = 'edit'; console.log(chalk.red(`⚠️ Modo EDIT ativado.\n`)); continue; }
|
|
186
201
|
if (cmd === '/edit auto') { currentMode = 'edit'; editState.autoAccept = true; console.log(chalk.red('⚠️ Modo EDIT (AUTO) ativado.\n')); continue; }
|
|
187
202
|
if (cmd === '/edit manual') { currentMode = 'edit'; editState.autoAccept = false; console.log(chalk.red('⚠️ Modo EDIT (MANUAL) ativado.\n')); continue; }
|
|
188
203
|
|
|
204
|
+
if (cmd === '/init') {
|
|
205
|
+
const bimmoRcPath = path.join(process.cwd(), '.bimmorc.json');
|
|
206
|
+
if (fs.existsSync(bimmoRcPath)) {
|
|
207
|
+
const { overwrite } = await inquirer.prompt([{ type: 'confirm', name: 'overwrite', message: 'O arquivo .bimmorc.json já existe. Sobrescrever?', default: false }]);
|
|
208
|
+
if (!overwrite) continue;
|
|
209
|
+
}
|
|
210
|
+
const initialConfig = {
|
|
211
|
+
projectName: path.basename(process.cwd()),
|
|
212
|
+
rules: ["Siga as convenções existentes.", "Prefira código modular."],
|
|
213
|
+
ignorePatterns: ["node_modules", ".git"]
|
|
214
|
+
};
|
|
215
|
+
fs.writeFileSync(bimmoRcPath, JSON.stringify(initialConfig, null, 2));
|
|
216
|
+
console.log(green(`\n✅ .bimmorc.json criado com sucesso.\n`));
|
|
217
|
+
resetMessages();
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
|
|
189
221
|
if (cmd.startsWith('/switch ')) {
|
|
190
222
|
const profileName = rawInput.split(' ')[1];
|
|
191
223
|
if (profileName && switchProfile(profileName)) {
|
|
@@ -199,28 +231,22 @@ export async function startInteractive() {
|
|
|
199
231
|
if (cmd.startsWith('/use ')) {
|
|
200
232
|
const agentName = rawInput.split(' ')[1];
|
|
201
233
|
const agents = config.agents || {};
|
|
202
|
-
if (agentName === 'normal' || agentName === 'default') { activePersona = null;
|
|
234
|
+
if (agentName === 'normal' || agentName === 'default') { activePersona = null; resetMessages(); continue; }
|
|
203
235
|
if (agents[agentName]) {
|
|
204
236
|
activePersona = agentName;
|
|
205
237
|
const agent = agents[agentName];
|
|
206
238
|
if (switchProfile(agent.profile)) { config = getConfig(); provider = createProvider(config); }
|
|
207
239
|
currentMode = agent.mode || 'chat';
|
|
208
|
-
console.log(green(`\n✓
|
|
240
|
+
console.log(green(`\n✓ Ativado Agente: ${bold(agentName)}`));
|
|
209
241
|
resetMessages();
|
|
210
|
-
} else { console.log(chalk.red(`\n✖ Agente
|
|
242
|
+
} else { console.log(chalk.red(`\n✖ Agente não encontrado.\n`)); }
|
|
211
243
|
continue;
|
|
212
244
|
}
|
|
213
245
|
|
|
214
|
-
if (cmd === '/clear') { resetMessages(); console.clear();
|
|
246
|
+
if (cmd === '/clear') { resetMessages(); console.clear(); continue; }
|
|
215
247
|
|
|
216
248
|
if (cmd === '/help') {
|
|
217
|
-
console.log(gray(`
|
|
218
|
-
Comandos:
|
|
219
|
-
/chat /plan /edit [auto/manual] → Mudar modo
|
|
220
|
-
/use [agente] | /use normal → Usar Agentes
|
|
221
|
-
/switch [nome] | /model [nome] → Mudar IA/Modelo
|
|
222
|
-
/config | /init | @arquivo → Configurações
|
|
223
|
-
`));
|
|
249
|
+
console.log(gray(`\nComandos:\n /chat | /plan | /edit [auto/manual] | /init\n /switch [nome] | /model [nome] | /use [agente]\n /config | /clear | @arquivo\n`));
|
|
224
250
|
continue;
|
|
225
251
|
}
|
|
226
252
|
|
|
@@ -228,6 +254,7 @@ Comandos:
|
|
|
228
254
|
|
|
229
255
|
if (rawInput === '') continue;
|
|
230
256
|
|
|
257
|
+
// Enviar para a IA
|
|
231
258
|
const controller = new AbortController();
|
|
232
259
|
const localInterruptHandler = () => controller.abort();
|
|
233
260
|
process.removeListener('SIGINT', globalSigIntHandler);
|
|
@@ -246,18 +273,21 @@ Comandos:
|
|
|
246
273
|
let responseText = await provider.sendMessage(messages, { signal: controller.signal });
|
|
247
274
|
spinner.stop();
|
|
248
275
|
|
|
249
|
-
// EXECUTA LIMPEZA BRUTA
|
|
250
276
|
const cleanedText = cleanAIResponse(responseText);
|
|
251
|
-
|
|
252
277
|
messages.push({ role: 'assistant', content: responseText });
|
|
278
|
+
|
|
253
279
|
console.log('\n' + lavender('bimmo ') + getModeStyle());
|
|
254
280
|
console.log(lavender('─'.repeat(50)));
|
|
255
281
|
console.log(marked(cleanedText));
|
|
256
282
|
console.log(gray('─'.repeat(50)) + '\n');
|
|
257
283
|
} catch (err) {
|
|
258
284
|
spinner.stop();
|
|
259
|
-
if (controller.signal.aborted || err.name === 'AbortError') {
|
|
260
|
-
|
|
285
|
+
if (controller.signal.aborted || err.name === 'AbortError') {
|
|
286
|
+
console.log(yellow('\n⚠️ Interrompido.\n'));
|
|
287
|
+
messages.pop();
|
|
288
|
+
} else {
|
|
289
|
+
console.error(chalk.red('\n✖ Erro:') + ' ' + err.message + '\n');
|
|
290
|
+
}
|
|
261
291
|
} finally {
|
|
262
292
|
process.removeListener('SIGINT', localInterruptHandler);
|
|
263
293
|
process.on('SIGINT', globalSigIntHandler);
|