bimmo-cli 3.2.0 → 4.0.0
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/bin/bimmo +1 -3
- package/package.json +3 -21
- package/src/{interface.jsx → interface.js} +65 -75
package/bin/bimmo
CHANGED
|
@@ -4,14 +4,12 @@
|
|
|
4
4
|
process.removeAllListeners('warning');
|
|
5
5
|
|
|
6
6
|
import { program } from 'commander';
|
|
7
|
+
import { startInteractive } from '../src/interface.js';
|
|
7
8
|
import { configure } from '../src/config.js';
|
|
8
9
|
import fs from 'fs';
|
|
9
10
|
import path from 'path';
|
|
10
11
|
import { fileURLToPath } from 'url';
|
|
11
12
|
|
|
12
|
-
// Importa a interface compilada em dist/
|
|
13
|
-
import { startInteractive } from '../dist/interface.js';
|
|
14
|
-
|
|
15
13
|
const __filename = fileURLToPath(import.meta.url);
|
|
16
14
|
const __dirname = path.dirname(__filename);
|
|
17
15
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8'));
|
package/package.json
CHANGED
|
@@ -1,25 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bimmo-cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "🌿 Plataforma de IA universal profissional com interface React (Ink)
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "esbuild src/interface.jsx --bundle --platform=node --format=esm --outfile=dist/interface.js --packages=external"
|
|
7
|
-
},
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"description": "🌿 Plataforma de IA universal profissional com interface React (Ink) pura.",
|
|
8
5
|
"bin": {
|
|
9
6
|
"bimmo": "bin/bimmo"
|
|
10
7
|
},
|
|
11
8
|
"type": "module",
|
|
12
9
|
"keywords": [
|
|
13
|
-
"ai",
|
|
14
|
-
"cli",
|
|
15
|
-
"ink",
|
|
16
|
-
"react",
|
|
17
|
-
"openai",
|
|
18
|
-
"anthropic",
|
|
19
|
-
"gemini",
|
|
20
|
-
"agent",
|
|
21
|
-
"swarm",
|
|
22
|
-
"terminal"
|
|
10
|
+
"ai", "cli", "ink", "react", "openai", "anthropic", "gemini", "agent", "swarm", "terminal"
|
|
23
11
|
],
|
|
24
12
|
"author": "Judah",
|
|
25
13
|
"license": "MIT",
|
|
@@ -51,7 +39,6 @@
|
|
|
51
39
|
"ink-spinner": "^5.0.0",
|
|
52
40
|
"ink-text-input": "^6.0.0",
|
|
53
41
|
"inquirer": "^9.3.8",
|
|
54
|
-
"jiti": "^2.6.1",
|
|
55
42
|
"marked": "^14.0.0",
|
|
56
43
|
"marked-terminal": "^7.0.0",
|
|
57
44
|
"mime-types": "^2.1.35",
|
|
@@ -59,11 +46,6 @@
|
|
|
59
46
|
"openai": "^4.82.0",
|
|
60
47
|
"ora": "^8.1.1",
|
|
61
48
|
"react": "^18.2.0",
|
|
62
|
-
"tsx": "^4.19.2",
|
|
63
49
|
"zod": "^3.24.1"
|
|
64
|
-
},
|
|
65
|
-
"devDependencies": {
|
|
66
|
-
"esbuild": "^0.27.4",
|
|
67
|
-
"tsx": "^4.21.0"
|
|
68
50
|
}
|
|
69
51
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect, useMemo
|
|
1
|
+
import React, { useState, useEffect, useMemo } from 'react';
|
|
2
2
|
import { render, Box, Text, useInput, useApp } from 'ink';
|
|
3
3
|
import TextInput from 'ink-text-input';
|
|
4
4
|
import Spinner from 'ink-spinner';
|
|
@@ -16,7 +16,6 @@ import { getProjectContext } from './project-context.js';
|
|
|
16
16
|
import { editState } from './agent.js';
|
|
17
17
|
import { SwarmOrchestrator } from './orchestrator.js';
|
|
18
18
|
|
|
19
|
-
// --- CONFIGURAÇÃO VISUAL ---
|
|
20
19
|
const green = '#00ff9d';
|
|
21
20
|
const lavender = '#c084fc';
|
|
22
21
|
const gray = '#6272a4';
|
|
@@ -37,63 +36,63 @@ const __dirname = path.dirname(__filename);
|
|
|
37
36
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf-8'));
|
|
38
37
|
const version = pkg.version;
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
const h = React.createElement;
|
|
41
40
|
|
|
42
41
|
const Header = ({ config }) => (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
h(Box, { flexDirection: 'column', marginBottom: 1 },
|
|
43
|
+
h(Text, { color: lavender }, figlet.textSync('bimmo')),
|
|
44
|
+
h(Box, { borderStyle: 'single', borderColor: lavender, paddingX: 1, justifyContent: 'space-between' },
|
|
45
|
+
h(Text, { color: green, bold: true }, `v${version}`),
|
|
46
|
+
h(Box, null,
|
|
47
|
+
h(Text, { color: gray }, `${config.activeProfile || 'Default'} `),
|
|
48
|
+
h(Text, { color: lavender }, '•'),
|
|
49
|
+
h(Text, { color: gray }, ` ${config.model}`)
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
)
|
|
54
53
|
);
|
|
55
54
|
|
|
56
55
|
const MessageList = ({ messages }) => (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
h(Box, { flexDirection: 'column', flexGrow: 1 },
|
|
57
|
+
messages.filter(m => m.role !== 'system').slice(-10).map((m, i) => (
|
|
58
|
+
h(Box, { key: i, flexDirection: 'column', marginBottom: 1 },
|
|
59
|
+
h(Box, null,
|
|
60
|
+
h(Text, { bold: true, color: m.role === 'user' ? green : lavender },
|
|
61
|
+
m.role === 'user' ? '› Você' : '› bimmo'
|
|
62
|
+
),
|
|
63
|
+
m.role === 'system' && h(Text, { color: yellow }, ' [SISTEMA]')
|
|
64
|
+
),
|
|
65
|
+
h(Box, { paddingLeft: 2 },
|
|
66
|
+
h(Text, null,
|
|
67
|
+
m.role === 'assistant'
|
|
69
68
|
? marked.parse(m.content).trim()
|
|
70
|
-
: (m.displayContent || m.content)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
))
|
|
75
|
-
|
|
69
|
+
: (m.displayContent || m.content)
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
))
|
|
74
|
+
)
|
|
76
75
|
);
|
|
77
76
|
|
|
78
77
|
const Autocomplete = ({ suggestions }) => (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
{f.isDir ? '📁' : '📄'} {f.rel}{f.isDir ? '/' : ''}
|
|
84
|
-
|
|
85
|
-
))
|
|
86
|
-
|
|
78
|
+
h(Box, { flexDirection: 'column', borderStyle: 'round', borderColor: gray, paddingX: 1, marginBottom: 1 },
|
|
79
|
+
h(Text, { color: gray, dimColor: true, italic: true }, 'Sugestões (TAB para completar):'),
|
|
80
|
+
suggestions.map((f, i) => (
|
|
81
|
+
h(Text, { key: i, color: i === 0 ? green : gray },
|
|
82
|
+
`${f.isDir ? '📁' : '📄'} ${f.rel}${f.isDir ? '/' : ''}`
|
|
83
|
+
)
|
|
84
|
+
))
|
|
85
|
+
)
|
|
87
86
|
);
|
|
88
87
|
|
|
89
88
|
const Footer = ({ exitCounter }) => (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
h(Box, { marginTop: 1, justifyContent: 'space-between', paddingX: 1 },
|
|
90
|
+
h(Text, { color: gray, dimColor: true }, `📁 ${path.relative(process.env.HOME || '', process.cwd())}`),
|
|
91
|
+
exitCounter === 1 && h(Text, { color: yellow, bold: true }, ' Pressione Ctrl+C novamente para sair'),
|
|
92
|
+
h(Box, null,
|
|
93
|
+
h(Text, { color: gray, dimColor: true, italic: true }, '↑↓ para histórico • /help para comandos')
|
|
94
|
+
)
|
|
95
|
+
)
|
|
97
96
|
);
|
|
98
97
|
|
|
99
98
|
const BimmoApp = ({ initialConfig }) => {
|
|
@@ -108,7 +107,6 @@ const BimmoApp = ({ initialConfig }) => {
|
|
|
108
107
|
const [exitCounter, setExitCounter] = useState(0);
|
|
109
108
|
const [provider, setProvider] = useState(() => createProvider(initialConfig));
|
|
110
109
|
|
|
111
|
-
// Inicializa contexto
|
|
112
110
|
useEffect(() => {
|
|
113
111
|
const ctx = getProjectContext();
|
|
114
112
|
setMessages([
|
|
@@ -146,7 +144,6 @@ const BimmoApp = ({ initialConfig }) => {
|
|
|
146
144
|
const parts = rawInput.split(' ');
|
|
147
145
|
const cmd = parts[0].toLowerCase();
|
|
148
146
|
|
|
149
|
-
// Comandos de Sistema
|
|
150
147
|
if (cmd === '/exit') exit();
|
|
151
148
|
if (cmd === '/clear') {
|
|
152
149
|
setMessages([{ role: 'system', content: getProjectContext() }, { role: 'assistant', content: 'Chat limpo.' }]);
|
|
@@ -215,7 +212,6 @@ const BimmoApp = ({ initialConfig }) => {
|
|
|
215
212
|
return;
|
|
216
213
|
}
|
|
217
214
|
|
|
218
|
-
// Processamento de arquivos @
|
|
219
215
|
setIsThinking(true);
|
|
220
216
|
let processedInput = rawInput;
|
|
221
217
|
const fileMatches = rawInput.match(/@[\w\.\-\/]+/g);
|
|
@@ -266,30 +262,24 @@ const BimmoApp = ({ initialConfig }) => {
|
|
|
266
262
|
});
|
|
267
263
|
|
|
268
264
|
return (
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
</Text>
|
|
288
|
-
<TextInput value={input} onChange={setInput} onSubmit={handleSubmit} placeholder="Como posso ajudar hoje?" />
|
|
289
|
-
</Box>
|
|
290
|
-
|
|
291
|
-
<Footer exitCounter={exitCounter} />
|
|
292
|
-
</Box>
|
|
265
|
+
h(Box, { flexDirection: 'column', paddingX: 1, minHeight: 10 },
|
|
266
|
+
h(Header, { config }),
|
|
267
|
+
h(MessageList, { messages }),
|
|
268
|
+
isThinking && h(Box, { marginBottom: 1 },
|
|
269
|
+
h(Text, { color: lavender },
|
|
270
|
+
h(Spinner, { type: 'dots' }),
|
|
271
|
+
h(Text, { italic: true }, ` ${thinkingMessage}`)
|
|
272
|
+
)
|
|
273
|
+
),
|
|
274
|
+
filePreview.length > 0 && h(Autocomplete, { suggestions: filePreview }),
|
|
275
|
+
h(Box, { borderStyle: 'round', borderColor: isThinking ? gray : lavender, paddingX: 1 },
|
|
276
|
+
h(Text, { bold: true, color: mode === 'edit' ? red : mode === 'plan' ? cyan : lavender },
|
|
277
|
+
`${activePersona ? `[${activePersona.toUpperCase()}] ` : ''}[${mode.toUpperCase()}] › `
|
|
278
|
+
),
|
|
279
|
+
h(TextInput, { value: input, onChange: setInput, onSubmit: handleSubmit, placeholder: 'Como posso ajudar hoje?' })
|
|
280
|
+
),
|
|
281
|
+
h(Footer, { exitCounter })
|
|
282
|
+
)
|
|
293
283
|
);
|
|
294
284
|
};
|
|
295
285
|
|
|
@@ -300,5 +290,5 @@ export async function startInteractive() {
|
|
|
300
290
|
process.exit(0);
|
|
301
291
|
}
|
|
302
292
|
process.stdout.write('\x1Bc');
|
|
303
|
-
render(
|
|
293
|
+
render(h(BimmoApp, { initialConfig: config }));
|
|
304
294
|
}
|