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 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": "3.2.0",
4
- "description": "🌿 Plataforma de IA universal profissional com interface React (Ink). Agentes, Swarms, Autocomplete real-time e Contexto Inteligente.",
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, useRef } from 'react';
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
- // --- COMPONENTES ---
39
+ const h = React.createElement;
41
40
 
42
41
  const Header = ({ config }) => (
43
- <Box flexDirection="column" marginBottom={1}>
44
- <Text color={lavender}>{figlet.textSync('bimmo')}</Text>
45
- <Box borderStyle="single" borderColor={lavender} paddingX={1} justifyContent="space-between">
46
- <Text color={green} bold>v{version}</Text>
47
- <Box>
48
- <Text color={gray}>{config.activeProfile || 'Default'} </Text>
49
- <Text color={lavender}>•</Text>
50
- <Text color={gray}> {config.model}</Text>
51
- </Box>
52
- </Box>
53
- </Box>
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
- <Box flexDirection="column" flexGrow={1}>
58
- {messages.filter(m => m.role !== 'system').slice(-10).map((m, i) => (
59
- <Box key={i} flexDirection="column" marginBottom={1}>
60
- <Box>
61
- <Text bold color={m.role === 'user' ? green : lavender}>
62
- {m.role === 'user' ? '› Você' : '› bimmo'}
63
- </Text>
64
- {m.role === 'system' && <Text color={yellow}> [SISTEMA]</Text>}
65
- </Box>
66
- <Box paddingLeft={2}>
67
- <Text>
68
- {m.role === 'assistant'
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
- </Text>
72
- </Box>
73
- </Box>
74
- ))}
75
- </Box>
69
+ : (m.displayContent || m.content)
70
+ )
71
+ )
72
+ )
73
+ ))
74
+ )
76
75
  );
77
76
 
78
77
  const Autocomplete = ({ suggestions }) => (
79
- <Box flexDirection="column" borderStyle="round" borderColor={gray} paddingX={1} marginBottom={1}>
80
- <Text color={gray} dimColor italic>Sugestões (TAB para completar):</Text>
81
- {suggestions.map((f, i) => (
82
- <Text key={i} color={i === 0 ? green : gray}>
83
- {f.isDir ? '📁' : '📄'} {f.rel}{f.isDir ? '/' : ''}
84
- </Text>
85
- ))}
86
- </Box>
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
- <Box marginTop={1} justifyContent="space-between" paddingX={1}>
91
- <Text color={gray} dimColor>📁 {path.relative(process.env.HOME || '', process.cwd())}</Text>
92
- {exitCounter === 1 && <Text color={yellow} bold> Pressione Ctrl+C novamente para sair</Text>}
93
- <Box>
94
- <Text color={gray} dimColor italic>↑↓ para histórico • /help para comandos</Text>
95
- </Box>
96
- </Box>
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
- <Box flexDirection="column" paddingX={1} minHeight={10}>
270
- <Header config={config} />
271
- <MessageList messages={messages} />
272
-
273
- {isThinking && (
274
- <Box marginBottom={1}>
275
- <Text color={lavender}>
276
- <Spinner type="dots" /> <Text italic>{thinkingMessage}</Text>
277
- </Text>
278
- </Box>
279
- )}
280
-
281
- {filePreview.length > 0 && <Autocomplete suggestions={filePreview} />}
282
-
283
- <Box borderStyle="round" borderColor={isThinking ? gray : lavender} paddingX={1}>
284
- <Text bold color={mode === 'edit' ? red : mode === 'plan' ? cyan : lavender}>
285
- {activePersona ? `[${activePersona.toUpperCase()}] ` : ''}
286
- [{mode.toUpperCase()}] ›{' '}
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(<BimmoApp initialConfig={config} />);
293
+ render(h(BimmoApp, { initialConfig: config }));
304
294
  }