plazbot-cli 0.1.2 → 0.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/.claude/settings.local.json +14 -0
- package/CLAUDE.md +92 -0
- package/README.md +102 -0
- package/dist/cli.js +14 -5
- package/dist/commands/agent/ai-config.js +107 -0
- package/dist/commands/agent/chat.js +130 -34
- package/dist/commands/agent/copy.js +37 -0
- package/dist/commands/agent/create.js +80 -17
- package/dist/commands/agent/files.js +142 -0
- package/dist/commands/agent/index.js +14 -2
- package/dist/commands/agent/set.js +127 -0
- package/dist/commands/agent/templates.js +240 -0
- package/dist/commands/agent/tools.js +161 -0
- package/dist/commands/agent/wizard.js +369 -0
- package/dist/commands/whatsapp/broadcast.js +97 -0
- package/dist/commands/whatsapp/channels.js +86 -0
- package/dist/commands/whatsapp/chat.js +74 -0
- package/dist/commands/whatsapp/index.js +11 -2
- package/dist/commands/whatsapp/send-template.js +51 -14
- package/dist/commands/whatsapp/send.js +10 -10
- package/dist/commands/whatsapp/widget.js +64 -0
- package/dist/utils/banner.js +87 -0
- package/dist/utils/logger.js +27 -6
- package/dist/utils/ui.js +111 -0
- package/package.json +10 -2
- package/src/cli.ts +13 -5
- package/src/commands/agent/ai-config.ts +112 -0
- package/src/commands/agent/chat.ts +149 -40
- package/src/commands/agent/copy.ts +40 -0
- package/src/commands/agent/create.ts +58 -23
- package/src/commands/agent/files.ts +158 -0
- package/src/commands/agent/index.ts +14 -2
- package/src/commands/agent/set.ts +137 -0
- package/src/commands/agent/templates.ts +249 -0
- package/src/commands/agent/tools.ts +167 -0
- package/src/commands/agent/wizard.ts +475 -0
- package/src/commands/whatsapp/broadcast.ts +100 -0
- package/src/commands/whatsapp/channels.ts +98 -0
- package/src/commands/whatsapp/chat.ts +77 -0
- package/src/commands/whatsapp/index.ts +11 -2
- package/src/commands/whatsapp/send-template.ts +57 -19
- package/src/commands/whatsapp/send.ts +15 -14
- package/src/commands/whatsapp/widget.ts +67 -0
- package/src/utils/banner.ts +94 -0
- package/src/utils/logger.ts +26 -7
- package/src/utils/ui.ts +109 -0
- package/dist/commands/message/delete-webhook.js +0 -39
- package/dist/commands/message/index.js +0 -14
- package/dist/commands/message/register-webhook.js +0 -42
- package/dist/commands/message/send-template.js +0 -42
- package/dist/commands/message/send.js +0 -42
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.toolsCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const plazbot_1 = require("plazbot");
|
|
9
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
+
const credentials_1 = require("../../utils/credentials");
|
|
11
|
+
const logger_1 = require("../../utils/logger");
|
|
12
|
+
const ui_1 = require("../../utils/ui");
|
|
13
|
+
exports.toolsCommand = new commander_1.Command('tools')
|
|
14
|
+
.description('Gestionar herramientas de Tool Calling del agente')
|
|
15
|
+
.argument('<agentId>', 'ID del agente')
|
|
16
|
+
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
17
|
+
.action(async (agentId, options) => {
|
|
18
|
+
try {
|
|
19
|
+
const credentials = await (0, credentials_1.getStoredCredentials)();
|
|
20
|
+
const agent = new plazbot_1.Agent({
|
|
21
|
+
workspaceId: credentials.workspace,
|
|
22
|
+
apiKey: credentials.apiKey,
|
|
23
|
+
zone: credentials.zone,
|
|
24
|
+
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
25
|
+
});
|
|
26
|
+
const spinner = (0, ui_1.createSpinner)('Cargando agente...');
|
|
27
|
+
spinner.start();
|
|
28
|
+
const agentData = await agent.getAgentById({ id: agentId });
|
|
29
|
+
spinner.stop();
|
|
30
|
+
console.log((0, ui_1.section)('Tool Calling - ' + (agentData.name || agentId)));
|
|
31
|
+
console.log((0, ui_1.kvPair)('Estado', agentData.useToolCalling ? ui_1.theme.success('Activado') : ui_1.theme.error('Desactivado')));
|
|
32
|
+
// Servicios
|
|
33
|
+
const services = agentData.services || [];
|
|
34
|
+
if (services.length > 0) {
|
|
35
|
+
console.log((0, ui_1.section)('Servicios (API calls)'));
|
|
36
|
+
const rows = services.map((s) => [
|
|
37
|
+
s.intent,
|
|
38
|
+
s.method || 'POST',
|
|
39
|
+
s.endpoint ? s.endpoint.substring(0, 40) + '...' : 'N/A',
|
|
40
|
+
(0, ui_1.statusBadge)(s.enabled !== false),
|
|
41
|
+
]);
|
|
42
|
+
console.log((0, ui_1.createTable)(['Intent', 'Method', 'Endpoint', 'Estado'], rows));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.log(ui_1.theme.muted('\n No hay servicios configurados'));
|
|
46
|
+
}
|
|
47
|
+
// Acciones
|
|
48
|
+
const actions = agentData.actions || [];
|
|
49
|
+
if (actions.length > 0) {
|
|
50
|
+
console.log((0, ui_1.section)('Acciones'));
|
|
51
|
+
const rows = actions.map((a) => [
|
|
52
|
+
a.intent,
|
|
53
|
+
(a.action || []).map((ac) => ac.type).join(', '),
|
|
54
|
+
(0, ui_1.statusBadge)(a.enabled !== false),
|
|
55
|
+
]);
|
|
56
|
+
console.log((0, ui_1.createTable)(['Intent', 'Tipo', 'Estado'], rows));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log(ui_1.theme.muted('\n No hay acciones configuradas'));
|
|
60
|
+
}
|
|
61
|
+
// Menu de opciones
|
|
62
|
+
console.log();
|
|
63
|
+
const { action } = await inquirer_1.default.prompt([{
|
|
64
|
+
type: 'list',
|
|
65
|
+
name: 'action',
|
|
66
|
+
message: 'Que deseas hacer?',
|
|
67
|
+
choices: [
|
|
68
|
+
{ name: 'Agregar servicio (API call)', value: 'add-service' },
|
|
69
|
+
{ name: 'Agregar accion', value: 'add-action' },
|
|
70
|
+
{ name: agentData.useToolCalling ? 'Desactivar Tool Calling' : 'Activar Tool Calling', value: 'toggle' },
|
|
71
|
+
{ name: 'Salir', value: 'exit' },
|
|
72
|
+
],
|
|
73
|
+
}]);
|
|
74
|
+
if (action === 'exit')
|
|
75
|
+
return;
|
|
76
|
+
if (action === 'toggle') {
|
|
77
|
+
const toggleSpinner = (0, ui_1.createSpinner)('Actualizando...');
|
|
78
|
+
toggleSpinner.start();
|
|
79
|
+
const updatedConfig = { ...agentData, useToolCalling: !agentData.useToolCalling };
|
|
80
|
+
delete updatedConfig.id;
|
|
81
|
+
delete updatedConfig._id;
|
|
82
|
+
await agent.updateAgent(agentId, updatedConfig);
|
|
83
|
+
toggleSpinner.succeed(`Tool Calling ${!agentData.useToolCalling ? 'activado' : 'desactivado'}`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (action === 'add-service') {
|
|
87
|
+
const svc = await inquirer_1.default.prompt([
|
|
88
|
+
{ type: 'input', name: 'intent', message: 'Nombre/intent del servicio:', validate: (v) => v.length > 0 || 'Requerido' },
|
|
89
|
+
{ type: 'input', name: 'reference', message: 'Palabras clave:', default: '' },
|
|
90
|
+
{ type: 'list', name: 'method', message: 'Metodo HTTP:', choices: ['GET', 'POST'] },
|
|
91
|
+
{ type: 'input', name: 'endpoint', message: 'URL del endpoint:', validate: (v) => v.length > 0 || 'Requerido' },
|
|
92
|
+
{ type: 'input', name: 'responseMessage', message: 'Mensaje de respuesta:', default: '' },
|
|
93
|
+
]);
|
|
94
|
+
const newService = {
|
|
95
|
+
intent: svc.intent,
|
|
96
|
+
reference: svc.reference,
|
|
97
|
+
enabled: true,
|
|
98
|
+
method: svc.method,
|
|
99
|
+
endpoint: svc.endpoint,
|
|
100
|
+
requiredFields: [],
|
|
101
|
+
headers: {},
|
|
102
|
+
bodyTemplate: {},
|
|
103
|
+
responseMapping: {},
|
|
104
|
+
responseMessage: svc.responseMessage,
|
|
105
|
+
responseConditions: [],
|
|
106
|
+
};
|
|
107
|
+
const updatedServices = [...services, newService];
|
|
108
|
+
const updatedConfig = { ...agentData, services: updatedServices, useToolCalling: true };
|
|
109
|
+
delete updatedConfig.id;
|
|
110
|
+
delete updatedConfig._id;
|
|
111
|
+
const updateSpinner = (0, ui_1.createSpinner)('Guardando servicio...');
|
|
112
|
+
updateSpinner.start();
|
|
113
|
+
await agent.updateAgent(agentId, updatedConfig);
|
|
114
|
+
updateSpinner.succeed(`Servicio "${svc.intent}" agregado`);
|
|
115
|
+
}
|
|
116
|
+
if (action === 'add-action') {
|
|
117
|
+
const act = await inquirer_1.default.prompt([
|
|
118
|
+
{ type: 'input', name: 'intent', message: 'Nombre/intent de la accion:', validate: (v) => v.length > 0 || 'Requerido' },
|
|
119
|
+
{ type: 'input', name: 'reference', message: 'Palabras clave:', default: '' },
|
|
120
|
+
{
|
|
121
|
+
type: 'list', name: 'actionType', message: 'Tipo de accion:',
|
|
122
|
+
choices: [
|
|
123
|
+
{ name: 'Agendar evento', value: 'action.event.add' },
|
|
124
|
+
{ name: 'Actualizar evento (reagendar)', value: 'action.event.update' },
|
|
125
|
+
{ name: 'Listar eventos', value: 'action.event.list' },
|
|
126
|
+
{ name: 'Eliminar evento (cancelar)', value: 'action.event.delete' },
|
|
127
|
+
{ name: 'Agregar tag', value: 'action.tag' },
|
|
128
|
+
{ name: 'Cambiar stage', value: 'action.stage' },
|
|
129
|
+
{ name: 'Derivar a agente humano', value: 'action.agentShutDown' },
|
|
130
|
+
{ name: 'Marcar como resuelto', value: 'action.solved' },
|
|
131
|
+
{ name: 'Asignar agente', value: 'action.asign' },
|
|
132
|
+
{ name: 'Segmentacion', value: 'action.segmentation' },
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
{ type: 'input', name: 'actionValue', message: 'Valor (opcional):', default: '' },
|
|
136
|
+
{ type: 'input', name: 'responseMessage', message: 'Mensaje de respuesta:', default: '' },
|
|
137
|
+
]);
|
|
138
|
+
const newAction = {
|
|
139
|
+
intent: act.intent,
|
|
140
|
+
reference: act.reference,
|
|
141
|
+
enabled: true,
|
|
142
|
+
requiredFields: [],
|
|
143
|
+
responseMessage: act.responseMessage,
|
|
144
|
+
action: [{ type: act.actionType, value: act.actionValue }],
|
|
145
|
+
};
|
|
146
|
+
const updatedActions = [...actions, newAction];
|
|
147
|
+
const updatedConfig = { ...agentData, actions: updatedActions, useToolCalling: true };
|
|
148
|
+
delete updatedConfig.id;
|
|
149
|
+
delete updatedConfig._id;
|
|
150
|
+
const updateSpinner = (0, ui_1.createSpinner)('Guardando accion...');
|
|
151
|
+
updateSpinner.start();
|
|
152
|
+
await agent.updateAgent(agentId, updatedConfig);
|
|
153
|
+
updateSpinner.succeed(`Accion "${act.intent}" agregada`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
const message = error instanceof Error ? error.message : 'Error desconocido';
|
|
158
|
+
logger_1.logger.error(message);
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runAgentWizard = runAgentWizard;
|
|
7
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
|
+
const ui_1 = require("../../utils/ui");
|
|
9
|
+
const MODELS = {
|
|
10
|
+
openai: ['gpt-4o', 'gpt-4', 'gpt-3.5-turbo', 'o1-preview', 'o1-mini'],
|
|
11
|
+
claude: ['claude-3-5-sonnet-20241022', 'claude-3-opus-20240229', 'claude-3-haiku-20240307'],
|
|
12
|
+
gemini: ['gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash'],
|
|
13
|
+
};
|
|
14
|
+
const COLORS = ['blue', 'green', 'orange', 'gray', 'white'];
|
|
15
|
+
async function runAgentWizard(zone) {
|
|
16
|
+
console.log((0, ui_1.section)('Crear nuevo agente de IA'));
|
|
17
|
+
console.log(ui_1.theme.muted(' Responde las siguientes preguntas para configurar tu agente.\n'));
|
|
18
|
+
// Paso 1: Informacion basica
|
|
19
|
+
console.log(ui_1.theme.bold('\n Paso 1/8: Informacion basica'));
|
|
20
|
+
const basic = await inquirer_1.default.prompt([
|
|
21
|
+
{
|
|
22
|
+
type: 'input',
|
|
23
|
+
name: 'name',
|
|
24
|
+
message: 'Nombre del agente:',
|
|
25
|
+
validate: (v) => v.length > 0 || 'El nombre es requerido',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: 'input',
|
|
29
|
+
name: 'description',
|
|
30
|
+
message: 'Descripcion breve:',
|
|
31
|
+
default: '',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
type: 'input',
|
|
35
|
+
name: 'prompt',
|
|
36
|
+
message: 'Prompt del sistema (instrucciones principales):',
|
|
37
|
+
default: 'Eres un asistente virtual amigable y profesional.',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
type: 'number',
|
|
41
|
+
name: 'buffer',
|
|
42
|
+
message: 'Buffer de conversacion (3-20 mensajes):',
|
|
43
|
+
default: 5,
|
|
44
|
+
validate: (v) => (v >= 3 && v <= 20) || 'Debe ser entre 3 y 20',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: 'list',
|
|
48
|
+
name: 'color',
|
|
49
|
+
message: 'Color del agente:',
|
|
50
|
+
choices: COLORS,
|
|
51
|
+
default: 'blue',
|
|
52
|
+
},
|
|
53
|
+
]);
|
|
54
|
+
// Paso 2: Personalidad
|
|
55
|
+
console.log(ui_1.theme.bold('\n Paso 2/8: Personalidad e instrucciones'));
|
|
56
|
+
const personality = await inquirer_1.default.prompt([
|
|
57
|
+
{
|
|
58
|
+
type: 'list',
|
|
59
|
+
name: 'tone',
|
|
60
|
+
message: 'Tono de comunicacion:',
|
|
61
|
+
choices: ['profesional', 'amigable', 'formal', 'casual', 'tecnico', 'empatico'],
|
|
62
|
+
default: 'profesional',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: 'list',
|
|
66
|
+
name: 'style',
|
|
67
|
+
message: 'Estilo de respuesta:',
|
|
68
|
+
choices: ['conciso', 'detallado', 'conversacional', 'directo'],
|
|
69
|
+
default: 'conciso',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: 'input',
|
|
73
|
+
name: 'personality',
|
|
74
|
+
message: 'Personalidad en una frase:',
|
|
75
|
+
default: 'Servicial y conocedor',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
type: 'input',
|
|
79
|
+
name: 'objective',
|
|
80
|
+
message: 'Objetivo principal del agente:',
|
|
81
|
+
default: 'Ayudar a los usuarios con sus consultas',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
type: 'list',
|
|
85
|
+
name: 'language',
|
|
86
|
+
message: 'Idioma principal:',
|
|
87
|
+
choices: ['Espanol', 'English', 'Portugues', 'Frances'],
|
|
88
|
+
default: 'Espanol',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
type: 'confirm',
|
|
92
|
+
name: 'useEmojis',
|
|
93
|
+
message: 'Usar emojis en respuestas?',
|
|
94
|
+
default: true,
|
|
95
|
+
},
|
|
96
|
+
]);
|
|
97
|
+
// Paso 3: Persona
|
|
98
|
+
console.log(ui_1.theme.bold('\n Paso 3/8: Identidad del agente'));
|
|
99
|
+
const person = await inquirer_1.default.prompt([
|
|
100
|
+
{
|
|
101
|
+
type: 'input',
|
|
102
|
+
name: 'name',
|
|
103
|
+
message: 'Nombre del personaje (como se presenta):',
|
|
104
|
+
default: basic.name,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
type: 'input',
|
|
108
|
+
name: 'role',
|
|
109
|
+
message: 'Rol (ej: Asistente de ventas, Soporte tecnico):',
|
|
110
|
+
default: 'Asistente virtual',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'confirm',
|
|
114
|
+
name: 'firstPerson',
|
|
115
|
+
message: 'Hablar en primera persona?',
|
|
116
|
+
default: true,
|
|
117
|
+
},
|
|
118
|
+
]);
|
|
119
|
+
// Paso 4: Fallbacks
|
|
120
|
+
console.log(ui_1.theme.bold('\n Paso 4/8: Mensajes de fallback'));
|
|
121
|
+
const fallbacks = await inquirer_1.default.prompt([
|
|
122
|
+
{
|
|
123
|
+
type: 'input',
|
|
124
|
+
name: 'noAnswer',
|
|
125
|
+
message: 'Cuando no tiene respuesta:',
|
|
126
|
+
default: 'Lo siento, no tengo informacion sobre eso. Puedo ayudarte con otra consulta?',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'input',
|
|
130
|
+
name: 'serviceError',
|
|
131
|
+
message: 'Cuando hay error de servicio:',
|
|
132
|
+
default: 'Disculpa, estamos experimentando dificultades tecnicas. Intenta de nuevo en unos momentos.',
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: 'input',
|
|
136
|
+
name: 'misunderstanding',
|
|
137
|
+
message: 'Cuando no entiende la pregunta:',
|
|
138
|
+
default: 'No estoy seguro de entender tu consulta. Podrias reformularla?',
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
// Paso 5: Tool Calling
|
|
142
|
+
console.log(ui_1.theme.bold('\n Paso 5/8: Tool Calling'));
|
|
143
|
+
console.log(ui_1.theme.muted(' Tool Calling permite al agente ejecutar acciones automaticas\n'));
|
|
144
|
+
const { useToolCalling } = await inquirer_1.default.prompt([
|
|
145
|
+
{
|
|
146
|
+
type: 'confirm',
|
|
147
|
+
name: 'useToolCalling',
|
|
148
|
+
message: 'Activar Tool Calling?',
|
|
149
|
+
default: true,
|
|
150
|
+
},
|
|
151
|
+
]);
|
|
152
|
+
// Servicios (API calls)
|
|
153
|
+
const services = [];
|
|
154
|
+
if (useToolCalling) {
|
|
155
|
+
const { addServices } = await inquirer_1.default.prompt([{
|
|
156
|
+
type: 'confirm',
|
|
157
|
+
name: 'addServices',
|
|
158
|
+
message: 'Agregar servicios externos (API calls)?',
|
|
159
|
+
default: false,
|
|
160
|
+
}]);
|
|
161
|
+
if (addServices) {
|
|
162
|
+
let addMore = true;
|
|
163
|
+
while (addMore) {
|
|
164
|
+
console.log(ui_1.theme.muted('\n Nuevo servicio:'));
|
|
165
|
+
const svc = await inquirer_1.default.prompt([
|
|
166
|
+
{ type: 'input', name: 'intent', message: 'Nombre/intent del servicio:', validate: (v) => v.length > 0 || 'Requerido' },
|
|
167
|
+
{ type: 'input', name: 'reference', message: 'Palabras clave de referencia:', default: '' },
|
|
168
|
+
{ type: 'list', name: 'method', message: 'Metodo HTTP:', choices: ['GET', 'POST'] },
|
|
169
|
+
{ type: 'input', name: 'endpoint', message: 'URL del endpoint:', validate: (v) => v.length > 0 || 'Requerido' },
|
|
170
|
+
{ type: 'input', name: 'responseMessage', message: 'Mensaje de respuesta:', default: '' },
|
|
171
|
+
]);
|
|
172
|
+
// Required fields
|
|
173
|
+
const fields = [];
|
|
174
|
+
const { addFields } = await inquirer_1.default.prompt([{
|
|
175
|
+
type: 'confirm', name: 'addFields',
|
|
176
|
+
message: 'Agregar campos requeridos?', default: false,
|
|
177
|
+
}]);
|
|
178
|
+
if (addFields) {
|
|
179
|
+
let moreFields = true;
|
|
180
|
+
while (moreFields) {
|
|
181
|
+
const field = await inquirer_1.default.prompt([
|
|
182
|
+
{ type: 'input', name: 'name', message: 'Nombre del campo:' },
|
|
183
|
+
{ type: 'list', name: 'type', message: 'Tipo:', choices: ['string', 'number', 'boolean', 'date'] },
|
|
184
|
+
{ type: 'input', name: 'description', message: 'Descripcion:' },
|
|
185
|
+
{ type: 'input', name: 'promptHint', message: 'Hint para el LLM:' },
|
|
186
|
+
]);
|
|
187
|
+
fields.push(field);
|
|
188
|
+
const { more } = await inquirer_1.default.prompt([{ type: 'confirm', name: 'more', message: 'Agregar otro campo?', default: false }]);
|
|
189
|
+
moreFields = more;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
services.push({
|
|
193
|
+
intent: svc.intent,
|
|
194
|
+
reference: svc.reference,
|
|
195
|
+
enabled: true,
|
|
196
|
+
method: svc.method,
|
|
197
|
+
endpoint: svc.endpoint,
|
|
198
|
+
requiredFields: fields,
|
|
199
|
+
headers: {},
|
|
200
|
+
bodyTemplate: {},
|
|
201
|
+
responseMapping: {},
|
|
202
|
+
responseMessage: svc.responseMessage,
|
|
203
|
+
responseConditions: [],
|
|
204
|
+
});
|
|
205
|
+
const { more } = await inquirer_1.default.prompt([{ type: 'confirm', name: 'more', message: 'Agregar otro servicio?', default: false }]);
|
|
206
|
+
addMore = more;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Acciones
|
|
211
|
+
const actions = [];
|
|
212
|
+
if (useToolCalling) {
|
|
213
|
+
const { addActions } = await inquirer_1.default.prompt([{
|
|
214
|
+
type: 'confirm',
|
|
215
|
+
name: 'addActions',
|
|
216
|
+
message: 'Agregar acciones (tag, stage, asignar agente)?',
|
|
217
|
+
default: false,
|
|
218
|
+
}]);
|
|
219
|
+
if (addActions) {
|
|
220
|
+
let addMore = true;
|
|
221
|
+
while (addMore) {
|
|
222
|
+
console.log(ui_1.theme.muted('\n Nueva accion:'));
|
|
223
|
+
const act = await inquirer_1.default.prompt([
|
|
224
|
+
{ type: 'input', name: 'intent', message: 'Nombre/intent de la accion:', validate: (v) => v.length > 0 || 'Requerido' },
|
|
225
|
+
{ type: 'input', name: 'reference', message: 'Palabras clave de referencia:', default: '' },
|
|
226
|
+
{
|
|
227
|
+
type: 'list', name: 'actionType', message: 'Tipo de accion:',
|
|
228
|
+
choices: [
|
|
229
|
+
{ name: 'Agendar evento', value: 'action.event.add' },
|
|
230
|
+
{ name: 'Actualizar evento (reagendar)', value: 'action.event.update' },
|
|
231
|
+
{ name: 'Listar eventos', value: 'action.event.list' },
|
|
232
|
+
{ name: 'Eliminar evento (cancelar)', value: 'action.event.delete' },
|
|
233
|
+
{ name: 'Agregar tag', value: 'action.tag' },
|
|
234
|
+
{ name: 'Cambiar stage', value: 'action.stage' },
|
|
235
|
+
{ name: 'Derivar a agente humano', value: 'action.agentShutDown' },
|
|
236
|
+
{ name: 'Marcar como resuelto', value: 'action.solved' },
|
|
237
|
+
{ name: 'Asignar agente', value: 'action.asign' },
|
|
238
|
+
{ name: 'Segmentacion', value: 'action.segmentation' },
|
|
239
|
+
],
|
|
240
|
+
},
|
|
241
|
+
{ type: 'input', name: 'actionValue', message: 'Valor de la accion:', default: '' },
|
|
242
|
+
{ type: 'input', name: 'responseMessage', message: 'Mensaje de respuesta:', default: '' },
|
|
243
|
+
]);
|
|
244
|
+
actions.push({
|
|
245
|
+
intent: act.intent,
|
|
246
|
+
reference: act.reference,
|
|
247
|
+
enabled: true,
|
|
248
|
+
requiredFields: [],
|
|
249
|
+
responseMessage: act.responseMessage,
|
|
250
|
+
action: [{ type: act.actionType, value: act.actionValue }],
|
|
251
|
+
});
|
|
252
|
+
const { more } = await inquirer_1.default.prompt([{ type: 'confirm', name: 'more', message: 'Agregar otra accion?', default: false }]);
|
|
253
|
+
addMore = more;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Paso 6: AI Provider
|
|
258
|
+
console.log(ui_1.theme.bold('\n Paso 6/8: Proveedor de IA'));
|
|
259
|
+
const { configureAI } = await inquirer_1.default.prompt([{
|
|
260
|
+
type: 'confirm',
|
|
261
|
+
name: 'configureAI',
|
|
262
|
+
message: 'Configurar proveedor de IA personalizado?',
|
|
263
|
+
default: false,
|
|
264
|
+
}]);
|
|
265
|
+
const aiProviders = [];
|
|
266
|
+
if (configureAI) {
|
|
267
|
+
const ai = await inquirer_1.default.prompt([
|
|
268
|
+
{ type: 'list', name: 'provider', message: 'Proveedor:', choices: ['openai', 'claude', 'gemini'] },
|
|
269
|
+
]);
|
|
270
|
+
const models = MODELS[ai.provider] || MODELS.openai;
|
|
271
|
+
const aiConfig = await inquirer_1.default.prompt([
|
|
272
|
+
{ type: 'list', name: 'model', message: 'Modelo:', choices: models },
|
|
273
|
+
{ type: 'password', name: 'apiToken', message: 'API Token:', mask: '*', validate: (v) => v.length > 0 || 'Requerido' },
|
|
274
|
+
{ type: 'number', name: 'temperature', message: 'Temperatura (0-2):', default: 0.7 },
|
|
275
|
+
{ type: 'number', name: 'maxTokens', message: 'Max tokens (1024-16384):', default: 4096 },
|
|
276
|
+
]);
|
|
277
|
+
aiProviders.push({
|
|
278
|
+
provider: ai.provider,
|
|
279
|
+
model: aiConfig.model,
|
|
280
|
+
apiToken: aiConfig.apiToken,
|
|
281
|
+
temperature: aiConfig.temperature,
|
|
282
|
+
maxTokens: aiConfig.maxTokens,
|
|
283
|
+
isDefault: true,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
// Paso 7: Canal WhatsApp
|
|
287
|
+
console.log(ui_1.theme.bold('\n Paso 7/8: Canal WhatsApp'));
|
|
288
|
+
const channels = [];
|
|
289
|
+
const { addWhatsApp } = await inquirer_1.default.prompt([{
|
|
290
|
+
type: 'confirm',
|
|
291
|
+
name: 'addWhatsApp',
|
|
292
|
+
message: 'Conectar a un numero de WhatsApp?',
|
|
293
|
+
default: false,
|
|
294
|
+
}]);
|
|
295
|
+
if (addWhatsApp) {
|
|
296
|
+
const wa = await inquirer_1.default.prompt([
|
|
297
|
+
{ type: 'input', name: 'key', message: 'Numero de WhatsApp (con codigo de pais):', validate: (v) => v.length > 0 || 'Requerido' },
|
|
298
|
+
{ type: 'confirm', name: 'multianswer', message: 'Permitir multiples respuestas?', default: false },
|
|
299
|
+
]);
|
|
300
|
+
channels.push({ channel: 'whatsapp', key: wa.key, multianswer: wa.multianswer });
|
|
301
|
+
}
|
|
302
|
+
// Paso 8: Ejemplos
|
|
303
|
+
console.log(ui_1.theme.bold('\n Paso 8/8: Ejemplos de conversacion'));
|
|
304
|
+
const examples = [];
|
|
305
|
+
const { addExamples } = await inquirer_1.default.prompt([{
|
|
306
|
+
type: 'confirm',
|
|
307
|
+
name: 'addExamples',
|
|
308
|
+
message: 'Agregar ejemplos de conversacion?',
|
|
309
|
+
default: false,
|
|
310
|
+
}]);
|
|
311
|
+
if (addExamples) {
|
|
312
|
+
let addMore = true;
|
|
313
|
+
while (addMore) {
|
|
314
|
+
const ex = await inquirer_1.default.prompt([
|
|
315
|
+
{ type: 'input', name: 'user', message: 'Mensaje del usuario:' },
|
|
316
|
+
{ type: 'input', name: 'agent', message: 'Respuesta del agente:' },
|
|
317
|
+
]);
|
|
318
|
+
examples.push({ value: `Usuario: ${ex.user}\nAgente: ${ex.agent}`, color: 'blue' });
|
|
319
|
+
const { more } = await inquirer_1.default.prompt([{ type: 'confirm', name: 'more', message: 'Agregar otro ejemplo?', default: false }]);
|
|
320
|
+
addMore = more;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// Armar config final (alineado con agent.config.schema.json del backend)
|
|
324
|
+
const config = {
|
|
325
|
+
name: basic.name,
|
|
326
|
+
description: basic.description || '',
|
|
327
|
+
prompt: basic.prompt,
|
|
328
|
+
buffer: basic.buffer,
|
|
329
|
+
zone,
|
|
330
|
+
color: basic.color,
|
|
331
|
+
useToolCalling,
|
|
332
|
+
customAIConfig: configureAI,
|
|
333
|
+
aiProviders,
|
|
334
|
+
instructions: {
|
|
335
|
+
tone: personality.tone,
|
|
336
|
+
style: personality.style,
|
|
337
|
+
personality: personality.personality,
|
|
338
|
+
objective: personality.objective,
|
|
339
|
+
language: personality.language,
|
|
340
|
+
emojis: personality.useEmojis,
|
|
341
|
+
},
|
|
342
|
+
person: {
|
|
343
|
+
name: person.name,
|
|
344
|
+
role: person.role,
|
|
345
|
+
speaksInFirstPerson: person.firstPerson,
|
|
346
|
+
},
|
|
347
|
+
fallbacks: {
|
|
348
|
+
noAnswer: fallbacks.noAnswer,
|
|
349
|
+
serviceError: fallbacks.serviceError,
|
|
350
|
+
doNotUnderstand: fallbacks.misunderstanding,
|
|
351
|
+
},
|
|
352
|
+
services,
|
|
353
|
+
actions,
|
|
354
|
+
channels,
|
|
355
|
+
examples,
|
|
356
|
+
tags: [],
|
|
357
|
+
};
|
|
358
|
+
// Preview
|
|
359
|
+
console.log((0, ui_1.section)('Vista previa de la configuracion'));
|
|
360
|
+
console.log((0, ui_1.kvPair)('Nombre', config.name));
|
|
361
|
+
console.log((0, ui_1.kvPair)('Prompt', config.prompt.substring(0, 80) + '...'));
|
|
362
|
+
console.log((0, ui_1.kvPair)('Tool Calling', config.useToolCalling ? 'Activado' : 'Desactivado'));
|
|
363
|
+
console.log((0, ui_1.kvPair)('Servicios', String(config.services.length)));
|
|
364
|
+
console.log((0, ui_1.kvPair)('Acciones', String(config.actions.length)));
|
|
365
|
+
console.log((0, ui_1.kvPair)('AI Provider', config.customAIConfig ? config.aiProviders[0]?.provider + ' / ' + config.aiProviders[0]?.model : 'Default (Plazbot)'));
|
|
366
|
+
console.log((0, ui_1.kvPair)('Canal WhatsApp', config.channels.length > 0 ? config.channels[0].key : 'No configurado'));
|
|
367
|
+
console.log();
|
|
368
|
+
return config;
|
|
369
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.broadcastCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const plazbot_1 = require("plazbot");
|
|
9
|
+
const credentials_1 = require("../../utils/credentials");
|
|
10
|
+
const logger_1 = require("../../utils/logger");
|
|
11
|
+
const ui_1 = require("../../utils/ui");
|
|
12
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
13
|
+
exports.broadcastCommand = new commander_1.Command('broadcast')
|
|
14
|
+
.description('Envio masivo de mensajes de template WhatsApp')
|
|
15
|
+
.requiredOption('-t, --template <name>', 'Nombre del template')
|
|
16
|
+
.requiredOption('--phones <file>', 'Archivo CSV con numeros de telefono (uno por linea)')
|
|
17
|
+
.option('--var <vars...>', 'Variables del body (formato: name=valor)')
|
|
18
|
+
.option('--delay <ms>', 'Delay entre mensajes en ms', '1000')
|
|
19
|
+
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
20
|
+
.action(async (options) => {
|
|
21
|
+
try {
|
|
22
|
+
const credentials = await (0, credentials_1.getStoredCredentials)();
|
|
23
|
+
const messageClient = new plazbot_1.Message({
|
|
24
|
+
workspaceId: credentials.workspace,
|
|
25
|
+
apiKey: credentials.apiKey,
|
|
26
|
+
zone: credentials.zone,
|
|
27
|
+
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
28
|
+
});
|
|
29
|
+
// Leer archivo de telefonos
|
|
30
|
+
let phones;
|
|
31
|
+
try {
|
|
32
|
+
const content = await promises_1.default.readFile(options.phones, 'utf-8');
|
|
33
|
+
phones = content.split('\n')
|
|
34
|
+
.map(line => line.trim())
|
|
35
|
+
.filter(line => line && !line.startsWith('#'));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
throw new Error(`No se pudo leer el archivo: ${options.phones}`);
|
|
39
|
+
}
|
|
40
|
+
if (phones.length === 0) {
|
|
41
|
+
throw new Error('El archivo no contiene numeros de telefono');
|
|
42
|
+
}
|
|
43
|
+
// Parsear variables
|
|
44
|
+
const variablesBody = parseVariables(options.var);
|
|
45
|
+
console.log((0, ui_1.section)('Broadcast WhatsApp'));
|
|
46
|
+
logger_1.logger.label('Template', options.template);
|
|
47
|
+
logger_1.logger.label('Destinatarios', String(phones.length));
|
|
48
|
+
logger_1.logger.label('Delay', `${options.delay}ms`);
|
|
49
|
+
if (variablesBody.length > 0) {
|
|
50
|
+
logger_1.logger.label('Variables', variablesBody.map(v => `${v.variable}=${v.value}`).join(', '));
|
|
51
|
+
}
|
|
52
|
+
console.log();
|
|
53
|
+
const delay = parseInt(options.delay) || 1000;
|
|
54
|
+
let sent = 0;
|
|
55
|
+
let failed = 0;
|
|
56
|
+
for (let i = 0; i < phones.length; i++) {
|
|
57
|
+
const phone = phones[i];
|
|
58
|
+
try {
|
|
59
|
+
const params = {
|
|
60
|
+
to: phone,
|
|
61
|
+
template: options.template,
|
|
62
|
+
};
|
|
63
|
+
if (variablesBody.length > 0)
|
|
64
|
+
params.variablesBody = variablesBody;
|
|
65
|
+
await messageClient.onConversation(params);
|
|
66
|
+
sent++;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
failed++;
|
|
70
|
+
console.log(ui_1.theme.error(` ✖ Fallo: ${phone}`));
|
|
71
|
+
}
|
|
72
|
+
// Progress
|
|
73
|
+
console.log(` ${(0, ui_1.progressBar)(i + 1, phones.length)}`);
|
|
74
|
+
// Rate limiting
|
|
75
|
+
if (i < phones.length - 1) {
|
|
76
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
console.log((0, ui_1.section)('Resultado'));
|
|
80
|
+
logger_1.logger.label('Enviados', ui_1.theme.success(String(sent)));
|
|
81
|
+
logger_1.logger.label('Fallidos', failed > 0 ? ui_1.theme.error(String(failed)) : '0');
|
|
82
|
+
logger_1.logger.label('Total', String(phones.length));
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const message = error?.message || 'Error desconocido';
|
|
86
|
+
logger_1.logger.error(message);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
function parseVariables(vars) {
|
|
91
|
+
if (!vars)
|
|
92
|
+
return [];
|
|
93
|
+
return vars.map(v => {
|
|
94
|
+
const [variable, ...rest] = v.split('=');
|
|
95
|
+
return { variable: variable.trim(), value: rest.join('=').trim() };
|
|
96
|
+
}).filter(v => v.variable && v.value);
|
|
97
|
+
}
|