plazbot-cli 0.2.3 → 0.2.5

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.
@@ -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
- logger_1.logger.label('WhatsApp', agentConfig.channels[0].key);
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
- // Crear instancia del agente con las credenciales guardadas
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: credentials.workspace,
28
+ workspaceId: effectiveWorkspace,
19
29
  apiKey: credentials.apiKey,
20
- zone: credentials.zone,
30
+ zone: effectiveZone,
21
31
  ...(options.dev && { customUrl: "http://localhost:5090" })
22
32
  });
23
- // Obtener detalles del agente
24
- const agentData = await agent.getAgentById({ id: agentId });
25
- logger_1.logger.info('\nDetalles del Agente:');
26
- logger_1.logger.doubleDivider();
27
- // Información básica
28
- logger_1.logger.info('Información Básica:');
29
- logger_1.logger.divider();
30
- logger_1.logger.info(`ID: ${agentData.id}`);
31
- logger_1.logger.info(`Nombre: ${agentData.name}`);
32
- logger_1.logger.info(`Descripción: ${agentData.description}`);
33
- logger_1.logger.info(`Estado: ${agentData.enable ? 'Activo' : 'Inactivo'}`);
34
- logger_1.logger.info(`Zona: ${agentData.zone}`);
35
- logger_1.logger.info(`Buffer: ${agentData.buffer}`);
36
- logger_1.logger.info(`Color: ${agentData.color}`);
37
- logger_1.logger.info(`Pregunta inicial: ${agentData.question}`);
38
- logger_1.logger.info(`Zona horaria: ${agentData.timezone}`);
39
- logger_1.logger.info(`Mostrar en chat: ${agentData.showInChat ? 'Sí' : 'No'}`);
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
- logger_1.logger.info(`\nTags: ${agentData.tags.join(', ')}`);
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
- logger_1.logger.info('\nEjemplos:');
47
- logger_1.logger.divider();
82
+ sectionHeader('Ejemplos');
48
83
  agentData.examples.forEach((example) => {
49
- logger_1.logger.info(`- ${example.value} (${example.color})`);
84
+ console.log(chalk_1.default.white(` - ${example.value || example}`));
50
85
  });
51
86
  }
52
87
  // Instrucciones
53
88
  if (agentData.instructions) {
54
- logger_1.logger.info('\nInstrucciones:');
55
- logger_1.logger.divider();
56
- const instructions = agentData.instructions;
57
- logger_1.logger.info(`Tono: ${instructions.tone}`);
58
- logger_1.logger.info(`Estilo: ${instructions.style}`);
59
- logger_1.logger.info(`Personalidad: ${instructions.personality}`);
60
- logger_1.logger.info(`Objetivo: ${instructions.objective}`);
61
- logger_1.logger.info(`Idioma: ${instructions.language}`);
62
- logger_1.logger.info(`Emojis: ${instructions.emojis ? 'Sí' : 'No'}`);
63
- logger_1.logger.info(`Formato preferido: ${instructions.preferredFormat}`);
64
- logger_1.logger.info(`Máximo de palabras: ${instructions.maxWords}`);
65
- if (instructions.avoidTopics) {
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
- logger_1.logger.info(`Responder solo si sabe: ${instructions.respondOnlyIfKnows ? '' : 'No'}`);
69
- logger_1.logger.info(`Mantener tono entre mensajes: ${instructions.maintainToneBetweenMessages ? '' : 'No'}`);
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
- logger_1.logger.info('\nPersona:');
75
- logger_1.logger.divider();
76
- const person = agentData.person;
77
- logger_1.logger.info(`Nombre: ${person.name}`);
78
- logger_1.logger.info(`Rol: ${person.role}`);
79
- logger_1.logger.info(`Habla en primera persona: ${person.speaksInFirstPerson ? '' : 'No'}`);
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
- logger_1.logger.info('\nFallbacks:');
85
- logger_1.logger.divider();
86
- const fallbacks = agentData.fallbacks;
87
- logger_1.logger.info(`Sin respuesta: ${fallbacks.noAnswer}`);
88
- logger_1.logger.info(`Error de servicio: ${fallbacks.serviceError}`);
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
- logger_1.logger.info('\nReglas:');
94
- logger_1.logger.divider();
95
- const rules = agentData.rules;
96
- logger_1.logger.info(`No mencionar precios: ${rules.doNotMentionPrices ? '' : 'No'}`);
97
- logger_1.logger.info(`No diagnosticar: ${rules.doNotDiagnose ? 'Sí' : 'No'}`);
98
- if (rules.doNotRespondOutsideHours) {
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
- logger_1.logger.info('\nServicios:');
105
- logger_1.logger.divider();
106
- agentData.services.forEach((service, index) => {
107
- logger_1.logger.info(`\nServicio ${index + 1}:`);
108
- logger_1.logger.info(`Intent: ${service.intent}`);
109
- logger_1.logger.info(`Referencia: ${service.reference}`);
110
- logger_1.logger.info(`Habilitado: ${service.enabled ? '' : 'No'}`);
111
- logger_1.logger.info(`Método: ${service.method}`);
112
- logger_1.logger.info(`Endpoint: ${service.endpoint}`);
113
- if (service.requiredFields) {
114
- logger_1.logger.info('Campos requeridos:');
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
- logger_1.logger.info('\nAcciones:');
124
- logger_1.logger.divider();
125
- agentData.actions.forEach((action, index) => {
126
- logger_1.logger.info(`\nAcción ${index + 1}:`);
127
- logger_1.logger.info(`Intent: ${action.intent}`);
128
- logger_1.logger.info(`Referencia: ${action.reference}`);
129
- logger_1.logger.info(`Habilitado: ${action.enabled ? 'Sí' : 'No'}`);
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
- logger_1.logger.info(`Mensaje de respuesta: ${action.responseMessage}`);
134
- if (action.action) {
135
- logger_1.logger.info('Sub-acciones:');
136
- action.action.forEach((subAction) => {
137
- logger_1.logger.info(` - ${subAction.type}: ${subAction.value}`);
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
- logger_1.logger.info('\nCanales:');
145
- logger_1.logger.divider();
146
- agentData.channels.forEach((channel) => {
147
- logger_1.logger.info(`${channel.channel}: ${channel.key}`);
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
- logger_1.logger.doubleDivider();
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
  }
@@ -16,6 +16,7 @@ const templates_1 = require("./templates");
16
16
  const copy_1 = require("./copy");
17
17
  const files_1 = require("./files");
18
18
  const set_1 = require("./set");
19
+ const monitor_1 = require("./monitor");
19
20
  exports.agentCommands = new commander_1.Command('agent')
20
21
  .description('Comandos relacionados con agentes de IA')
21
22
  .addCommand(list_1.listCommand)
@@ -31,4 +32,5 @@ exports.agentCommands = new commander_1.Command('agent')
31
32
  .addCommand(templates_1.templatesCommand)
32
33
  .addCommand(copy_1.copyCommand)
33
34
  .addCommand(files_1.filesCommand)
34
- .addCommand(set_1.setCommand);
35
+ .addCommand(set_1.setCommand)
36
+ .addCommand(monitor_1.monitorCommand);
@@ -0,0 +1,299 @@
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.monitorCommand = 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 chalk_1 = __importDefault(require("chalk"));
12
+ const readline_1 = __importDefault(require("readline"));
13
+ const signalr_1 = require("@microsoft/signalr");
14
+ // Colores por tipo de evento (mismos del MonitorTab frontend)
15
+ const EVENT_COLORS = {
16
+ msg_in: { color: '#22d3ee', label: 'msg_in' },
17
+ msg_out: { color: '#4ade80', label: 'msg_out' },
18
+ tool_call: { color: '#c084fc', label: 'tool_call' },
19
+ api_req: { color: '#fbbf24', label: 'api_req' },
20
+ api_res: { color: '#fbbf24', label: 'api_res' },
21
+ action: { color: '#f97316', label: 'action' },
22
+ rag: { color: '#60a5fa', label: 'rag' },
23
+ tokens: { color: '#94a3b8', label: 'tokens' },
24
+ error: { color: '#ef4444', label: 'error' },
25
+ model: { color: '#a78bfa', label: 'model' },
26
+ intent: { color: '#a78bfa', label: 'intent' },
27
+ bot_off: { color: '#f97316', label: 'bot_off' },
28
+ session_field: { color: '#a78bfa', label: 'session_field' },
29
+ };
30
+ const DEFAULT_EVENT_COLOR = { color: '#94a3b8', label: 'unknown' };
31
+ function getBaseUrl(zone, dev) {
32
+ if (dev)
33
+ return 'http://localhost:5090';
34
+ return zone === 'EU' ? 'https://apieu.plazbot.com' : 'https://api.plazbot.com';
35
+ }
36
+ function formatTimestamp(ts) {
37
+ try {
38
+ const d = new Date(ts);
39
+ return d.toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
40
+ }
41
+ catch {
42
+ return ts.substring(11, 19);
43
+ }
44
+ }
45
+ function truncate(text, maxLen) {
46
+ if (!text)
47
+ return '';
48
+ return text.length > maxLen ? text.substring(0, maxLen - 3) + '...' : text;
49
+ }
50
+ function shortSession(sessionId) {
51
+ if (!sessionId)
52
+ return '';
53
+ return sessionId.substring(0, 6);
54
+ }
55
+ function renderLogLine(log, opts, lastSessionId) {
56
+ // Modo JSON crudo
57
+ if (opts.jsonMode) {
58
+ return JSON.stringify(log);
59
+ }
60
+ const config = EVENT_COLORS[log.event_type] || DEFAULT_EVENT_COLOR;
61
+ const colorFn = chalk_1.default.hex(config.color);
62
+ const grayFn = chalk_1.default.hex('#71717a');
63
+ const dimFn = chalk_1.default.hex('#52525b');
64
+ let lines = [];
65
+ // Separador de sesion
66
+ if (lastSessionId && log.session_id && log.session_id !== lastSessionId) {
67
+ lines.push(dimFn(' ' + '─'.repeat(16) + ' nueva sesion ' + '─'.repeat(16)));
68
+ }
69
+ // Linea principal
70
+ const timestamp = grayFn(formatTimestamp(log.timestamp));
71
+ const dot = colorFn('●');
72
+ const eventType = colorFn(config.label.padEnd(14));
73
+ const title = chalk_1.default.white(truncate(log.event_title, 80));
74
+ const duration = log.duration_ms > 0 ? dimFn(` ${log.duration_ms}ms`) : '';
75
+ const session = opts.showSession && log.session_id
76
+ ? dimFn(` [${shortSession(log.session_id)}]`)
77
+ : '';
78
+ lines.push(` ${timestamp} ${dot} ${eventType} ${title}${duration}${session}`);
79
+ // Linea de contacto para mensajes
80
+ if (log.contact_name && (log.event_type === 'msg_in' || log.event_type === 'msg_out')) {
81
+ lines.push(dimFn(' | contacto: ') + dimFn(log.contact_name));
82
+ }
83
+ return lines.join('\n');
84
+ }
85
+ function printHeader(agentName) {
86
+ console.log();
87
+ console.log(chalk_1.default.hex('#4CAF50')(' ┌' + '─'.repeat(62) + '┐'));
88
+ console.log(chalk_1.default.hex('#4CAF50')(' │') +
89
+ chalk_1.default.bold(` Monitor`) +
90
+ chalk_1.default.hex('#4ade80')(' ● En vivo') +
91
+ ' '.repeat(38) +
92
+ chalk_1.default.hex('#4CAF50')('│'));
93
+ console.log(chalk_1.default.hex('#4CAF50')(' │') +
94
+ chalk_1.default.gray(` Agente: ${truncate(agentName, 44)}`) +
95
+ ' '.repeat(Math.max(0, 49 - agentName.length)) +
96
+ chalk_1.default.hex('#4CAF50')('│'));
97
+ console.log(chalk_1.default.hex('#4CAF50')(' │') +
98
+ chalk_1.default.gray(' Ctrl+C salir | /filter <tipo> | /clear | /help') +
99
+ ' '.repeat(12) +
100
+ chalk_1.default.hex('#4CAF50')('│'));
101
+ console.log(chalk_1.default.hex('#4CAF50')(' └' + '─'.repeat(62) + '┘'));
102
+ console.log();
103
+ }
104
+ const COMMANDS_HELP = `
105
+ ${chalk_1.default.bold('Comandos disponibles:')}
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
108
+ ${chalk_1.default.hex('#4CAF50')('/filters')} Mostrar filtros activos
109
+ ${chalk_1.default.hex('#4CAF50')('/clear')} Limpiar pantalla
110
+ ${chalk_1.default.hex('#4CAF50')('/json')} Toggle modo JSON expandido
111
+ ${chalk_1.default.hex('#4CAF50')('/help')} Mostrar estos comandos
112
+
113
+ ${chalk_1.default.bold('Tipos de evento:')}
114
+ ${Object.entries(EVENT_COLORS).map(([key, val]) => ` ${chalk_1.default.hex(val.color)('●')} ${key}`).join('\n')}
115
+ `;
116
+ exports.monitorCommand = new commander_1.Command('monitor')
117
+ .description('Monitor en tiempo real de un agente (logs via SignalR)')
118
+ .requiredOption('-a, --agent-id <id>', 'ID del agente')
119
+ .option('-f, --filter <types>', 'Filtrar por tipos separados por coma (ej: msg_in,msg_out)')
120
+ .option('--no-session', 'Ocultar session ID')
121
+ .option('--json', 'Modo JSON crudo (para piping)', false)
122
+ .option('--dev', 'Usar ambiente de desarrollo', false)
123
+ .action(async (options) => {
124
+ try {
125
+ const credentials = await (0, credentials_1.getStoredCredentials)();
126
+ const baseUrl = getBaseUrl(credentials.zone, options.dev);
127
+ // Filtros iniciales
128
+ const activeFilters = new Set(options.filter ? options.filter.split(',').map(f => f.trim()) : []);
129
+ let jsonMode = options.json;
130
+ let lastSessionId = '';
131
+ // Cargar info del agente
132
+ let agentName = 'Agente';
133
+ try {
134
+ process.stdout.write(chalk_1.default.gray(' Conectando con agente...'));
135
+ const agent = new plazbot_1.Agent({
136
+ workspaceId: credentials.workspace,
137
+ apiKey: credentials.apiKey,
138
+ zone: credentials.zone,
139
+ ...(options.dev && { customUrl: 'http://localhost:5090' }),
140
+ });
141
+ const info = await agent.getAgentById({ id: options.agentId });
142
+ if (info?.name)
143
+ agentName = info.name;
144
+ process.stdout.write('\r' + ' '.repeat(40) + '\r');
145
+ }
146
+ catch {
147
+ process.stdout.write('\r' + ' '.repeat(40) + '\r');
148
+ }
149
+ // Dibujar header
150
+ if (!jsonMode) {
151
+ console.clear();
152
+ printHeader(agentName);
153
+ }
154
+ // Conectar a SignalR
155
+ const hubUrl = `${baseUrl}/agentMonitorHub`;
156
+ const connection = new signalr_1.HubConnectionBuilder()
157
+ .withUrl(hubUrl, {
158
+ skipNegotiation: true,
159
+ transport: signalr_1.HttpTransportType.WebSockets,
160
+ })
161
+ .withAutomaticReconnect([0, 2000, 5000, 10000, 30000])
162
+ .build();
163
+ // Evento de log
164
+ connection.on('agent_log', (log) => {
165
+ // Aplicar filtros
166
+ if (activeFilters.size > 0 && !activeFilters.has(log.event_type))
167
+ return;
168
+ const line = renderLogLine(log, {
169
+ showSession: options.session,
170
+ jsonMode,
171
+ }, lastSessionId);
172
+ console.log(line);
173
+ lastSessionId = log.session_id || lastSessionId;
174
+ });
175
+ // Eventos de conexion
176
+ connection.onreconnecting(() => {
177
+ if (!jsonMode) {
178
+ console.log(chalk_1.default.hex('#FFA726')(' ⟳ Reconectando...'));
179
+ }
180
+ });
181
+ connection.onreconnected(() => {
182
+ if (!jsonMode) {
183
+ console.log(chalk_1.default.hex('#4ade80')(' ● Reconectado'));
184
+ }
185
+ connection.invoke('JoinAgentMonitor', options.agentId).catch(() => { });
186
+ });
187
+ connection.onclose(() => {
188
+ if (!jsonMode) {
189
+ console.log(chalk_1.default.hex('#ef4444')(' ● Desconectado'));
190
+ }
191
+ });
192
+ // Iniciar conexion
193
+ try {
194
+ await connection.start();
195
+ await connection.invoke('JoinAgentMonitor', options.agentId);
196
+ if (!jsonMode) {
197
+ console.log(chalk_1.default.hex('#4ade80')(' ● Conectado al monitor en tiempo real'));
198
+ console.log();
199
+ }
200
+ }
201
+ catch (err) {
202
+ logger_1.logger.error(`No se pudo conectar al monitor: ${err instanceof Error ? err.message : err}`);
203
+ process.exit(1);
204
+ }
205
+ // readline para comandos interactivos
206
+ const rl = readline_1.default.createInterface({
207
+ input: process.stdin,
208
+ output: process.stdout,
209
+ prompt: '',
210
+ });
211
+ // No mostrar prompt para no interferir con el stream
212
+ rl.on('line', (input) => {
213
+ const cmd = input.trim().toLowerCase();
214
+ if (cmd === '/help') {
215
+ console.log(COMMANDS_HELP);
216
+ return;
217
+ }
218
+ if (cmd === '/clear') {
219
+ console.clear();
220
+ printHeader(agentName);
221
+ return;
222
+ }
223
+ if (cmd === '/json') {
224
+ jsonMode = !jsonMode;
225
+ console.log(chalk_1.default.gray(` Modo JSON: ${jsonMode ? 'activado' : 'desactivado'}`));
226
+ return;
227
+ }
228
+ if (cmd === '/filters') {
229
+ if (activeFilters.size === 0) {
230
+ console.log(chalk_1.default.gray(' Sin filtros activos (mostrando todos)'));
231
+ }
232
+ else {
233
+ console.log(chalk_1.default.gray(' Filtros activos: ') + chalk_1.default.white([...activeFilters].join(', ')));
234
+ }
235
+ return;
236
+ }
237
+ if (cmd.startsWith('/filter ')) {
238
+ const filterType = cmd.substring(8).trim();
239
+ if (!filterType) {
240
+ console.log(chalk_1.default.gray(' Uso: /filter <tipo> | /filter clear'));
241
+ return;
242
+ }
243
+ if (filterType === 'clear') {
244
+ activeFilters.clear();
245
+ console.log(chalk_1.default.gray(' Todos los filtros removidos (mostrando todos)'));
246
+ return;
247
+ }
248
+ if (activeFilters.has(filterType)) {
249
+ activeFilters.delete(filterType);
250
+ console.log(chalk_1.default.gray(` Filtro removido: ${filterType}`));
251
+ }
252
+ else {
253
+ activeFilters.add(filterType);
254
+ const config = EVENT_COLORS[filterType];
255
+ if (config) {
256
+ console.log(chalk_1.default.hex(config.color)(` ● Filtro agregado: ${filterType}`));
257
+ }
258
+ else {
259
+ console.log(chalk_1.default.gray(` Filtro agregado: ${filterType} (tipo desconocido)`));
260
+ }
261
+ }
262
+ if (activeFilters.size > 0) {
263
+ console.log(chalk_1.default.gray(' Activos: ') + chalk_1.default.white([...activeFilters].join(', ')));
264
+ }
265
+ else {
266
+ console.log(chalk_1.default.gray(' Sin filtros (mostrando todos)'));
267
+ }
268
+ return;
269
+ }
270
+ });
271
+ // Cierre limpio
272
+ const cleanup = async () => {
273
+ if (!jsonMode) {
274
+ console.log(chalk_1.default.gray('\n Cerrando monitor...'));
275
+ }
276
+ try {
277
+ if (connection.state === signalr_1.HubConnectionState.Connected) {
278
+ await connection.invoke('LeaveAgentMonitor', options.agentId);
279
+ }
280
+ await connection.stop();
281
+ }
282
+ catch {
283
+ // Ignorar errores al cerrar
284
+ }
285
+ rl.close();
286
+ if (!jsonMode) {
287
+ console.log(chalk_1.default.gray(' Monitor cerrado.\n'));
288
+ }
289
+ process.exit(0);
290
+ };
291
+ process.on('SIGINT', cleanup);
292
+ process.on('SIGTERM', cleanup);
293
+ }
294
+ catch (error) {
295
+ const message = error instanceof Error ? error.message : 'Error desconocido';
296
+ logger_1.logger.error(message);
297
+ process.exit(1);
298
+ }
299
+ });