plazbot-cli 0.2.4 → 0.2.6
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/dist/commands/agent/create.js +4 -2
- package/dist/commands/agent/get.js +128 -93
- package/dist/commands/agent/monitor.js +17 -4
- package/dist/commands/agent/wizard.js +179 -14
- package/package.json +1 -1
- package/src/commands/agent/create.ts +4 -2
- package/src/commands/agent/get.ts +140 -101
- package/src/commands/agent/monitor.ts +21 -4
- package/src/commands/agent/wizard.ts +204 -14
|
@@ -73,7 +73,7 @@ exports.createCommand = new commander_1.Command('create')
|
|
|
73
73
|
}
|
|
74
74
|
else {
|
|
75
75
|
// Modo wizard interactivo
|
|
76
|
-
agentConfig = await (0, wizard_1.runAgentWizard)(credentials.zone);
|
|
76
|
+
agentConfig = await (0, wizard_1.runAgentWizard)(credentials.zone, credentials.workspace, credentials.apiKey, options.dev);
|
|
77
77
|
const inquirer = await Promise.resolve().then(() => __importStar(require('inquirer')));
|
|
78
78
|
const { confirm } = await inquirer.default.prompt([{
|
|
79
79
|
type: 'confirm',
|
|
@@ -99,7 +99,9 @@ exports.createCommand = new commander_1.Command('create')
|
|
|
99
99
|
}
|
|
100
100
|
logger_1.logger.label('Tool Calling', agentConfig.useToolCalling ? 'Activado' : 'Desactivado');
|
|
101
101
|
if (agentConfig.channels && agentConfig.channels.length > 0) {
|
|
102
|
-
|
|
102
|
+
agentConfig.channels.forEach((ch) => {
|
|
103
|
+
logger_1.logger.label(`Canal (${ch.channel})`, ch.key);
|
|
104
|
+
});
|
|
103
105
|
}
|
|
104
106
|
console.log();
|
|
105
107
|
logger_1.logger.dim('Siguiente paso: plazbot agent chat -a ' + (result.agentId || '<agentId>'));
|
|
@@ -1,153 +1,188 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.getCommand = void 0;
|
|
4
7
|
const commander_1 = require("commander");
|
|
5
8
|
const plazbot_1 = require("plazbot");
|
|
6
9
|
const credentials_1 = require("../../utils/credentials");
|
|
7
10
|
const logger_1 = require("../../utils/logger");
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
12
|
exports.getCommand = new commander_1.Command('get')
|
|
9
13
|
.description('Obtiene información detallada de un agente específico')
|
|
10
14
|
.argument('<agentId>', 'ID del agente a consultar')
|
|
15
|
+
.option('-w, --workspace <id>', 'Workspace ID (sobreescribe config local)')
|
|
16
|
+
.option('-z, --zone <zone>', 'Zona LA o EU (sobreescribe config local)')
|
|
17
|
+
.option('--raw', 'Mostrar el JSON completo sin formatear', false)
|
|
11
18
|
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
12
19
|
.action(async (agentId, options) => {
|
|
13
20
|
try {
|
|
14
|
-
// Obtener credenciales guardadas
|
|
15
21
|
const credentials = await (0, credentials_1.getStoredCredentials)();
|
|
16
|
-
|
|
22
|
+
const effectiveWorkspace = options.workspace || credentials.workspace;
|
|
23
|
+
const effectiveZone = (options.zone?.toUpperCase() === 'EU' ? 'EU' : options.zone?.toUpperCase() === 'LA' ? 'LA' : credentials.zone);
|
|
24
|
+
if (options.workspace || options.zone) {
|
|
25
|
+
console.log(chalk_1.default.hex('#FFA726')(`\n Modo soporte: workspace=${effectiveWorkspace} zona=${effectiveZone}`));
|
|
26
|
+
}
|
|
17
27
|
const agent = new plazbot_1.Agent({
|
|
18
|
-
workspaceId:
|
|
28
|
+
workspaceId: effectiveWorkspace,
|
|
19
29
|
apiKey: credentials.apiKey,
|
|
20
|
-
zone:
|
|
30
|
+
zone: effectiveZone,
|
|
21
31
|
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
22
32
|
});
|
|
23
|
-
//
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
// El SDK retorna { success, agent: {...} }
|
|
34
|
+
const response = await agent.getAgentById({ id: agentId });
|
|
35
|
+
const agentData = response.agent || response.data || response;
|
|
36
|
+
// Modo JSON crudo
|
|
37
|
+
if (options.raw) {
|
|
38
|
+
console.log(JSON.stringify(agentData, null, 2));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const label = (key, value) => {
|
|
42
|
+
const v = value !== undefined && value !== null && value !== '' ? String(value) : chalk_1.default.gray('—');
|
|
43
|
+
console.log(` ${chalk_1.default.gray(key + ':')} ${chalk_1.default.white(v)}`);
|
|
44
|
+
};
|
|
45
|
+
const sectionHeader = (title) => {
|
|
46
|
+
console.log();
|
|
47
|
+
console.log(chalk_1.default.bold.hex('#4CAF50')(` ${title}`));
|
|
48
|
+
console.log(chalk_1.default.gray(' ' + '─'.repeat(40)));
|
|
49
|
+
};
|
|
50
|
+
console.log();
|
|
51
|
+
console.log(chalk_1.default.hex('#4CAF50')(' ┌' + '─'.repeat(58) + '┐'));
|
|
52
|
+
console.log(chalk_1.default.hex('#4CAF50')(' │') + chalk_1.default.bold(` ${agentData.name || 'Agente'}`).padEnd(68) + chalk_1.default.hex('#4CAF50')('│'));
|
|
53
|
+
console.log(chalk_1.default.hex('#4CAF50')(' │') + chalk_1.default.gray(` ${agentId}`).padEnd(68) + chalk_1.default.hex('#4CAF50')('│'));
|
|
54
|
+
console.log(chalk_1.default.hex('#4CAF50')(' └' + '─'.repeat(58) + '┘'));
|
|
55
|
+
// Informacion basica
|
|
56
|
+
sectionHeader('Informacion Basica');
|
|
57
|
+
label('ID', agentData.id);
|
|
58
|
+
label('Nombre', agentData.name);
|
|
59
|
+
label('Descripcion', agentData.description);
|
|
60
|
+
label('Estado', agentData.enable ? chalk_1.default.hex('#66BB6A')('Activo') : chalk_1.default.hex('#EF5350')('Inactivo'));
|
|
61
|
+
label('Zona', agentData.zone);
|
|
62
|
+
label('Buffer', agentData.buffer);
|
|
63
|
+
label('Color', agentData.color);
|
|
64
|
+
label('Pregunta inicial', agentData.question);
|
|
65
|
+
label('Zona horaria', agentData.timezone);
|
|
66
|
+
label('Mostrar en chat', agentData.showInChat ? 'Si' : 'No');
|
|
67
|
+
label('Tool Calling', agentData.useToolCalling ? 'Activado' : 'Desactivado');
|
|
40
68
|
// Tags
|
|
41
69
|
if (agentData.tags && agentData.tags.length > 0) {
|
|
42
|
-
|
|
70
|
+
label('Tags', agentData.tags.join(', '));
|
|
71
|
+
}
|
|
72
|
+
// Prompt
|
|
73
|
+
if (agentData.prompt) {
|
|
74
|
+
sectionHeader('Prompt');
|
|
75
|
+
const promptPreview = agentData.prompt.length > 200
|
|
76
|
+
? agentData.prompt.substring(0, 200) + '...'
|
|
77
|
+
: agentData.prompt;
|
|
78
|
+
console.log(chalk_1.default.white(' ' + promptPreview.split('\n').join('\n ')));
|
|
43
79
|
}
|
|
44
80
|
// Ejemplos
|
|
45
81
|
if (agentData.examples && agentData.examples.length > 0) {
|
|
46
|
-
|
|
47
|
-
logger_1.logger.divider();
|
|
82
|
+
sectionHeader('Ejemplos');
|
|
48
83
|
agentData.examples.forEach((example) => {
|
|
49
|
-
|
|
84
|
+
console.log(chalk_1.default.white(` - ${example.value || example}`));
|
|
50
85
|
});
|
|
51
86
|
}
|
|
52
87
|
// Instrucciones
|
|
53
88
|
if (agentData.instructions) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
logger_1.logger.info(`Temas a evitar: ${instructions.avoidTopics.join(', ')}`);
|
|
89
|
+
sectionHeader('Instrucciones');
|
|
90
|
+
const inst = agentData.instructions;
|
|
91
|
+
label('Tono', inst.tone);
|
|
92
|
+
label('Estilo', inst.style);
|
|
93
|
+
label('Personalidad', inst.personality);
|
|
94
|
+
label('Objetivo', inst.objective);
|
|
95
|
+
label('Idioma', inst.language);
|
|
96
|
+
label('Emojis', inst.emojis ? 'Si' : 'No');
|
|
97
|
+
label('Formato preferido', inst.preferredFormat);
|
|
98
|
+
label('Max palabras', inst.maxWords);
|
|
99
|
+
if (inst.avoidTopics && inst.avoidTopics.length > 0) {
|
|
100
|
+
label('Temas a evitar', inst.avoidTopics.join(', '));
|
|
67
101
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
logger_1.logger.info(`Saludo: ${instructions.greeting}`);
|
|
102
|
+
label('Solo responder si sabe', inst.respondOnlyIfKnows ? 'Si' : 'No');
|
|
103
|
+
label('Saludo', inst.greeting);
|
|
71
104
|
}
|
|
72
105
|
// Persona
|
|
73
106
|
if (agentData.person) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
logger_1.logger.info(`Es humano: ${person.isHuman ? 'Sí' : 'No'}`);
|
|
107
|
+
sectionHeader('Persona');
|
|
108
|
+
const p = agentData.person;
|
|
109
|
+
label('Nombre', p.name);
|
|
110
|
+
label('Rol', p.role);
|
|
111
|
+
label('Primera persona', p.speaksInFirstPerson ? 'Si' : 'No');
|
|
112
|
+
label('Es humano', p.isHuman ? 'Si' : 'No');
|
|
81
113
|
}
|
|
82
114
|
// Fallbacks
|
|
83
115
|
if (agentData.fallbacks) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
logger_1.logger.info(`No entiende: ${fallbacks.doNotUnderstand}`);
|
|
116
|
+
sectionHeader('Fallbacks');
|
|
117
|
+
const fb = agentData.fallbacks;
|
|
118
|
+
label('Sin respuesta', fb.noAnswer);
|
|
119
|
+
label('Error de servicio', fb.serviceError);
|
|
120
|
+
label('No entiende', fb.doNotUnderstand);
|
|
90
121
|
}
|
|
91
122
|
// Reglas
|
|
92
123
|
if (agentData.rules) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
logger_1.logger.info(`Horario de atención: ${rules.doNotRespondOutsideHours}`);
|
|
124
|
+
sectionHeader('Reglas');
|
|
125
|
+
const r = agentData.rules;
|
|
126
|
+
label('No mencionar precios', r.doNotMentionPrices ? 'Si' : 'No');
|
|
127
|
+
label('No diagnosticar', r.doNotDiagnose ? 'Si' : 'No');
|
|
128
|
+
if (r.doNotRespondOutsideHours) {
|
|
129
|
+
label('Fuera de horario', r.doNotRespondOutsideHours);
|
|
100
130
|
}
|
|
101
131
|
}
|
|
102
132
|
// Servicios
|
|
103
133
|
if (agentData.services && agentData.services.length > 0) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
service.requiredFields.forEach((field) => {
|
|
116
|
-
logger_1.logger.info(` - ${field.name} (${field.type}): ${field.description}`);
|
|
134
|
+
sectionHeader(`Servicios (${agentData.services.length})`);
|
|
135
|
+
agentData.services.forEach((svc, i) => {
|
|
136
|
+
console.log(chalk_1.default.hex('#2196F3')(` ${i + 1}. ${svc.intent || svc.reference || 'Servicio'}`));
|
|
137
|
+
label(' Referencia', svc.reference);
|
|
138
|
+
label(' Habilitado', svc.enabled ? 'Si' : 'No');
|
|
139
|
+
label(' Metodo', svc.method);
|
|
140
|
+
label(' Endpoint', svc.endpoint);
|
|
141
|
+
if (svc.requiredFields && svc.requiredFields.length > 0) {
|
|
142
|
+
console.log(chalk_1.default.gray(' Campos:'));
|
|
143
|
+
svc.requiredFields.forEach((f) => {
|
|
144
|
+
console.log(chalk_1.default.white(` - ${f.name} (${f.type}): ${f.description || ''}`));
|
|
117
145
|
});
|
|
118
146
|
}
|
|
119
147
|
});
|
|
120
148
|
}
|
|
121
149
|
// Acciones
|
|
122
150
|
if (agentData.actions && agentData.actions.length > 0) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (action.tags) {
|
|
131
|
-
logger_1.logger.info(`Tags: ${action.tags.join(', ')}`);
|
|
151
|
+
sectionHeader(`Acciones (${agentData.actions.length})`);
|
|
152
|
+
agentData.actions.forEach((act, i) => {
|
|
153
|
+
console.log(chalk_1.default.hex('#FFA726')(` ${i + 1}. ${act.intent || act.reference || 'Accion'}`));
|
|
154
|
+
label(' Referencia', act.reference);
|
|
155
|
+
label(' Habilitado', act.enabled ? 'Si' : 'No');
|
|
156
|
+
if (act.tags && act.tags.length > 0) {
|
|
157
|
+
label(' Tags', act.tags.join(', '));
|
|
132
158
|
}
|
|
133
|
-
|
|
134
|
-
if (action.action) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
159
|
+
label(' Respuesta', act.responseMessage);
|
|
160
|
+
if (act.action && act.action.length > 0) {
|
|
161
|
+
console.log(chalk_1.default.gray(' Sub-acciones:'));
|
|
162
|
+
act.action.forEach((sa) => {
|
|
163
|
+
console.log(chalk_1.default.white(` - ${sa.type}: ${sa.value || ''}`));
|
|
138
164
|
});
|
|
139
165
|
}
|
|
140
166
|
});
|
|
141
167
|
}
|
|
142
168
|
// Canales
|
|
143
169
|
if (agentData.channels && agentData.channels.length > 0) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
170
|
+
sectionHeader(`Canales (${agentData.channels.length})`);
|
|
171
|
+
agentData.channels.forEach((ch) => {
|
|
172
|
+
console.log(chalk_1.default.white(` ${chalk_1.default.hex('#22d3ee')(ch.channel || 'canal')}: ${ch.key || ''}`));
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
// AI Config
|
|
176
|
+
if (agentData.customAIConfig && agentData.aiProviders && agentData.aiProviders.length > 0) {
|
|
177
|
+
sectionHeader('Modelo IA');
|
|
178
|
+
agentData.aiProviders.forEach((ai) => {
|
|
179
|
+
label('Proveedor', ai.provider);
|
|
180
|
+
label('Modelo', ai.model);
|
|
148
181
|
});
|
|
149
182
|
}
|
|
150
|
-
|
|
183
|
+
console.log();
|
|
184
|
+
console.log(chalk_1.default.gray(' Usa --raw para ver el JSON completo'));
|
|
185
|
+
console.log();
|
|
151
186
|
if (options.dev) {
|
|
152
187
|
logger_1.logger.warning('Ambiente: desarrollo');
|
|
153
188
|
}
|
|
@@ -104,6 +104,7 @@ function printHeader(agentName) {
|
|
|
104
104
|
const COMMANDS_HELP = `
|
|
105
105
|
${chalk_1.default.bold('Comandos disponibles:')}
|
|
106
106
|
${chalk_1.default.hex('#4CAF50')('/filter <tipo>')} Toggle filtro por tipo (ej: msg_in, error, tool_call)
|
|
107
|
+
${chalk_1.default.hex('#4CAF50')('/filter clear')} Quitar todos los filtros
|
|
107
108
|
${chalk_1.default.hex('#4CAF50')('/filters')} Mostrar filtros activos
|
|
108
109
|
${chalk_1.default.hex('#4CAF50')('/clear')} Limpiar pantalla
|
|
109
110
|
${chalk_1.default.hex('#4CAF50')('/json')} Toggle modo JSON expandido
|
|
@@ -118,11 +119,18 @@ exports.monitorCommand = new commander_1.Command('monitor')
|
|
|
118
119
|
.option('-f, --filter <types>', 'Filtrar por tipos separados por coma (ej: msg_in,msg_out)')
|
|
119
120
|
.option('--no-session', 'Ocultar session ID')
|
|
120
121
|
.option('--json', 'Modo JSON crudo (para piping)', false)
|
|
122
|
+
.option('-w, --workspace <id>', 'Workspace ID (sobreescribe config local)')
|
|
123
|
+
.option('-z, --zone <zone>', 'Zona LA o EU (sobreescribe config local)')
|
|
121
124
|
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
122
125
|
.action(async (options) => {
|
|
123
126
|
try {
|
|
124
127
|
const credentials = await (0, credentials_1.getStoredCredentials)();
|
|
125
|
-
const
|
|
128
|
+
const effectiveWorkspace = options.workspace || credentials.workspace;
|
|
129
|
+
const effectiveZone = (options.zone?.toUpperCase() === 'EU' ? 'EU' : options.zone?.toUpperCase() === 'LA' ? 'LA' : credentials.zone);
|
|
130
|
+
const baseUrl = getBaseUrl(effectiveZone, options.dev);
|
|
131
|
+
if (options.workspace || options.zone) {
|
|
132
|
+
console.log(chalk_1.default.hex('#FFA726')(`\n Modo soporte: workspace=${effectiveWorkspace} zona=${effectiveZone}`));
|
|
133
|
+
}
|
|
126
134
|
// Filtros iniciales
|
|
127
135
|
const activeFilters = new Set(options.filter ? options.filter.split(',').map(f => f.trim()) : []);
|
|
128
136
|
let jsonMode = options.json;
|
|
@@ -132,9 +140,9 @@ exports.monitorCommand = new commander_1.Command('monitor')
|
|
|
132
140
|
try {
|
|
133
141
|
process.stdout.write(chalk_1.default.gray(' Conectando con agente...'));
|
|
134
142
|
const agent = new plazbot_1.Agent({
|
|
135
|
-
workspaceId:
|
|
143
|
+
workspaceId: effectiveWorkspace,
|
|
136
144
|
apiKey: credentials.apiKey,
|
|
137
|
-
zone:
|
|
145
|
+
zone: effectiveZone,
|
|
138
146
|
...(options.dev && { customUrl: 'http://localhost:5090' }),
|
|
139
147
|
});
|
|
140
148
|
const info = await agent.getAgentById({ id: options.agentId });
|
|
@@ -236,7 +244,12 @@ exports.monitorCommand = new commander_1.Command('monitor')
|
|
|
236
244
|
if (cmd.startsWith('/filter ')) {
|
|
237
245
|
const filterType = cmd.substring(8).trim();
|
|
238
246
|
if (!filterType) {
|
|
239
|
-
console.log(chalk_1.default.gray(' Uso: /filter <tipo>'));
|
|
247
|
+
console.log(chalk_1.default.gray(' Uso: /filter <tipo> | /filter clear'));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (filterType === 'clear') {
|
|
251
|
+
activeFilters.clear();
|
|
252
|
+
console.log(chalk_1.default.gray(' Todos los filtros removidos (mostrando todos)'));
|
|
240
253
|
return;
|
|
241
254
|
}
|
|
242
255
|
if (activeFilters.has(filterType)) {
|
|
@@ -5,14 +5,170 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.runAgentWizard = runAgentWizard;
|
|
7
7
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const ora_1 = __importDefault(require("ora"));
|
|
8
11
|
const ui_1 = require("../../utils/ui");
|
|
9
12
|
const MODELS = {
|
|
10
|
-
openai: ['gpt-4o', 'gpt-4', 'gpt-3.5-turbo', 'o1-preview', 'o1-mini'],
|
|
13
|
+
openai: ['gpt-4o', 'gpt-4o-mini', 'gpt-4', 'gpt-3.5-turbo', 'o1-preview', 'o1-mini'],
|
|
11
14
|
claude: ['claude-3-5-sonnet-20241022', 'claude-3-opus-20240229', 'claude-3-haiku-20240307'],
|
|
12
15
|
gemini: ['gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash'],
|
|
13
16
|
};
|
|
14
17
|
const COLORS = ['blue', 'green', 'orange', 'gray', 'white'];
|
|
15
|
-
|
|
18
|
+
function getBaseUrl(zone, dev) {
|
|
19
|
+
if (dev)
|
|
20
|
+
return 'http://localhost:5090';
|
|
21
|
+
return zone === 'EU' ? 'https://apieu.plazbot.com' : 'https://api.plazbot.com';
|
|
22
|
+
}
|
|
23
|
+
const CHANNEL_CHOICES = [
|
|
24
|
+
{ name: 'WhatsApp', value: 'whatsapp' },
|
|
25
|
+
{ name: 'WhatsApp Business', value: 'whatsapp_business' },
|
|
26
|
+
{ name: 'Instagram', value: 'instagram' },
|
|
27
|
+
{ name: 'Messenger', value: 'facebook' },
|
|
28
|
+
];
|
|
29
|
+
const CHANNEL_AGENT_MAP = {
|
|
30
|
+
whatsapp: 'whatsapp',
|
|
31
|
+
whatsapp_business: 'whatsapp',
|
|
32
|
+
instagram: 'instagram',
|
|
33
|
+
facebook: 'facebook',
|
|
34
|
+
};
|
|
35
|
+
async function connectChannelFlow(ctx) {
|
|
36
|
+
const channels = [];
|
|
37
|
+
const baseUrl = getBaseUrl(ctx.zone, ctx.dev);
|
|
38
|
+
const headers = {
|
|
39
|
+
'Authorization': `Bearer ${ctx.apiKey}`,
|
|
40
|
+
'x-workspace-id': ctx.workspaceId,
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
};
|
|
43
|
+
let addMore = true;
|
|
44
|
+
while (addMore) {
|
|
45
|
+
const { channelType } = await inquirer_1.default.prompt([{
|
|
46
|
+
type: 'list',
|
|
47
|
+
name: 'channelType',
|
|
48
|
+
message: 'Que canal deseas conectar?',
|
|
49
|
+
choices: CHANNEL_CHOICES,
|
|
50
|
+
}]);
|
|
51
|
+
const channelLabel = CHANNEL_CHOICES.find(c => c.value === channelType)?.name || channelType;
|
|
52
|
+
// Generar link de onboarding
|
|
53
|
+
const spinner = (0, ora_1.default)({ text: chalk_1.default.gray('Generando link de conexion...'), spinner: 'dots', color: 'green' }).start();
|
|
54
|
+
try {
|
|
55
|
+
const linkRes = await axios_1.default.post(`${baseUrl}/api/workspace/${ctx.workspaceId}/onboarding-link`, { type: channelType }, { headers });
|
|
56
|
+
if (!linkRes.data?.success) {
|
|
57
|
+
spinner.fail(chalk_1.default.hex('#EF5350')(`Error: ${linkRes.data?.message || 'No se pudo generar el link'}`));
|
|
58
|
+
const { tryManual } = await inquirer_1.default.prompt([{
|
|
59
|
+
type: 'confirm', name: 'tryManual',
|
|
60
|
+
message: 'Deseas ingresar el numero manualmente?', default: false,
|
|
61
|
+
}]);
|
|
62
|
+
if (tryManual) {
|
|
63
|
+
const { key } = await inquirer_1.default.prompt([
|
|
64
|
+
{ type: 'input', name: 'key', message: `ID/numero del canal ${channelLabel}:`, validate: (v) => v.length > 0 || 'Requerido' },
|
|
65
|
+
]);
|
|
66
|
+
channels.push({ channel: CHANNEL_AGENT_MAP[channelType], key, multianswer: false });
|
|
67
|
+
}
|
|
68
|
+
const { more } = await inquirer_1.default.prompt([{ type: 'confirm', name: 'more', message: 'Conectar otro canal?', default: false }]);
|
|
69
|
+
addMore = more;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const shortUrl = linkRes.data.data?.shortUrl || '';
|
|
73
|
+
spinner.stop();
|
|
74
|
+
// Mostrar link
|
|
75
|
+
console.log();
|
|
76
|
+
console.log(chalk_1.default.hex('#4CAF50')(' ─'.repeat(32)));
|
|
77
|
+
console.log(chalk_1.default.bold(` Envia este link para conectar ${channelLabel}:`));
|
|
78
|
+
console.log();
|
|
79
|
+
console.log(' ' + chalk_1.default.hex('#22d3ee')(shortUrl));
|
|
80
|
+
console.log();
|
|
81
|
+
console.log(chalk_1.default.hex('#4CAF50')(' ─'.repeat(32)));
|
|
82
|
+
console.log();
|
|
83
|
+
// Snapshot de integraciones actuales
|
|
84
|
+
let prevIntegrationIds = new Set();
|
|
85
|
+
try {
|
|
86
|
+
const wkRes = await axios_1.default.get(`${baseUrl}/api/workspace/${ctx.workspaceId}`, { headers });
|
|
87
|
+
const integrations = wkRes.data?.integrations || [];
|
|
88
|
+
prevIntegrationIds = new Set(integrations.map((i) => i.id));
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Si falla, se parte de vacio
|
|
92
|
+
}
|
|
93
|
+
// Polling para detectar nueva integracion
|
|
94
|
+
const pollSpinner = (0, ora_1.default)({ text: chalk_1.default.gray('Esperando conexion... (Ctrl+C para cancelar)'), spinner: 'dots', color: 'cyan' }).start();
|
|
95
|
+
const POLL_INTERVAL = 5000;
|
|
96
|
+
const MAX_POLLS = 60; // 5 minutos
|
|
97
|
+
let detected = null;
|
|
98
|
+
for (let i = 0; i < MAX_POLLS; i++) {
|
|
99
|
+
await new Promise(r => setTimeout(r, POLL_INTERVAL));
|
|
100
|
+
try {
|
|
101
|
+
const wkRes = await axios_1.default.get(`${baseUrl}/api/workspace/${ctx.workspaceId}`, { headers });
|
|
102
|
+
const integrations = wkRes.data?.integrations || [];
|
|
103
|
+
// Buscar integraciones nuevas (cualquier ID que no existia antes)
|
|
104
|
+
const newOnes = integrations.filter((ig) => !prevIntegrationIds.has(ig.id));
|
|
105
|
+
if (newOnes.length > 0) {
|
|
106
|
+
// Preferir la que coincida con el tipo solicitado
|
|
107
|
+
const targetType = channelType === 'whatsapp_business' ? 'whatsapp' : channelType;
|
|
108
|
+
const matchingNew = newOnes.find((ig) => ig.type === targetType);
|
|
109
|
+
detected = matchingNew || newOnes[0];
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Ignorar errores de poll individual
|
|
115
|
+
}
|
|
116
|
+
const elapsed = Math.floor(((i + 1) * POLL_INTERVAL) / 1000);
|
|
117
|
+
pollSpinner.text = chalk_1.default.gray(`Esperando conexion... ${elapsed}s`);
|
|
118
|
+
}
|
|
119
|
+
if (detected) {
|
|
120
|
+
const detectedName = detected.aliasName || detected.cellphoneNumberFormat || detected.cellphoneNumber || detected.srcName || detected.id;
|
|
121
|
+
pollSpinner.succeed(chalk_1.default.hex('#4ade80')(`Conexion detectada: ${detectedName} (${channelLabel})`));
|
|
122
|
+
const { associate } = await inquirer_1.default.prompt([{
|
|
123
|
+
type: 'confirm', name: 'associate',
|
|
124
|
+
message: 'Deseas asociar este canal al agente?', default: true,
|
|
125
|
+
}]);
|
|
126
|
+
if (associate) {
|
|
127
|
+
channels.push({
|
|
128
|
+
channel: CHANNEL_AGENT_MAP[channelType],
|
|
129
|
+
key: detected.id,
|
|
130
|
+
multianswer: false,
|
|
131
|
+
});
|
|
132
|
+
console.log(chalk_1.default.hex('#4ade80')(' Canal asociado correctamente.'));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
pollSpinner.warn(chalk_1.default.hex('#FFA726')('Timeout: no se detecto una conexion.'));
|
|
137
|
+
const { action } = await inquirer_1.default.prompt([{
|
|
138
|
+
type: 'list', name: 'action',
|
|
139
|
+
message: 'Que deseas hacer?',
|
|
140
|
+
choices: [
|
|
141
|
+
{ name: 'Ingresar numero/ID manualmente', value: 'manual' },
|
|
142
|
+
{ name: 'Saltar este paso', value: 'skip' },
|
|
143
|
+
],
|
|
144
|
+
}]);
|
|
145
|
+
if (action === 'manual') {
|
|
146
|
+
const { key } = await inquirer_1.default.prompt([
|
|
147
|
+
{ type: 'input', name: 'key', message: `ID/numero del canal ${channelLabel}:`, validate: (v) => v.length > 0 || 'Requerido' },
|
|
148
|
+
]);
|
|
149
|
+
channels.push({ channel: CHANNEL_AGENT_MAP[channelType], key, multianswer: false });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
spinner.fail(chalk_1.default.hex('#EF5350')(`Error al generar link: ${err instanceof Error ? err.message : err}`));
|
|
155
|
+
const { tryManual } = await inquirer_1.default.prompt([{
|
|
156
|
+
type: 'confirm', name: 'tryManual',
|
|
157
|
+
message: 'Deseas ingresar el numero manualmente?', default: false,
|
|
158
|
+
}]);
|
|
159
|
+
if (tryManual) {
|
|
160
|
+
const { key } = await inquirer_1.default.prompt([
|
|
161
|
+
{ type: 'input', name: 'key', message: `ID/numero del canal ${channelLabel}:`, validate: (v) => v.length > 0 || 'Requerido' },
|
|
162
|
+
]);
|
|
163
|
+
channels.push({ channel: CHANNEL_AGENT_MAP[channelType], key, multianswer: false });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const { more } = await inquirer_1.default.prompt([{ type: 'confirm', name: 'more', message: 'Conectar otro canal?', default: false }]);
|
|
167
|
+
addMore = more;
|
|
168
|
+
}
|
|
169
|
+
return channels;
|
|
170
|
+
}
|
|
171
|
+
async function runAgentWizard(zone, workspaceId, apiKey, dev) {
|
|
16
172
|
console.log((0, ui_1.section)('Crear nuevo agente de IA'));
|
|
17
173
|
console.log(ui_1.theme.muted(' Responde las siguientes preguntas para configurar tu agente.\n'));
|
|
18
174
|
// Paso 1: Informacion basica
|
|
@@ -271,28 +427,30 @@ async function runAgentWizard(zone) {
|
|
|
271
427
|
const aiConfig = await inquirer_1.default.prompt([
|
|
272
428
|
{ type: 'list', name: 'model', message: 'Modelo:', choices: models },
|
|
273
429
|
{ 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
430
|
]);
|
|
277
431
|
aiProviders.push({
|
|
278
432
|
provider: ai.provider,
|
|
279
433
|
model: aiConfig.model,
|
|
280
434
|
apiToken: aiConfig.apiToken,
|
|
281
|
-
temperature:
|
|
282
|
-
maxTokens:
|
|
435
|
+
temperature: 0.7,
|
|
436
|
+
maxTokens: 4096,
|
|
283
437
|
isDefault: true,
|
|
284
438
|
});
|
|
285
439
|
}
|
|
286
|
-
// Paso 7:
|
|
287
|
-
console.log(ui_1.theme.bold('\n Paso 7/8:
|
|
288
|
-
|
|
289
|
-
const {
|
|
440
|
+
// Paso 7: Conectar canal
|
|
441
|
+
console.log(ui_1.theme.bold('\n Paso 7/8: Conectar canal'));
|
|
442
|
+
let channels = [];
|
|
443
|
+
const { addChannel } = await inquirer_1.default.prompt([{
|
|
290
444
|
type: 'confirm',
|
|
291
|
-
name: '
|
|
292
|
-
message: '
|
|
445
|
+
name: 'addChannel',
|
|
446
|
+
message: 'Deseas conectar un canal (WhatsApp, Instagram, Messenger)?',
|
|
293
447
|
default: false,
|
|
294
448
|
}]);
|
|
295
|
-
if (
|
|
449
|
+
if (addChannel && workspaceId && apiKey) {
|
|
450
|
+
channels = await connectChannelFlow({ zone, workspaceId, apiKey, dev: dev || false });
|
|
451
|
+
}
|
|
452
|
+
else if (addChannel) {
|
|
453
|
+
// Fallback manual si no hay credenciales para API
|
|
296
454
|
const wa = await inquirer_1.default.prompt([
|
|
297
455
|
{ type: 'input', name: 'key', message: 'Numero de WhatsApp (con codigo de pais):', validate: (v) => v.length > 0 || 'Requerido' },
|
|
298
456
|
{ type: 'confirm', name: 'multianswer', message: 'Permitir multiples respuestas?', default: false },
|
|
@@ -363,7 +521,14 @@ async function runAgentWizard(zone) {
|
|
|
363
521
|
console.log((0, ui_1.kvPair)('Servicios', String(config.services.length)));
|
|
364
522
|
console.log((0, ui_1.kvPair)('Acciones', String(config.actions.length)));
|
|
365
523
|
console.log((0, ui_1.kvPair)('AI Provider', config.customAIConfig ? config.aiProviders[0]?.provider + ' / ' + config.aiProviders[0]?.model : 'Default (Plazbot)'));
|
|
366
|
-
|
|
524
|
+
if (config.channels.length > 0) {
|
|
525
|
+
config.channels.forEach((ch, i) => {
|
|
526
|
+
console.log((0, ui_1.kvPair)(`Canal ${i + 1} (${ch.channel})`, ch.key));
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
console.log((0, ui_1.kvPair)('Canales', 'No configurado'));
|
|
531
|
+
}
|
|
367
532
|
console.log();
|
|
368
533
|
return config;
|
|
369
534
|
}
|
package/package.json
CHANGED
|
@@ -37,7 +37,7 @@ export const createCommand = new Command('create')
|
|
|
37
37
|
logger.json(agentConfig);
|
|
38
38
|
} else {
|
|
39
39
|
// Modo wizard interactivo
|
|
40
|
-
agentConfig = await runAgentWizard(credentials.zone);
|
|
40
|
+
agentConfig = await runAgentWizard(credentials.zone, credentials.workspace, credentials.apiKey, options.dev);
|
|
41
41
|
|
|
42
42
|
const inquirer = await import('inquirer');
|
|
43
43
|
const { confirm } = await inquirer.default.prompt([{
|
|
@@ -70,7 +70,9 @@ export const createCommand = new Command('create')
|
|
|
70
70
|
logger.label('Tool Calling', agentConfig.useToolCalling ? 'Activado' : 'Desactivado');
|
|
71
71
|
|
|
72
72
|
if (agentConfig.channels && agentConfig.channels.length > 0) {
|
|
73
|
-
|
|
73
|
+
agentConfig.channels.forEach((ch: any) => {
|
|
74
|
+
logger.label(`Canal (${ch.channel})`, ch.key);
|
|
75
|
+
});
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
console.log();
|
|
@@ -3,127 +3,158 @@ import { Agent } from 'plazbot';
|
|
|
3
3
|
import { getStoredCredentials } from '../../utils/credentials';
|
|
4
4
|
import { logger } from '../../utils/logger';
|
|
5
5
|
import { AgentCommandOptions } from '../../types/agent';
|
|
6
|
+
import chalk from 'chalk';
|
|
6
7
|
|
|
7
8
|
export const getCommand = new Command('get')
|
|
8
9
|
.description('Obtiene información detallada de un agente específico')
|
|
9
10
|
.argument('<agentId>', 'ID del agente a consultar')
|
|
11
|
+
.option('-w, --workspace <id>', 'Workspace ID (sobreescribe config local)')
|
|
12
|
+
.option('-z, --zone <zone>', 'Zona LA o EU (sobreescribe config local)')
|
|
13
|
+
.option('--raw', 'Mostrar el JSON completo sin formatear', false)
|
|
10
14
|
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
11
|
-
.action(async (agentId: string, options: AgentCommandOptions) => {
|
|
15
|
+
.action(async (agentId: string, options: AgentCommandOptions & { raw: boolean; workspace?: string; zone?: string }) => {
|
|
12
16
|
try {
|
|
13
|
-
// Obtener credenciales guardadas
|
|
14
17
|
const credentials = await getStoredCredentials();
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
|
|
19
|
+
const effectiveWorkspace = options.workspace || credentials.workspace;
|
|
20
|
+
const effectiveZone = (options.zone?.toUpperCase() === 'EU' ? 'EU' : options.zone?.toUpperCase() === 'LA' ? 'LA' : credentials.zone) as 'LA' | 'EU';
|
|
21
|
+
|
|
22
|
+
if (options.workspace || options.zone) {
|
|
23
|
+
console.log(chalk.hex('#FFA726')(`\n Modo soporte: workspace=${effectiveWorkspace} zona=${effectiveZone}`));
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
const agent = new Agent({
|
|
18
|
-
workspaceId:
|
|
27
|
+
workspaceId: effectiveWorkspace,
|
|
19
28
|
apiKey: credentials.apiKey,
|
|
20
|
-
zone:
|
|
29
|
+
zone: effectiveZone,
|
|
21
30
|
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
22
31
|
});
|
|
23
32
|
|
|
24
|
-
//
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
// El SDK retorna { success, agent: {...} }
|
|
34
|
+
const response: any = await agent.getAgentById({ id: agentId });
|
|
35
|
+
const agentData = response.agent || response.data || response;
|
|
36
|
+
|
|
37
|
+
// Modo JSON crudo
|
|
38
|
+
if (options.raw) {
|
|
39
|
+
console.log(JSON.stringify(agentData, null, 2));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const label = (key: string, value: any) => {
|
|
44
|
+
const v = value !== undefined && value !== null && value !== '' ? String(value) : chalk.gray('—');
|
|
45
|
+
console.log(` ${chalk.gray(key + ':')} ${chalk.white(v)}`);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const sectionHeader = (title: string) => {
|
|
49
|
+
console.log();
|
|
50
|
+
console.log(chalk.bold.hex('#4CAF50')(` ${title}`));
|
|
51
|
+
console.log(chalk.gray(' ' + '─'.repeat(40)));
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
console.log();
|
|
55
|
+
console.log(chalk.hex('#4CAF50')(' ┌' + '─'.repeat(58) + '┐'));
|
|
56
|
+
console.log(chalk.hex('#4CAF50')(' │') + chalk.bold(` ${agentData.name || 'Agente'}`).padEnd(68) + chalk.hex('#4CAF50')('│'));
|
|
57
|
+
console.log(chalk.hex('#4CAF50')(' │') + chalk.gray(` ${agentId}`).padEnd(68) + chalk.hex('#4CAF50')('│'));
|
|
58
|
+
console.log(chalk.hex('#4CAF50')(' └' + '─'.repeat(58) + '┘'));
|
|
59
|
+
|
|
60
|
+
// Informacion basica
|
|
61
|
+
sectionHeader('Informacion Basica');
|
|
62
|
+
label('ID', agentData.id);
|
|
63
|
+
label('Nombre', agentData.name);
|
|
64
|
+
label('Descripcion', agentData.description);
|
|
65
|
+
label('Estado', agentData.enable ? chalk.hex('#66BB6A')('Activo') : chalk.hex('#EF5350')('Inactivo'));
|
|
66
|
+
label('Zona', agentData.zone);
|
|
67
|
+
label('Buffer', agentData.buffer);
|
|
68
|
+
label('Color', agentData.color);
|
|
69
|
+
label('Pregunta inicial', agentData.question);
|
|
70
|
+
label('Zona horaria', agentData.timezone);
|
|
71
|
+
label('Mostrar en chat', agentData.showInChat ? 'Si' : 'No');
|
|
72
|
+
label('Tool Calling', agentData.useToolCalling ? 'Activado' : 'Desactivado');
|
|
73
|
+
|
|
44
74
|
// Tags
|
|
45
75
|
if (agentData.tags && agentData.tags.length > 0) {
|
|
46
|
-
|
|
76
|
+
label('Tags', agentData.tags.join(', '));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Prompt
|
|
80
|
+
if (agentData.prompt) {
|
|
81
|
+
sectionHeader('Prompt');
|
|
82
|
+
const promptPreview = agentData.prompt.length > 200
|
|
83
|
+
? agentData.prompt.substring(0, 200) + '...'
|
|
84
|
+
: agentData.prompt;
|
|
85
|
+
console.log(chalk.white(' ' + promptPreview.split('\n').join('\n ')));
|
|
47
86
|
}
|
|
48
87
|
|
|
49
88
|
// Ejemplos
|
|
50
89
|
if (agentData.examples && agentData.examples.length > 0) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
logger.info(`- ${example.value} (${example.color})`);
|
|
90
|
+
sectionHeader('Ejemplos');
|
|
91
|
+
agentData.examples.forEach((example: any) => {
|
|
92
|
+
console.log(chalk.white(` - ${example.value || example}`));
|
|
55
93
|
});
|
|
56
94
|
}
|
|
57
95
|
|
|
58
96
|
// Instrucciones
|
|
59
97
|
if (agentData.instructions) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
logger.info(`Temas a evitar: ${instructions.avoidTopics.join(', ')}`);
|
|
98
|
+
sectionHeader('Instrucciones');
|
|
99
|
+
const inst = agentData.instructions;
|
|
100
|
+
label('Tono', inst.tone);
|
|
101
|
+
label('Estilo', inst.style);
|
|
102
|
+
label('Personalidad', inst.personality);
|
|
103
|
+
label('Objetivo', inst.objective);
|
|
104
|
+
label('Idioma', inst.language);
|
|
105
|
+
label('Emojis', inst.emojis ? 'Si' : 'No');
|
|
106
|
+
label('Formato preferido', inst.preferredFormat);
|
|
107
|
+
label('Max palabras', inst.maxWords);
|
|
108
|
+
if (inst.avoidTopics && inst.avoidTopics.length > 0) {
|
|
109
|
+
label('Temas a evitar', inst.avoidTopics.join(', '));
|
|
73
110
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
logger.info(`Saludo: ${instructions.greeting}`);
|
|
111
|
+
label('Solo responder si sabe', inst.respondOnlyIfKnows ? 'Si' : 'No');
|
|
112
|
+
label('Saludo', inst.greeting);
|
|
77
113
|
}
|
|
78
114
|
|
|
79
115
|
// Persona
|
|
80
116
|
if (agentData.person) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
logger.info(`Es humano: ${person.isHuman ? 'Sí' : 'No'}`);
|
|
117
|
+
sectionHeader('Persona');
|
|
118
|
+
const p = agentData.person;
|
|
119
|
+
label('Nombre', p.name);
|
|
120
|
+
label('Rol', p.role);
|
|
121
|
+
label('Primera persona', p.speaksInFirstPerson ? 'Si' : 'No');
|
|
122
|
+
label('Es humano', p.isHuman ? 'Si' : 'No');
|
|
88
123
|
}
|
|
89
124
|
|
|
90
125
|
// Fallbacks
|
|
91
126
|
if (agentData.fallbacks) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
logger.info(`No entiende: ${fallbacks.doNotUnderstand}`);
|
|
127
|
+
sectionHeader('Fallbacks');
|
|
128
|
+
const fb = agentData.fallbacks;
|
|
129
|
+
label('Sin respuesta', fb.noAnswer);
|
|
130
|
+
label('Error de servicio', fb.serviceError);
|
|
131
|
+
label('No entiende', fb.doNotUnderstand);
|
|
98
132
|
}
|
|
99
133
|
|
|
100
134
|
// Reglas
|
|
101
135
|
if (agentData.rules) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
logger.info(`Horario de atención: ${rules.doNotRespondOutsideHours}`);
|
|
136
|
+
sectionHeader('Reglas');
|
|
137
|
+
const r = agentData.rules;
|
|
138
|
+
label('No mencionar precios', r.doNotMentionPrices ? 'Si' : 'No');
|
|
139
|
+
label('No diagnosticar', r.doNotDiagnose ? 'Si' : 'No');
|
|
140
|
+
if (r.doNotRespondOutsideHours) {
|
|
141
|
+
label('Fuera de horario', r.doNotRespondOutsideHours);
|
|
109
142
|
}
|
|
110
143
|
}
|
|
111
144
|
|
|
112
145
|
// Servicios
|
|
113
146
|
if (agentData.services && agentData.services.length > 0) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
service.requiredFields.forEach((field: any) => {
|
|
126
|
-
logger.info(` - ${field.name} (${field.type}): ${field.description}`);
|
|
147
|
+
sectionHeader(`Servicios (${agentData.services.length})`);
|
|
148
|
+
agentData.services.forEach((svc: any, i: number) => {
|
|
149
|
+
console.log(chalk.hex('#2196F3')(` ${i + 1}. ${svc.intent || svc.reference || 'Servicio'}`));
|
|
150
|
+
label(' Referencia', svc.reference);
|
|
151
|
+
label(' Habilitado', svc.enabled ? 'Si' : 'No');
|
|
152
|
+
label(' Metodo', svc.method);
|
|
153
|
+
label(' Endpoint', svc.endpoint);
|
|
154
|
+
if (svc.requiredFields && svc.requiredFields.length > 0) {
|
|
155
|
+
console.log(chalk.gray(' Campos:'));
|
|
156
|
+
svc.requiredFields.forEach((f: any) => {
|
|
157
|
+
console.log(chalk.white(` - ${f.name} (${f.type}): ${f.description || ''}`));
|
|
127
158
|
});
|
|
128
159
|
}
|
|
129
160
|
});
|
|
@@ -131,21 +162,19 @@ export const getCommand = new Command('get')
|
|
|
131
162
|
|
|
132
163
|
// Acciones
|
|
133
164
|
if (agentData.actions && agentData.actions.length > 0) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (action.tags) {
|
|
142
|
-
logger.info(`Tags: ${action.tags.join(', ')}`);
|
|
165
|
+
sectionHeader(`Acciones (${agentData.actions.length})`);
|
|
166
|
+
agentData.actions.forEach((act: any, i: number) => {
|
|
167
|
+
console.log(chalk.hex('#FFA726')(` ${i + 1}. ${act.intent || act.reference || 'Accion'}`));
|
|
168
|
+
label(' Referencia', act.reference);
|
|
169
|
+
label(' Habilitado', act.enabled ? 'Si' : 'No');
|
|
170
|
+
if (act.tags && act.tags.length > 0) {
|
|
171
|
+
label(' Tags', act.tags.join(', '));
|
|
143
172
|
}
|
|
144
|
-
|
|
145
|
-
if (action.action) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
173
|
+
label(' Respuesta', act.responseMessage);
|
|
174
|
+
if (act.action && act.action.length > 0) {
|
|
175
|
+
console.log(chalk.gray(' Sub-acciones:'));
|
|
176
|
+
act.action.forEach((sa: any) => {
|
|
177
|
+
console.log(chalk.white(` - ${sa.type}: ${sa.value || ''}`));
|
|
149
178
|
});
|
|
150
179
|
}
|
|
151
180
|
});
|
|
@@ -153,19 +182,29 @@ export const getCommand = new Command('get')
|
|
|
153
182
|
|
|
154
183
|
// Canales
|
|
155
184
|
if (agentData.channels && agentData.channels.length > 0) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
logger.info(`${channel.channel}: ${channel.key}`);
|
|
185
|
+
sectionHeader(`Canales (${agentData.channels.length})`);
|
|
186
|
+
agentData.channels.forEach((ch: any) => {
|
|
187
|
+
console.log(chalk.white(` ${chalk.hex('#22d3ee')(ch.channel || 'canal')}: ${ch.key || ''}`));
|
|
160
188
|
});
|
|
161
189
|
}
|
|
162
190
|
|
|
163
|
-
|
|
164
|
-
|
|
191
|
+
// AI Config
|
|
192
|
+
if (agentData.customAIConfig && agentData.aiProviders && agentData.aiProviders.length > 0) {
|
|
193
|
+
sectionHeader('Modelo IA');
|
|
194
|
+
agentData.aiProviders.forEach((ai: any) => {
|
|
195
|
+
label('Proveedor', ai.provider);
|
|
196
|
+
label('Modelo', ai.model);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
console.log();
|
|
201
|
+
console.log(chalk.gray(' Usa --raw para ver el JSON completo'));
|
|
202
|
+
console.log();
|
|
203
|
+
|
|
165
204
|
if (options.dev) {
|
|
166
205
|
logger.warning('Ambiente: desarrollo');
|
|
167
206
|
}
|
|
168
|
-
|
|
207
|
+
|
|
169
208
|
} catch (error) {
|
|
170
209
|
const message = error instanceof Error ? error.message : 'Error desconocido al obtener el agente';
|
|
171
210
|
logger.error(message);
|
|
@@ -135,6 +135,7 @@ function printHeader(agentName: string) {
|
|
|
135
135
|
const COMMANDS_HELP = `
|
|
136
136
|
${chalk.bold('Comandos disponibles:')}
|
|
137
137
|
${chalk.hex('#4CAF50')('/filter <tipo>')} Toggle filtro por tipo (ej: msg_in, error, tool_call)
|
|
138
|
+
${chalk.hex('#4CAF50')('/filter clear')} Quitar todos los filtros
|
|
138
139
|
${chalk.hex('#4CAF50')('/filters')} Mostrar filtros activos
|
|
139
140
|
${chalk.hex('#4CAF50')('/clear')} Limpiar pantalla
|
|
140
141
|
${chalk.hex('#4CAF50')('/json')} Toggle modo JSON expandido
|
|
@@ -152,17 +153,28 @@ export const monitorCommand = new Command('monitor')
|
|
|
152
153
|
.option('-f, --filter <types>', 'Filtrar por tipos separados por coma (ej: msg_in,msg_out)')
|
|
153
154
|
.option('--no-session', 'Ocultar session ID')
|
|
154
155
|
.option('--json', 'Modo JSON crudo (para piping)', false)
|
|
156
|
+
.option('-w, --workspace <id>', 'Workspace ID (sobreescribe config local)')
|
|
157
|
+
.option('-z, --zone <zone>', 'Zona LA o EU (sobreescribe config local)')
|
|
155
158
|
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
156
159
|
.action(async (options: {
|
|
157
160
|
agentId: string;
|
|
158
161
|
filter?: string;
|
|
159
162
|
session: boolean;
|
|
160
163
|
json: boolean;
|
|
164
|
+
workspace?: string;
|
|
165
|
+
zone?: string;
|
|
161
166
|
dev: boolean;
|
|
162
167
|
}) => {
|
|
163
168
|
try {
|
|
164
169
|
const credentials = await getStoredCredentials();
|
|
165
|
-
|
|
170
|
+
|
|
171
|
+
const effectiveWorkspace = options.workspace || credentials.workspace;
|
|
172
|
+
const effectiveZone = (options.zone?.toUpperCase() === 'EU' ? 'EU' : options.zone?.toUpperCase() === 'LA' ? 'LA' : credentials.zone) as 'LA' | 'EU';
|
|
173
|
+
const baseUrl = getBaseUrl(effectiveZone, options.dev);
|
|
174
|
+
|
|
175
|
+
if (options.workspace || options.zone) {
|
|
176
|
+
console.log(chalk.hex('#FFA726')(`\n Modo soporte: workspace=${effectiveWorkspace} zona=${effectiveZone}`));
|
|
177
|
+
}
|
|
166
178
|
|
|
167
179
|
// Filtros iniciales
|
|
168
180
|
const activeFilters: Set<string> = new Set(
|
|
@@ -176,9 +188,9 @@ export const monitorCommand = new Command('monitor')
|
|
|
176
188
|
try {
|
|
177
189
|
process.stdout.write(chalk.gray(' Conectando con agente...'));
|
|
178
190
|
const agent = new Agent({
|
|
179
|
-
workspaceId:
|
|
191
|
+
workspaceId: effectiveWorkspace,
|
|
180
192
|
apiKey: credentials.apiKey,
|
|
181
|
-
zone:
|
|
193
|
+
zone: effectiveZone,
|
|
182
194
|
...(options.dev && { customUrl: 'http://localhost:5090' }),
|
|
183
195
|
});
|
|
184
196
|
const info: any = await agent.getAgentById({ id: options.agentId });
|
|
@@ -291,7 +303,12 @@ export const monitorCommand = new Command('monitor')
|
|
|
291
303
|
if (cmd.startsWith('/filter ')) {
|
|
292
304
|
const filterType = cmd.substring(8).trim();
|
|
293
305
|
if (!filterType) {
|
|
294
|
-
console.log(chalk.gray(' Uso: /filter <tipo>'));
|
|
306
|
+
console.log(chalk.gray(' Uso: /filter <tipo> | /filter clear'));
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
if (filterType === 'clear') {
|
|
310
|
+
activeFilters.clear();
|
|
311
|
+
console.log(chalk.gray(' Todos los filtros removidos (mostrando todos)'));
|
|
295
312
|
return;
|
|
296
313
|
}
|
|
297
314
|
if (activeFilters.has(filterType)) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import inquirer from 'inquirer';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
import ora from 'ora';
|
|
3
5
|
import { theme, section, kvPair } from '../../utils/ui';
|
|
4
6
|
|
|
5
7
|
interface AgentConfig {
|
|
@@ -87,14 +89,195 @@ interface AgentExample {
|
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
const MODELS: Record<string, string[]> = {
|
|
90
|
-
openai: ['gpt-4o', 'gpt-4', 'gpt-3.5-turbo', 'o1-preview', 'o1-mini'],
|
|
92
|
+
openai: ['gpt-4o', 'gpt-4o-mini', 'gpt-4', 'gpt-3.5-turbo', 'o1-preview', 'o1-mini'],
|
|
91
93
|
claude: ['claude-3-5-sonnet-20241022', 'claude-3-opus-20240229', 'claude-3-haiku-20240307'],
|
|
92
94
|
gemini: ['gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash'],
|
|
93
95
|
};
|
|
94
96
|
|
|
95
97
|
const COLORS = ['blue', 'green', 'orange', 'gray', 'white'];
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
interface WizardContext {
|
|
100
|
+
zone: string;
|
|
101
|
+
workspaceId: string;
|
|
102
|
+
apiKey: string;
|
|
103
|
+
dev: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getBaseUrl(zone: string, dev: boolean): string {
|
|
107
|
+
if (dev) return 'http://localhost:5090';
|
|
108
|
+
return zone === 'EU' ? 'https://apieu.plazbot.com' : 'https://api.plazbot.com';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const CHANNEL_CHOICES = [
|
|
112
|
+
{ name: 'WhatsApp', value: 'whatsapp' },
|
|
113
|
+
{ name: 'WhatsApp Business', value: 'whatsapp_business' },
|
|
114
|
+
{ name: 'Instagram', value: 'instagram' },
|
|
115
|
+
{ name: 'Messenger', value: 'facebook' },
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
const CHANNEL_AGENT_MAP: Record<string, string> = {
|
|
119
|
+
whatsapp: 'whatsapp',
|
|
120
|
+
whatsapp_business: 'whatsapp',
|
|
121
|
+
instagram: 'instagram',
|
|
122
|
+
facebook: 'facebook',
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
async function connectChannelFlow(ctx: WizardContext): Promise<AgentChannel[]> {
|
|
126
|
+
const channels: AgentChannel[] = [];
|
|
127
|
+
const baseUrl = getBaseUrl(ctx.zone, ctx.dev);
|
|
128
|
+
const headers = {
|
|
129
|
+
'Authorization': `Bearer ${ctx.apiKey}`,
|
|
130
|
+
'x-workspace-id': ctx.workspaceId,
|
|
131
|
+
'Content-Type': 'application/json',
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
let addMore = true;
|
|
135
|
+
while (addMore) {
|
|
136
|
+
const { channelType } = await (inquirer as any).prompt([{
|
|
137
|
+
type: 'list',
|
|
138
|
+
name: 'channelType',
|
|
139
|
+
message: 'Que canal deseas conectar?',
|
|
140
|
+
choices: CHANNEL_CHOICES,
|
|
141
|
+
}]);
|
|
142
|
+
|
|
143
|
+
const channelLabel = CHANNEL_CHOICES.find(c => c.value === channelType)?.name || channelType;
|
|
144
|
+
|
|
145
|
+
// Generar link de onboarding
|
|
146
|
+
const spinner = ora({ text: chalk.gray('Generando link de conexion...'), spinner: 'dots', color: 'green' }).start();
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
const linkRes = await axios.post(
|
|
150
|
+
`${baseUrl}/api/workspace/${ctx.workspaceId}/onboarding-link`,
|
|
151
|
+
{ type: channelType },
|
|
152
|
+
{ headers }
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
if (!linkRes.data?.success) {
|
|
156
|
+
spinner.fail(chalk.hex('#EF5350')(`Error: ${linkRes.data?.message || 'No se pudo generar el link'}`));
|
|
157
|
+
const { tryManual } = await (inquirer as any).prompt([{
|
|
158
|
+
type: 'confirm', name: 'tryManual',
|
|
159
|
+
message: 'Deseas ingresar el numero manualmente?', default: false,
|
|
160
|
+
}]);
|
|
161
|
+
if (tryManual) {
|
|
162
|
+
const { key } = await (inquirer as any).prompt([
|
|
163
|
+
{ type: 'input', name: 'key', message: `ID/numero del canal ${channelLabel}:`, validate: (v: string) => v.length > 0 || 'Requerido' },
|
|
164
|
+
]);
|
|
165
|
+
channels.push({ channel: CHANNEL_AGENT_MAP[channelType], key, multianswer: false });
|
|
166
|
+
}
|
|
167
|
+
const { more } = await (inquirer as any).prompt([{ type: 'confirm', name: 'more', message: 'Conectar otro canal?', default: false }]);
|
|
168
|
+
addMore = more;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const shortUrl = linkRes.data.data?.shortUrl || '';
|
|
173
|
+
spinner.stop();
|
|
174
|
+
|
|
175
|
+
// Mostrar link
|
|
176
|
+
console.log();
|
|
177
|
+
console.log(chalk.hex('#4CAF50')(' ─'.repeat(32)));
|
|
178
|
+
console.log(chalk.bold(` Envia este link para conectar ${channelLabel}:`));
|
|
179
|
+
console.log();
|
|
180
|
+
console.log(' ' + chalk.hex('#22d3ee')(shortUrl));
|
|
181
|
+
console.log();
|
|
182
|
+
console.log(chalk.hex('#4CAF50')(' ─'.repeat(32)));
|
|
183
|
+
console.log();
|
|
184
|
+
|
|
185
|
+
// Snapshot de integraciones actuales
|
|
186
|
+
let prevIntegrationIds: Set<string> = new Set();
|
|
187
|
+
try {
|
|
188
|
+
const wkRes = await axios.get(`${baseUrl}/api/workspace/${ctx.workspaceId}`, { headers });
|
|
189
|
+
const integrations = wkRes.data?.integrations || [];
|
|
190
|
+
prevIntegrationIds = new Set(integrations.map((i: any) => i.id));
|
|
191
|
+
} catch {
|
|
192
|
+
// Si falla, se parte de vacio
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Polling para detectar nueva integracion
|
|
196
|
+
const pollSpinner = ora({ text: chalk.gray('Esperando conexion... (Ctrl+C para cancelar)'), spinner: 'dots', color: 'cyan' }).start();
|
|
197
|
+
const POLL_INTERVAL = 5000;
|
|
198
|
+
const MAX_POLLS = 60; // 5 minutos
|
|
199
|
+
let detected: any = null;
|
|
200
|
+
|
|
201
|
+
for (let i = 0; i < MAX_POLLS; i++) {
|
|
202
|
+
await new Promise(r => setTimeout(r, POLL_INTERVAL));
|
|
203
|
+
try {
|
|
204
|
+
const wkRes = await axios.get(`${baseUrl}/api/workspace/${ctx.workspaceId}`, { headers });
|
|
205
|
+
const integrations = wkRes.data?.integrations || [];
|
|
206
|
+
|
|
207
|
+
// Buscar integraciones nuevas (cualquier ID que no existia antes)
|
|
208
|
+
const newOnes = integrations.filter((ig: any) => !prevIntegrationIds.has(ig.id));
|
|
209
|
+
|
|
210
|
+
if (newOnes.length > 0) {
|
|
211
|
+
// Preferir la que coincida con el tipo solicitado
|
|
212
|
+
const targetType = channelType === 'whatsapp_business' ? 'whatsapp' : channelType;
|
|
213
|
+
const matchingNew = newOnes.find((ig: any) => ig.type === targetType);
|
|
214
|
+
detected = matchingNew || newOnes[0];
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
} catch {
|
|
218
|
+
// Ignorar errores de poll individual
|
|
219
|
+
}
|
|
220
|
+
const elapsed = Math.floor(((i + 1) * POLL_INTERVAL) / 1000);
|
|
221
|
+
pollSpinner.text = chalk.gray(`Esperando conexion... ${elapsed}s`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (detected) {
|
|
225
|
+
const detectedName = detected.aliasName || detected.cellphoneNumberFormat || detected.cellphoneNumber || detected.srcName || detected.id;
|
|
226
|
+
pollSpinner.succeed(chalk.hex('#4ade80')(`Conexion detectada: ${detectedName} (${channelLabel})`));
|
|
227
|
+
|
|
228
|
+
const { associate } = await (inquirer as any).prompt([{
|
|
229
|
+
type: 'confirm', name: 'associate',
|
|
230
|
+
message: 'Deseas asociar este canal al agente?', default: true,
|
|
231
|
+
}]);
|
|
232
|
+
|
|
233
|
+
if (associate) {
|
|
234
|
+
channels.push({
|
|
235
|
+
channel: CHANNEL_AGENT_MAP[channelType],
|
|
236
|
+
key: detected.id,
|
|
237
|
+
multianswer: false,
|
|
238
|
+
});
|
|
239
|
+
console.log(chalk.hex('#4ade80')(' Canal asociado correctamente.'));
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
pollSpinner.warn(chalk.hex('#FFA726')('Timeout: no se detecto una conexion.'));
|
|
243
|
+
const { action } = await (inquirer as any).prompt([{
|
|
244
|
+
type: 'list', name: 'action',
|
|
245
|
+
message: 'Que deseas hacer?',
|
|
246
|
+
choices: [
|
|
247
|
+
{ name: 'Ingresar numero/ID manualmente', value: 'manual' },
|
|
248
|
+
{ name: 'Saltar este paso', value: 'skip' },
|
|
249
|
+
],
|
|
250
|
+
}]);
|
|
251
|
+
if (action === 'manual') {
|
|
252
|
+
const { key } = await (inquirer as any).prompt([
|
|
253
|
+
{ type: 'input', name: 'key', message: `ID/numero del canal ${channelLabel}:`, validate: (v: string) => v.length > 0 || 'Requerido' },
|
|
254
|
+
]);
|
|
255
|
+
channels.push({ channel: CHANNEL_AGENT_MAP[channelType], key, multianswer: false });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
} catch (err) {
|
|
260
|
+
spinner.fail(chalk.hex('#EF5350')(`Error al generar link: ${err instanceof Error ? err.message : err}`));
|
|
261
|
+
const { tryManual } = await (inquirer as any).prompt([{
|
|
262
|
+
type: 'confirm', name: 'tryManual',
|
|
263
|
+
message: 'Deseas ingresar el numero manualmente?', default: false,
|
|
264
|
+
}]);
|
|
265
|
+
if (tryManual) {
|
|
266
|
+
const { key } = await (inquirer as any).prompt([
|
|
267
|
+
{ type: 'input', name: 'key', message: `ID/numero del canal ${channelLabel}:`, validate: (v: string) => v.length > 0 || 'Requerido' },
|
|
268
|
+
]);
|
|
269
|
+
channels.push({ channel: CHANNEL_AGENT_MAP[channelType], key, multianswer: false });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const { more } = await (inquirer as any).prompt([{ type: 'confirm', name: 'more', message: 'Conectar otro canal?', default: false }]);
|
|
274
|
+
addMore = more;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return channels;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export async function runAgentWizard(zone: string, workspaceId?: string, apiKey?: string, dev?: boolean): Promise<AgentConfig> {
|
|
98
281
|
console.log(section('Crear nuevo agente de IA'));
|
|
99
282
|
console.log(theme.muted(' Responde las siguientes preguntas para configurar tu agente.\n'));
|
|
100
283
|
|
|
@@ -369,31 +552,32 @@ export async function runAgentWizard(zone: string): Promise<AgentConfig> {
|
|
|
369
552
|
const aiConfig = await (inquirer as any).prompt([
|
|
370
553
|
{ type: 'list', name: 'model', message: 'Modelo:', choices: models },
|
|
371
554
|
{ type: 'password', name: 'apiToken', message: 'API Token:', mask: '*', validate: (v: string) => v.length > 0 || 'Requerido' },
|
|
372
|
-
{ type: 'number', name: 'temperature', message: 'Temperatura (0-2):', default: 0.7 },
|
|
373
|
-
{ type: 'number', name: 'maxTokens', message: 'Max tokens (1024-16384):', default: 4096 },
|
|
374
555
|
]);
|
|
375
556
|
|
|
376
557
|
aiProviders.push({
|
|
377
558
|
provider: ai.provider,
|
|
378
559
|
model: aiConfig.model,
|
|
379
560
|
apiToken: aiConfig.apiToken,
|
|
380
|
-
temperature:
|
|
381
|
-
maxTokens:
|
|
561
|
+
temperature: 0.7,
|
|
562
|
+
maxTokens: 4096,
|
|
382
563
|
isDefault: true,
|
|
383
564
|
});
|
|
384
565
|
}
|
|
385
566
|
|
|
386
|
-
// Paso 7:
|
|
387
|
-
console.log(theme.bold('\n Paso 7/8:
|
|
388
|
-
|
|
389
|
-
const {
|
|
567
|
+
// Paso 7: Conectar canal
|
|
568
|
+
console.log(theme.bold('\n Paso 7/8: Conectar canal'));
|
|
569
|
+
let channels: AgentChannel[] = [];
|
|
570
|
+
const { addChannel } = await (inquirer as any).prompt([{
|
|
390
571
|
type: 'confirm',
|
|
391
|
-
name: '
|
|
392
|
-
message: '
|
|
572
|
+
name: 'addChannel',
|
|
573
|
+
message: 'Deseas conectar un canal (WhatsApp, Instagram, Messenger)?',
|
|
393
574
|
default: false,
|
|
394
575
|
}]);
|
|
395
576
|
|
|
396
|
-
if (
|
|
577
|
+
if (addChannel && workspaceId && apiKey) {
|
|
578
|
+
channels = await connectChannelFlow({ zone, workspaceId, apiKey, dev: dev || false });
|
|
579
|
+
} else if (addChannel) {
|
|
580
|
+
// Fallback manual si no hay credenciales para API
|
|
397
581
|
const wa = await (inquirer as any).prompt([
|
|
398
582
|
{ type: 'input', name: 'key', message: 'Numero de WhatsApp (con codigo de pais):', validate: (v: string) => v.length > 0 || 'Requerido' },
|
|
399
583
|
{ type: 'confirm', name: 'multianswer', message: 'Permitir multiples respuestas?', default: false },
|
|
@@ -468,7 +652,13 @@ export async function runAgentWizard(zone: string): Promise<AgentConfig> {
|
|
|
468
652
|
console.log(kvPair('Servicios', String(config.services.length)));
|
|
469
653
|
console.log(kvPair('Acciones', String(config.actions.length)));
|
|
470
654
|
console.log(kvPair('AI Provider', config.customAIConfig ? config.aiProviders[0]?.provider + ' / ' + config.aiProviders[0]?.model : 'Default (Plazbot)'));
|
|
471
|
-
|
|
655
|
+
if (config.channels.length > 0) {
|
|
656
|
+
config.channels.forEach((ch, i) => {
|
|
657
|
+
console.log(kvPair(`Canal ${i + 1} (${ch.channel})`, ch.key));
|
|
658
|
+
});
|
|
659
|
+
} else {
|
|
660
|
+
console.log(kvPair('Canales', 'No configurado'));
|
|
661
|
+
}
|
|
472
662
|
console.log();
|
|
473
663
|
|
|
474
664
|
return config;
|