@rabts/cli 1.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/cli.js +70 -0
- package/package.json +23 -0
- package/src/agent.js +183 -0
- package/src/config.js +97 -0
- package/src/llm.js +120 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
|
|
9
|
+
import { ensureConfig, configureApiKey } from '../src/config.js';
|
|
10
|
+
import { startInteractiveLoop } from '../src/agent.js';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8'));
|
|
15
|
+
|
|
16
|
+
// Cor primária da marca
|
|
17
|
+
const rabtsColor = chalk.cyan; // Azul claro para padronizar
|
|
18
|
+
|
|
19
|
+
const logo = rabtsColor(`
|
|
20
|
+
%%%%
|
|
21
|
+
%%%%%%%%%%
|
|
22
|
+
%%%%%%%%%%%%%%%%%@
|
|
23
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
24
|
+
%%% %%%%% %%%%%%%%%%%%%%%%%%
|
|
25
|
+
@%%%% %%% %%%%%%%%%%%%%%%%%%
|
|
26
|
+
%%%%%% % %%%%%%%%%%%%%%%%%
|
|
27
|
+
@%%%%%%% %% %%%%%%%%%%%%%%%%%%
|
|
28
|
+
%%%%%%%%%% % %%%%%%%%%%%%%%%%
|
|
29
|
+
%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%
|
|
30
|
+
%%%%%%%%%%%%%%%%% %%%%%%%%%%
|
|
31
|
+
%%%%%%%%%%%%%%%%%% %%% %%%%%%%
|
|
32
|
+
%%%%%%%%%%%%%%%%% %%%%%
|
|
33
|
+
%%%%%%%%%%%%%%%%%% %%%%%%
|
|
34
|
+
%%%%%%%%%%%%%%% %%%%%%%%
|
|
35
|
+
@%%%%%%%%%%%%% %%%%%%%%%
|
|
36
|
+
%%%%%%%%%%% %%%%%%%
|
|
37
|
+
%%%%%%%%%% %%% %%%%%%%
|
|
38
|
+
%%%%%%%@ %%% @%%%%%%
|
|
39
|
+
% %% %%%%%%%
|
|
40
|
+
%%% @%%%%%%
|
|
41
|
+
%%% %%%%%@
|
|
42
|
+
%%%
|
|
43
|
+
`);
|
|
44
|
+
|
|
45
|
+
const program = new Command();
|
|
46
|
+
|
|
47
|
+
program
|
|
48
|
+
.name('rabts')
|
|
49
|
+
.description('Rabts Studio AI CLI')
|
|
50
|
+
.version(packageJson.version)
|
|
51
|
+
.action(async () => {
|
|
52
|
+
console.clear();
|
|
53
|
+
console.log(logo);
|
|
54
|
+
console.log(chalk.gray(`v${packageJson.version} - Seu Agente Inteligente\n`));
|
|
55
|
+
|
|
56
|
+
const config = await ensureConfig();
|
|
57
|
+
await startInteractiveLoop(config);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
program
|
|
61
|
+
.command('config')
|
|
62
|
+
.description('Força a reconfiguração de provedor e chave de API')
|
|
63
|
+
.action(async () => {
|
|
64
|
+
console.clear();
|
|
65
|
+
console.log(logo);
|
|
66
|
+
const config = await configureApiKey();
|
|
67
|
+
await startInteractiveLoop(config);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rabts/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Rabts Studio CLI",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"rabts": "bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node ./bin/cli.js"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@anthropic-ai/sdk": "^0.105.0",
|
|
15
|
+
"@google/genai": "^2.9.0",
|
|
16
|
+
"axios": "^1.7.2",
|
|
17
|
+
"chalk": "^5.3.0",
|
|
18
|
+
"commander": "^12.1.0",
|
|
19
|
+
"dotenv": "^16.4.5",
|
|
20
|
+
"inquirer": "^10.0.0",
|
|
21
|
+
"openai": "^4.52.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/agent.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
import util from 'util';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import { sendMessage } from './llm.js';
|
|
8
|
+
|
|
9
|
+
const execPromise = util.promisify(exec);
|
|
10
|
+
|
|
11
|
+
// Tema Rabts
|
|
12
|
+
const themeColor = chalk.cyan; // Azul claro para padronizar
|
|
13
|
+
const infoColor = chalk.gray;
|
|
14
|
+
|
|
15
|
+
const tools = [
|
|
16
|
+
{
|
|
17
|
+
type: "function",
|
|
18
|
+
function: {
|
|
19
|
+
name: "read_file",
|
|
20
|
+
description: "Lê o conteúdo de um arquivo do sistema local.",
|
|
21
|
+
parameters: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: { filepath: { type: "string" } },
|
|
24
|
+
required: ["filepath"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: "function",
|
|
30
|
+
function: {
|
|
31
|
+
name: "write_file",
|
|
32
|
+
description: "Escreve ou sobrescreve um arquivo no sistema local.",
|
|
33
|
+
parameters: {
|
|
34
|
+
type: "object",
|
|
35
|
+
properties: {
|
|
36
|
+
filepath: { type: "string" },
|
|
37
|
+
content: { type: "string" }
|
|
38
|
+
},
|
|
39
|
+
required: ["filepath", "content"]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
type: "function",
|
|
45
|
+
function: {
|
|
46
|
+
name: "run_command",
|
|
47
|
+
description: "Executa um comando no terminal local.",
|
|
48
|
+
parameters: {
|
|
49
|
+
type: "object",
|
|
50
|
+
properties: { command: { type: "string" } },
|
|
51
|
+
required: ["command"]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
async function executeToolCall(toolCall) {
|
|
58
|
+
const args = JSON.parse(toolCall.function.arguments);
|
|
59
|
+
const cwd = process.cwd();
|
|
60
|
+
|
|
61
|
+
if (toolCall.function.name === 'read_file') {
|
|
62
|
+
try {
|
|
63
|
+
const fullPath = path.resolve(cwd, args.filepath);
|
|
64
|
+
return fs.readFileSync(fullPath, 'utf8');
|
|
65
|
+
} catch (e) {
|
|
66
|
+
return `Erro ao ler arquivo: ${e.message}`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (toolCall.function.name === 'write_file') {
|
|
71
|
+
try {
|
|
72
|
+
const fullPath = path.resolve(cwd, args.filepath);
|
|
73
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
74
|
+
fs.writeFileSync(fullPath, args.content, 'utf8');
|
|
75
|
+
console.log(themeColor(` ↳ Arquivo salvo: `) + chalk.white(args.filepath));
|
|
76
|
+
return `Arquivo salvo em ${fullPath}`;
|
|
77
|
+
} catch (e) {
|
|
78
|
+
return `Erro ao salvar arquivo: ${e.message}`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (toolCall.function.name === 'run_command') {
|
|
83
|
+
const { confirm } = await inquirer.prompt([{
|
|
84
|
+
type: 'confirm',
|
|
85
|
+
name: 'confirm',
|
|
86
|
+
message: chalk.yellow(`Permitir comando: '${args.command}'?`),
|
|
87
|
+
default: false
|
|
88
|
+
}]);
|
|
89
|
+
|
|
90
|
+
if (!confirm) return `Usuário negou o comando: ${args.command}`;
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
console.log(themeColor(` ↳ Executando: `) + chalk.white(args.command));
|
|
94
|
+
const { stdout, stderr } = await execPromise(args.command, { cwd });
|
|
95
|
+
return stdout || stderr || "Sucesso sem output.";
|
|
96
|
+
} catch (e) {
|
|
97
|
+
return `Erro: ${e.message}\nStderr: ${e.stderr || ''}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return "Função desconhecida.";
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function startInteractiveLoop(config) {
|
|
105
|
+
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
|
+
];
|
|
114
|
+
|
|
115
|
+
const supportsTools = (config.provider === 'rabts' || config.provider === 'openai');
|
|
116
|
+
|
|
117
|
+
while (true) {
|
|
118
|
+
const { userPrompt } = await inquirer.prompt([
|
|
119
|
+
{
|
|
120
|
+
type: 'input',
|
|
121
|
+
name: 'userPrompt',
|
|
122
|
+
message: chalk.cyan('❯')
|
|
123
|
+
}
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
if (userPrompt.toLowerCase() === 'sair' || userPrompt.toLowerCase() === 'exit') {
|
|
127
|
+
console.log(infoColor('Até logo!'));
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!userPrompt.trim()) continue;
|
|
132
|
+
|
|
133
|
+
messages.push({ role: 'user', content: userPrompt });
|
|
134
|
+
|
|
135
|
+
let isProcessingTools = true;
|
|
136
|
+
let totalPromptTokens = 0;
|
|
137
|
+
let totalCompletionTokens = 0;
|
|
138
|
+
let startTime = Date.now();
|
|
139
|
+
|
|
140
|
+
while (isProcessingTools) {
|
|
141
|
+
process.stdout.write(infoColor(' Pensando...'));
|
|
142
|
+
|
|
143
|
+
const responseMessage = await sendMessage(config, messages, supportsTools ? tools : null);
|
|
144
|
+
|
|
145
|
+
process.stdout.clearLine(0);
|
|
146
|
+
process.stdout.cursorTo(0);
|
|
147
|
+
|
|
148
|
+
if (responseMessage.usage) {
|
|
149
|
+
totalPromptTokens += responseMessage.usage.prompt_tokens || 0;
|
|
150
|
+
totalCompletionTokens += responseMessage.usage.completion_tokens || 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
messages.push({
|
|
154
|
+
role: responseMessage.role,
|
|
155
|
+
content: responseMessage.content,
|
|
156
|
+
tool_calls: responseMessage.tool_calls
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
|
|
160
|
+
for (const toolCall of responseMessage.tool_calls) {
|
|
161
|
+
console.log(themeColor(` ✦ Usando ferramenta: `) + chalk.white(toolCall.function.name));
|
|
162
|
+
const result = await executeToolCall(toolCall);
|
|
163
|
+
messages.push({
|
|
164
|
+
tool_call_id: toolCall.id,
|
|
165
|
+
role: "tool",
|
|
166
|
+
name: toolCall.function.name,
|
|
167
|
+
content: result,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
const duration = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
172
|
+
|
|
173
|
+
if (responseMessage.content) {
|
|
174
|
+
console.log(themeColor('\nRabts:'));
|
|
175
|
+
console.log(chalk.white(responseMessage.content));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
console.log(infoColor(`\n ↳ Finalizado em ${duration}s • ${totalPromptTokens + totalCompletionTokens} tokens (${totalPromptTokens} in, ${totalCompletionTokens} out)\n`));
|
|
179
|
+
isProcessingTools = false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
package/src/config.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
|
|
7
|
+
const CONFIG_FILE_PATH = path.join(os.homedir(), '.rabts-config.json');
|
|
8
|
+
|
|
9
|
+
const RABTS_DEFAULT_KEY = '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';
|
|
10
|
+
|
|
11
|
+
export function getConfig() {
|
|
12
|
+
if (fs.existsSync(CONFIG_FILE_PATH)) {
|
|
13
|
+
try {
|
|
14
|
+
const data = fs.readFileSync(CONFIG_FILE_PATH, 'utf8');
|
|
15
|
+
return JSON.parse(data);
|
|
16
|
+
} catch (e) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function saveConfig(config) {
|
|
24
|
+
fs.writeFileSync(CONFIG_FILE_PATH, JSON.stringify(config, null, 2));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function ensureConfig() {
|
|
28
|
+
let config = getConfig();
|
|
29
|
+
if (config) {
|
|
30
|
+
return config;
|
|
31
|
+
}
|
|
32
|
+
return await configureApiKey();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function configureApiKey() {
|
|
36
|
+
console.log(chalk.blue('\n=== Bem-vindo ao Rabts Studio CLI ===\n'));
|
|
37
|
+
|
|
38
|
+
const { provider } = await inquirer.prompt([
|
|
39
|
+
{
|
|
40
|
+
type: 'list',
|
|
41
|
+
name: 'provider',
|
|
42
|
+
message: 'Qual provedor de IA você quer usar?',
|
|
43
|
+
choices: ['rabts', 'openai', 'anthropic', 'google']
|
|
44
|
+
}
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
let config = { provider };
|
|
48
|
+
|
|
49
|
+
if (provider === 'rabts') {
|
|
50
|
+
config.apiKey = RABTS_DEFAULT_KEY;
|
|
51
|
+
const { model } = await inquirer.prompt([
|
|
52
|
+
{
|
|
53
|
+
type: 'list',
|
|
54
|
+
name: 'model',
|
|
55
|
+
message: 'Escolha um modelo gratuito do Rabts:',
|
|
56
|
+
choices: [
|
|
57
|
+
'qwen/qwen3-32b',
|
|
58
|
+
'openai/gpt-oss-120b',
|
|
59
|
+
'moonshotai/kimi-k2-instruct',
|
|
60
|
+
'llama-3.1-8b-instant',
|
|
61
|
+
'openai/gpt-oss-20b',
|
|
62
|
+
'meta-llama/llama-4-scout-17b-16e-instruct'
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
]);
|
|
66
|
+
config.model = model;
|
|
67
|
+
console.log(chalk.green('\nConfigurado para usar o Rabts Studio (Modelos Gratuitos).\n'));
|
|
68
|
+
} else {
|
|
69
|
+
const { apiKey } = await inquirer.prompt([
|
|
70
|
+
{
|
|
71
|
+
type: 'input',
|
|
72
|
+
name: 'apiKey',
|
|
73
|
+
message: `Digite a sua chave de API da ${provider}:`
|
|
74
|
+
}
|
|
75
|
+
]);
|
|
76
|
+
config.apiKey = apiKey.trim();
|
|
77
|
+
|
|
78
|
+
let defaultModel = '';
|
|
79
|
+
if (provider === 'openai') defaultModel = 'gpt-4o';
|
|
80
|
+
if (provider === 'anthropic') defaultModel = 'claude-3-5-sonnet-20240620';
|
|
81
|
+
if (provider === 'google') defaultModel = 'gemini-1.5-pro';
|
|
82
|
+
|
|
83
|
+
const { model } = await inquirer.prompt([
|
|
84
|
+
{
|
|
85
|
+
type: 'input',
|
|
86
|
+
name: 'model',
|
|
87
|
+
message: `Digite o modelo desejado (Padrão: ${defaultModel}):`,
|
|
88
|
+
default: defaultModel
|
|
89
|
+
}
|
|
90
|
+
]);
|
|
91
|
+
config.model = model.trim();
|
|
92
|
+
console.log(chalk.green('\nConfiguração salva com sucesso!\n'));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
saveConfig(config);
|
|
96
|
+
return config;
|
|
97
|
+
}
|
package/src/llm.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { GoogleGenAI } from '@google/genai';
|
|
3
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
|
|
6
|
+
const clients = {};
|
|
7
|
+
|
|
8
|
+
export function getClient(config) {
|
|
9
|
+
if (clients[config.provider]) return clients[config.provider];
|
|
10
|
+
|
|
11
|
+
if (config.provider === 'rabts') {
|
|
12
|
+
clients[config.provider] = new OpenAI({
|
|
13
|
+
baseURL: 'https://api.groq.com/openai/v1',
|
|
14
|
+
apiKey: config.apiKey,
|
|
15
|
+
});
|
|
16
|
+
} else if (config.provider === 'openai') {
|
|
17
|
+
clients[config.provider] = new OpenAI({
|
|
18
|
+
apiKey: config.apiKey,
|
|
19
|
+
});
|
|
20
|
+
} else if (config.provider === 'anthropic') {
|
|
21
|
+
clients[config.provider] = new Anthropic({
|
|
22
|
+
apiKey: config.apiKey,
|
|
23
|
+
});
|
|
24
|
+
} else if (config.provider === 'google') {
|
|
25
|
+
clients[config.provider] = new GoogleGenAI({
|
|
26
|
+
apiKey: config.apiKey,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return clients[config.provider];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function sendMessage(config, messages, tools = null) {
|
|
33
|
+
const client = getClient(config);
|
|
34
|
+
let usage = null;
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
if (config.provider === 'rabts' || config.provider === 'openai') {
|
|
38
|
+
const params = {
|
|
39
|
+
model: config.model,
|
|
40
|
+
messages: messages,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
if (tools) {
|
|
44
|
+
params.tools = tools;
|
|
45
|
+
params.tool_choice = "auto";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const response = await client.chat.completions.create(params);
|
|
49
|
+
const msg = response.choices[0].message;
|
|
50
|
+
usage = response.usage;
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
role: msg.role,
|
|
54
|
+
content: msg.content || '',
|
|
55
|
+
tool_calls: msg.tool_calls,
|
|
56
|
+
usage
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
else if (config.provider === 'anthropic') {
|
|
61
|
+
const systemMessage = messages.find(m => m.role === 'system')?.content || '';
|
|
62
|
+
const anthropicMessages = messages.filter(m => m.role !== 'system').map(m => ({
|
|
63
|
+
role: m.role === 'user' ? 'user' : 'assistant',
|
|
64
|
+
content: m.content
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
const response = await client.messages.create({
|
|
68
|
+
model: config.model,
|
|
69
|
+
max_tokens: 4096,
|
|
70
|
+
system: systemMessage,
|
|
71
|
+
messages: anthropicMessages
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
usage = {
|
|
75
|
+
prompt_tokens: response.usage.input_tokens,
|
|
76
|
+
completion_tokens: response.usage.output_tokens,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
role: 'assistant',
|
|
81
|
+
content: response.content[0].text,
|
|
82
|
+
usage
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
else if (config.provider === 'google') {
|
|
87
|
+
const systemMessage = messages.find(m => m.role === 'system')?.content || '';
|
|
88
|
+
const googleMessages = messages.filter(m => m.role !== 'system').map(m => ({
|
|
89
|
+
role: m.role === 'user' ? 'user' : 'model',
|
|
90
|
+
parts: [{ text: m.content }]
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
const response = await client.models.generateContent({
|
|
94
|
+
model: config.model,
|
|
95
|
+
contents: googleMessages,
|
|
96
|
+
config: {
|
|
97
|
+
systemInstruction: systemMessage ? { parts: [{text: systemMessage}]} : undefined
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// GoogleGenAI might have usageMetadata
|
|
102
|
+
if (response.usageMetadata) {
|
|
103
|
+
usage = {
|
|
104
|
+
prompt_tokens: response.usageMetadata.promptTokenCount,
|
|
105
|
+
completion_tokens: response.usageMetadata.candidatesTokenCount,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
role: 'assistant',
|
|
111
|
+
content: response.text,
|
|
112
|
+
usage
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error(chalk.red(`\nErro na comunicação com a API (${config.provider}):`), error.message);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
}
|