@rabts/cli 1.0.0 → 2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rabts/cli",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Rabts Studio CLI",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -18,6 +18,8 @@
18
18
  "commander": "^12.1.0",
19
19
  "dotenv": "^16.4.5",
20
20
  "inquirer": "^10.0.0",
21
+ "marked": "^15.0.12",
22
+ "marked-terminal": "^7.3.0",
21
23
  "openai": "^4.52.0"
22
24
  }
23
25
  }
package/src/agent.js CHANGED
@@ -4,7 +4,14 @@ import { exec } from 'child_process';
4
4
  import util from 'util';
5
5
  import chalk from 'chalk';
6
6
  import inquirer from 'inquirer';
7
+ import { Marked } from 'marked';
8
+ import { markedTerminal } from 'marked-terminal';
7
9
  import { sendMessage } from './llm.js';
10
+ import { loadSessionMemory, saveSessionMemory, clearSessionMemory } from './memory.js';
11
+
12
+ // Setup Markdown Renderer
13
+ const marked = new Marked();
14
+ marked.use(markedTerminal());
8
15
 
9
16
  const execPromise = util.promisify(exec);
10
17
 
@@ -101,16 +108,47 @@ async function executeToolCall(toolCall) {
101
108
  return "Função desconhecida.";
102
109
  }
103
110
 
111
+ function getProjectContext() {
112
+ const cwd = process.cwd();
113
+ let contextStr = `\nContexto do Diretório Atual:\n- Caminho: ${cwd}\n`;
114
+
115
+ try {
116
+ const files = fs.readdirSync(cwd).slice(0, 50); // Limita para não estourar tokens
117
+ contextStr += `- Arquivos na raiz: ${files.join(', ')}\n`;
118
+
119
+ if (fs.existsSync(path.join(cwd, 'package.json'))) {
120
+ const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
121
+ contextStr += `- Projeto Node.js: ${pkg.name || 'Desconhecido'}\n`;
122
+ }
123
+
124
+ if (fs.existsSync(path.join(cwd, 'composer.json'))) {
125
+ const comp = JSON.parse(fs.readFileSync(path.join(cwd, 'composer.json'), 'utf8'));
126
+ contextStr += `- Projeto PHP (Composer): ${comp.name || 'Desconhecido'}\n`;
127
+ }
128
+ } catch (e) {
129
+ // Ignora erros de permissão ou parse
130
+ }
131
+ return contextStr;
132
+ }
133
+
104
134
  export async function startInteractiveLoop(config) {
105
135
  console.log(infoColor(`\nConectado via ${config.provider} (Modelo: ${config.model})`));
106
- console.log(infoColor('Você pode conversar ou pedir para ler/criar arquivos. Digite "sair" para encerrar.\n'));
107
-
108
- let messages = [
109
- {
110
- role: 'system',
111
- content: 'Você é o Rabts AI, um assistente de terminal. Você pode conversar com o usuário ou usar ferramentas para manipular arquivos e comandos quando requisitado.'
112
- }
113
- ];
136
+ console.log(infoColor('Dicas: Digite "sair" para encerrar. Digite "/clear" para limpar a memória desta pasta.\n'));
137
+
138
+ // Carrega memória anterior se existir
139
+ let messages = loadSessionMemory();
140
+ const isNewSession = messages.length === 0;
141
+
142
+ if (isNewSession) {
143
+ let systemContent = 'Você é o Rabts AI, um assistente de terminal inteligente. Responda em Markdown limpo.';
144
+ systemContent += getProjectContext();
145
+
146
+ messages = [
147
+ { role: 'system', content: systemContent }
148
+ ];
149
+ } else {
150
+ console.log(chalk.green('✓ Sessão anterior restaurada para este projeto.\n'));
151
+ }
114
152
 
115
153
  const supportsTools = (config.provider === 'rabts' || config.provider === 'openai');
116
154
 
@@ -123,14 +161,31 @@ export async function startInteractiveLoop(config) {
123
161
  }
124
162
  ]);
125
163
 
126
- if (userPrompt.toLowerCase() === 'sair' || userPrompt.toLowerCase() === 'exit') {
164
+ const input = userPrompt.trim();
165
+
166
+ if (input.toLowerCase() === 'sair' || input.toLowerCase() === 'exit') {
127
167
  console.log(infoColor('Até logo!'));
128
168
  break;
129
169
  }
170
+
171
+ if (input.toLowerCase() === '/clear') {
172
+ clearSessionMemory();
173
+ console.log(chalk.yellow('Memória limpa! O contexto do projeto será reiniciado na próxima mensagem.\n'));
174
+ messages = [];
175
+ continue;
176
+ }
177
+
178
+ if (!input) continue;
130
179
 
131
- if (!userPrompt.trim()) continue;
180
+ // Se a memória foi limpa, recarrega o context inicial
181
+ if (messages.length === 0) {
182
+ messages.push({
183
+ role: 'system',
184
+ content: 'Você é o Rabts AI, um assistente de terminal inteligente.' + getProjectContext()
185
+ });
186
+ }
132
187
 
133
- messages.push({ role: 'user', content: userPrompt });
188
+ messages.push({ role: 'user', content: input });
134
189
 
135
190
  let isProcessingTools = true;
136
191
  let totalPromptTokens = 0;
@@ -172,10 +227,15 @@ export async function startInteractiveLoop(config) {
172
227
 
173
228
  if (responseMessage.content) {
174
229
  console.log(themeColor('\nRabts:'));
175
- console.log(chalk.white(responseMessage.content));
230
+ // Renderiza a resposta visualmente com syntax highlighting
231
+ console.log(marked.parse(responseMessage.content).trim());
176
232
  }
177
233
 
178
234
  console.log(infoColor(`\n ↳ Finalizado em ${duration}s • ${totalPromptTokens + totalCompletionTokens} tokens (${totalPromptTokens} in, ${totalCompletionTokens} out)\n`));
235
+
236
+ // Salva memória a cada interação
237
+ saveSessionMemory(messages);
238
+
179
239
  isProcessingTools = false;
180
240
  }
181
241
  }
package/src/config.js CHANGED
@@ -6,7 +6,7 @@ import chalk from 'chalk';
6
6
 
7
7
  const CONFIG_FILE_PATH = path.join(os.homedir(), '.rabts-config.json');
8
8
 
9
- const RABTS_DEFAULT_KEY = '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';
9
+ // A chave padrão não fica mais no código-fonte por segurança
10
10
 
11
11
  export function getConfig() {
12
12
  if (fs.existsSync(CONFIG_FILE_PATH)) {
@@ -47,7 +47,8 @@ export async function configureApiKey() {
47
47
  let config = { provider };
48
48
 
49
49
  if (provider === 'rabts') {
50
- config.apiKey = RABTS_DEFAULT_KEY;
50
+ // A chave é injetada via proxy no servidor backend
51
+ config.apiKey = 'proxy_mode';
51
52
  const { model } = await inquirer.prompt([
52
53
  {
53
54
  type: 'list',
package/src/llm.js CHANGED
@@ -10,8 +10,8 @@ export function getClient(config) {
10
10
 
11
11
  if (config.provider === 'rabts') {
12
12
  clients[config.provider] = new OpenAI({
13
- baseURL: 'https://api.groq.com/openai/v1',
14
- apiKey: config.apiKey,
13
+ baseURL: 'https://dev.rabts.com/api',
14
+ apiKey: 'proxy_mode',
15
15
  });
16
16
  } else if (config.provider === 'openai') {
17
17
  clients[config.provider] = new OpenAI({
package/src/memory.js ADDED
@@ -0,0 +1,46 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ export function getMemoryPath() {
5
+ const cwd = process.cwd();
6
+ return path.join(cwd, '.rabts', 'session.json');
7
+ }
8
+
9
+ export function loadSessionMemory() {
10
+ const memPath = getMemoryPath();
11
+ if (fs.existsSync(memPath)) {
12
+ try {
13
+ const data = fs.readFileSync(memPath, 'utf8');
14
+ return JSON.parse(data);
15
+ } catch (e) {
16
+ return [];
17
+ }
18
+ }
19
+ return [];
20
+ }
21
+
22
+ export function saveSessionMemory(messages) {
23
+ const memPath = getMemoryPath();
24
+ const dirPath = path.dirname(memPath);
25
+
26
+ if (!fs.existsSync(dirPath)) {
27
+ fs.mkdirSync(dirPath, { recursive: true });
28
+ }
29
+
30
+ // Ocultar a pasta no Windows/Linux de forma simples
31
+ // Adicionar um gitignore para que o usuário não commite acidentalmente o histórico
32
+ const gitignorePath = path.join(dirPath, '.gitignore');
33
+ if (!fs.existsSync(gitignorePath)) {
34
+ fs.writeFileSync(gitignorePath, "*\n");
35
+ }
36
+
37
+ // Filtrar o que salvar (não precisamos salvar todos os resultados longos de tools se não quisermos)
38
+ fs.writeFileSync(memPath, JSON.stringify(messages, null, 2), 'utf8');
39
+ }
40
+
41
+ export function clearSessionMemory() {
42
+ const memPath = getMemoryPath();
43
+ if (fs.existsSync(memPath)) {
44
+ fs.unlinkSync(memPath);
45
+ }
46
+ }