plazbot-cli 0.2.25 → 0.3.1

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.
Files changed (178) hide show
  1. package/CLAUDE.md +34 -5
  2. package/README.md +21 -0
  3. package/dist/cli.js +32 -20
  4. package/dist/commands/agent/ai-config.js +98 -50
  5. package/dist/commands/agent/chat.js +80 -74
  6. package/dist/commands/agent/copy.js +23 -21
  7. package/dist/commands/agent/create.js +42 -72
  8. package/dist/commands/agent/delete.js +29 -30
  9. package/dist/commands/agent/enable-widget.js +30 -26
  10. package/dist/commands/agent/export.js +90 -77
  11. package/dist/commands/agent/files.js +68 -60
  12. package/dist/commands/agent/get.js +101 -87
  13. package/dist/commands/agent/index.js +53 -39
  14. package/dist/commands/agent/list.js +26 -24
  15. package/dist/commands/agent/monitor.js +91 -86
  16. package/dist/commands/agent/on-message.js +40 -37
  17. package/dist/commands/agent/set.js +62 -59
  18. package/dist/commands/agent/templates.js +109 -108
  19. package/dist/commands/agent/tools.js +64 -65
  20. package/dist/commands/agent/update.js +28 -27
  21. package/dist/commands/agent/validate.js +127 -0
  22. package/dist/commands/agent/wizard.js +152 -159
  23. package/dist/commands/auth/index.js +7 -10
  24. package/dist/commands/auth/login.js +50 -37
  25. package/dist/commands/auth/logout.js +16 -14
  26. package/dist/commands/auth/status.js +19 -16
  27. package/dist/commands/portal/add-agent.js +26 -24
  28. package/dist/commands/portal/add-link.js +21 -17
  29. package/dist/commands/portal/clear-links.js +17 -15
  30. package/dist/commands/portal/create.js +25 -21
  31. package/dist/commands/portal/delete.js +31 -30
  32. package/dist/commands/portal/get.js +33 -31
  33. package/dist/commands/portal/index.js +30 -22
  34. package/dist/commands/portal/list.js +34 -30
  35. package/dist/commands/portal/update.js +41 -33
  36. package/dist/commands/whatsapp/broadcast.js +40 -37
  37. package/dist/commands/whatsapp/channels.js +40 -34
  38. package/dist/commands/whatsapp/chat.js +33 -32
  39. package/dist/commands/whatsapp/connect.js +59 -55
  40. package/dist/commands/whatsapp/delete-webhook.js +19 -17
  41. package/dist/commands/whatsapp/index.js +35 -25
  42. package/dist/commands/whatsapp/register-webhook.js +21 -19
  43. package/dist/commands/whatsapp/send-template.js +39 -31
  44. package/dist/commands/whatsapp/send.js +27 -23
  45. package/dist/commands/whatsapp/widget.js +35 -31
  46. package/dist/commands/workers/deploy.js +49 -44
  47. package/dist/commands/workers/index.js +28 -18
  48. package/dist/commands/workers/list.js +43 -35
  49. package/dist/commands/workers/logs.js +38 -32
  50. package/dist/commands/workers/remove.js +38 -37
  51. package/dist/commands/workers/secret.js +63 -58
  52. package/dist/commands/workers/test.js +44 -36
  53. package/dist/schemas/agent.config.schema.json +569 -0
  54. package/dist/studio/api/sseClient.js +97 -0
  55. package/dist/studio/api/studioApi.js +25 -0
  56. package/dist/studio/api/types.js +16 -0
  57. package/dist/studio/components/AgentPanel.js +35 -0
  58. package/dist/studio/components/App.js +214 -0
  59. package/dist/studio/components/ChatLog.js +59 -0
  60. package/dist/studio/components/Footer.js +11 -0
  61. package/dist/studio/components/Header.js +8 -0
  62. package/dist/studio/components/Input.js +15 -0
  63. package/dist/studio/components/Message.js +56 -0
  64. package/dist/studio/components/Suggestions.js +11 -0
  65. package/dist/studio/components/ToolCall.js +33 -0
  66. package/dist/studio/components/WhatsappConnectCard.js +57 -0
  67. package/dist/studio/index.js +42 -0
  68. package/dist/studio/render/json.js +16 -0
  69. package/dist/studio/render/markdown.js +32 -0
  70. package/dist/studio/render/steps.js +58 -0
  71. package/dist/studio/runOneShot.js +96 -0
  72. package/dist/studio/runRepl.js +52 -0
  73. package/dist/studio/slash/handlers.js +199 -0
  74. package/dist/studio/slash/parser.js +46 -0
  75. package/dist/studio/slash/registry.js +16 -0
  76. package/dist/studio/state/store.js +181 -0
  77. package/dist/studio/whatsapp/api.js +63 -0
  78. package/dist/studio/whatsapp/polling.js +77 -0
  79. package/dist/studio/whatsapp/types.js +31 -0
  80. package/dist/types/agent.js +1 -2
  81. package/dist/types/auth.js +1 -2
  82. package/dist/types/common.js +1 -2
  83. package/dist/types/message.js +1 -2
  84. package/dist/types/portal.js +1 -2
  85. package/dist/types/workers.js +1 -2
  86. package/dist/utils/agent-errors.js +46 -0
  87. package/dist/utils/api.js +8 -9
  88. package/dist/utils/banner.js +33 -34
  89. package/dist/utils/credentials.js +12 -20
  90. package/dist/utils/help.js +44 -0
  91. package/dist/utils/logger.js +13 -19
  92. package/dist/utils/ui.js +35 -49
  93. package/package.json +21 -10
  94. package/src/cli.ts +24 -8
  95. package/src/commands/agent/ai-config.ts +89 -34
  96. package/src/commands/agent/chat.ts +49 -37
  97. package/src/commands/agent/copy.ts +19 -13
  98. package/src/commands/agent/create.ts +32 -22
  99. package/src/commands/agent/delete.ts +24 -18
  100. package/src/commands/agent/enable-widget.ts +31 -23
  101. package/src/commands/agent/export.ts +72 -51
  102. package/src/commands/agent/files.ts +51 -39
  103. package/src/commands/agent/get.ts +86 -66
  104. package/src/commands/agent/index.ts +36 -18
  105. package/src/commands/agent/list.ts +22 -16
  106. package/src/commands/agent/monitor.ts +67 -56
  107. package/src/commands/agent/on-message.ts +36 -27
  108. package/src/commands/agent/set.ts +47 -37
  109. package/src/commands/agent/templates.ts +90 -82
  110. package/src/commands/agent/tools.ts +53 -47
  111. package/src/commands/agent/update.ts +28 -20
  112. package/src/commands/agent/validate.ts +135 -0
  113. package/src/commands/agent/wizard.ts +114 -114
  114. package/src/commands/auth/index.ts +3 -3
  115. package/src/commands/auth/login.ts +44 -29
  116. package/src/commands/auth/logout.ts +16 -10
  117. package/src/commands/auth/status.ts +14 -8
  118. package/src/commands/portal/add-agent.ts +23 -17
  119. package/src/commands/portal/add-link.ts +17 -9
  120. package/src/commands/portal/clear-links.ts +13 -7
  121. package/src/commands/portal/create.ts +20 -12
  122. package/src/commands/portal/delete.ts +28 -20
  123. package/src/commands/portal/get.ts +25 -19
  124. package/src/commands/portal/index.ts +22 -10
  125. package/src/commands/portal/list.ts +27 -19
  126. package/src/commands/portal/update.ts +38 -26
  127. package/src/commands/whatsapp/broadcast.ts +28 -18
  128. package/src/commands/whatsapp/channels.ts +31 -20
  129. package/src/commands/whatsapp/chat.ts +20 -12
  130. package/src/commands/whatsapp/connect.ts +48 -36
  131. package/src/commands/whatsapp/delete-webhook.ts +15 -9
  132. package/src/commands/whatsapp/index.ts +24 -10
  133. package/src/commands/whatsapp/register-webhook.ts +16 -10
  134. package/src/commands/whatsapp/send-template.ts +33 -21
  135. package/src/commands/whatsapp/send.ts +23 -15
  136. package/src/commands/whatsapp/widget.ts +25 -17
  137. package/src/commands/workers/deploy.ts +34 -22
  138. package/src/commands/workers/index.ts +21 -7
  139. package/src/commands/workers/list.ts +31 -19
  140. package/src/commands/workers/logs.ts +30 -20
  141. package/src/commands/workers/remove.ts +30 -22
  142. package/src/commands/workers/secret.ts +46 -34
  143. package/src/commands/workers/test.ts +34 -22
  144. package/src/schemas/agent.config.schema.json +569 -0
  145. package/src/studio/api/sseClient.ts +91 -0
  146. package/src/studio/api/studioApi.ts +27 -0
  147. package/src/studio/api/types.ts +96 -0
  148. package/src/studio/components/App.tsx +266 -0
  149. package/src/studio/components/ChatLog.tsx +95 -0
  150. package/src/studio/components/Footer.tsx +38 -0
  151. package/src/studio/components/Header.tsx +39 -0
  152. package/src/studio/components/Input.tsx +32 -0
  153. package/src/studio/components/Message.tsx +87 -0
  154. package/src/studio/components/Suggestions.tsx +26 -0
  155. package/src/studio/components/ToolCall.tsx +58 -0
  156. package/src/studio/components/WhatsappConnectCard.tsx +139 -0
  157. package/src/studio/index.ts +58 -0
  158. package/src/studio/render/markdown.ts +32 -0
  159. package/src/studio/render/steps.ts +57 -0
  160. package/src/studio/runOneShot.ts +114 -0
  161. package/src/studio/runRepl.tsx +76 -0
  162. package/src/studio/slash/handlers.ts +226 -0
  163. package/src/studio/slash/parser.ts +41 -0
  164. package/src/studio/slash/registry.ts +54 -0
  165. package/src/studio/state/store.ts +273 -0
  166. package/src/studio/whatsapp/api.ts +96 -0
  167. package/src/studio/whatsapp/polling.ts +93 -0
  168. package/src/studio/whatsapp/types.ts +80 -0
  169. package/src/types/agent.ts +1 -1
  170. package/src/types/auth.ts +4 -3
  171. package/src/types/portal.ts +1 -1
  172. package/src/types/workers.ts +1 -1
  173. package/src/utils/agent-errors.ts +67 -0
  174. package/src/utils/api.ts +6 -0
  175. package/src/utils/banner.ts +14 -9
  176. package/src/utils/credentials.ts +6 -5
  177. package/src/utils/help.ts +51 -0
  178. package/tsconfig.json +9 -6
@@ -1,94 +1,89 @@
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)
1
+ import { Command } from 'commander';
2
+ import { Agent } from 'plazbot';
3
+ import inquirer from 'inquirer';
4
+ import { getStoredCredentials } from '../../utils/credentials.js';
5
+ import { logger } from '../../utils/logger.js';
6
+ import { addExamples } from '../../utils/help.js';
7
+ import { createSpinner, createTable, theme, section, kvPair, statusBadge } from '../../utils/ui.js';
8
+ export const toolsCommand = new Command('tools')
9
+ .description('Manage agent Tool Calling tools')
10
+ .argument('<agentId>', 'Agent ID')
11
+ .option('--dev', 'Use development environment', false)
17
12
  .action(async (agentId, options) => {
18
13
  try {
19
- const credentials = await (0, credentials_1.getStoredCredentials)();
20
- const agent = new plazbot_1.Agent({
14
+ const credentials = await getStoredCredentials();
15
+ const agent = new Agent({
21
16
  workspaceId: credentials.workspace,
22
17
  apiKey: credentials.apiKey,
23
18
  zone: credentials.zone,
24
19
  ...(options.dev && { customUrl: "http://localhost:5090" })
25
20
  });
26
- const spinner = (0, ui_1.createSpinner)('Cargando agente...');
21
+ const spinner = createSpinner('Loading agent...');
27
22
  spinner.start();
28
23
  const _res = await agent.getAgentById({ id: agentId });
29
24
  const agentData = _res.agent || _res.data || _res;
30
25
  spinner.stop();
31
- console.log((0, ui_1.section)('Tool Calling - ' + (agentData.name || agentId)));
32
- console.log((0, ui_1.kvPair)('Estado', agentData.useToolCalling ? ui_1.theme.success('Activado') : ui_1.theme.error('Desactivado')));
26
+ console.log(section('Tool Calling - ' + (agentData.name || agentId)));
27
+ console.log(kvPair('Status', agentData.useToolCalling ? theme.success('Enabled') : theme.error('Disabled')));
33
28
  // Servicios
34
29
  const services = agentData.services || [];
35
30
  if (services.length > 0) {
36
- console.log((0, ui_1.section)('Servicios (API calls)'));
31
+ console.log(section('Services (API calls)'));
37
32
  const rows = services.map((s) => [
38
33
  s.intent,
39
34
  s.method || 'POST',
40
35
  s.endpoint ? s.endpoint.substring(0, 40) + '...' : 'N/A',
41
- (0, ui_1.statusBadge)(s.enabled !== false),
36
+ statusBadge(s.enabled !== false),
42
37
  ]);
43
- console.log((0, ui_1.createTable)(['Intent', 'Method', 'Endpoint', 'Estado'], rows));
38
+ console.log(createTable(['Intent', 'Method', 'Endpoint', 'Status'], rows));
44
39
  }
45
40
  else {
46
- console.log(ui_1.theme.muted('\n No hay servicios configurados'));
41
+ console.log(theme.muted('\n No services configured'));
47
42
  }
48
43
  // Acciones
49
44
  const actions = agentData.actions || [];
50
45
  if (actions.length > 0) {
51
- console.log((0, ui_1.section)('Acciones'));
46
+ console.log(section('Actions'));
52
47
  const rows = actions.map((a) => [
53
48
  a.intent,
54
49
  (a.action || []).map((ac) => ac.type).join(', '),
55
- (0, ui_1.statusBadge)(a.enabled !== false),
50
+ statusBadge(a.enabled !== false),
56
51
  ]);
57
- console.log((0, ui_1.createTable)(['Intent', 'Tipo', 'Estado'], rows));
52
+ console.log(createTable(['Intent', 'Type', 'Status'], rows));
58
53
  }
59
54
  else {
60
- console.log(ui_1.theme.muted('\n No hay acciones configuradas'));
55
+ console.log(theme.muted('\n No actions configured'));
61
56
  }
62
57
  // Menu de opciones
63
58
  console.log();
64
- const { action } = await inquirer_1.default.prompt([{
59
+ const { action } = await inquirer.prompt([{
65
60
  type: 'list',
66
61
  name: 'action',
67
- message: 'Que deseas hacer?',
62
+ message: 'What would you like to do?',
68
63
  choices: [
69
- { name: 'Agregar servicio (API call)', value: 'add-service' },
70
- { name: 'Agregar accion', value: 'add-action' },
71
- { name: agentData.useToolCalling ? 'Desactivar Tool Calling' : 'Activar Tool Calling', value: 'toggle' },
72
- { name: 'Salir', value: 'exit' },
64
+ { name: 'Add service (API call)', value: 'add-service' },
65
+ { name: 'Add action', value: 'add-action' },
66
+ { name: agentData.useToolCalling ? 'Disable Tool Calling' : 'Enable Tool Calling', value: 'toggle' },
67
+ { name: 'Exit', value: 'exit' },
73
68
  ],
74
69
  }]);
75
70
  if (action === 'exit')
76
71
  return;
77
72
  if (action === 'toggle') {
78
- const toggleSpinner = (0, ui_1.createSpinner)('Actualizando...');
73
+ const toggleSpinner = createSpinner('Updating...');
79
74
  toggleSpinner.start();
80
75
  const { id: _i1, _id: _o1, ...updatedConfig } = { ...agentData, useToolCalling: !agentData.useToolCalling };
81
76
  await agent.updateAgent(agentId, updatedConfig);
82
- toggleSpinner.succeed(`Tool Calling ${!agentData.useToolCalling ? 'activado' : 'desactivado'}`);
77
+ toggleSpinner.succeed(`Tool Calling ${!agentData.useToolCalling ? 'enabled' : 'disabled'}`);
83
78
  return;
84
79
  }
85
80
  if (action === 'add-service') {
86
- const svc = await inquirer_1.default.prompt([
87
- { type: 'input', name: 'intent', message: 'Nombre/intent del servicio:', validate: (v) => v.length > 0 || 'Requerido' },
88
- { type: 'input', name: 'reference', message: 'Palabras clave:', default: '' },
89
- { type: 'list', name: 'method', message: 'Metodo HTTP:', choices: ['GET', 'POST'] },
90
- { type: 'input', name: 'endpoint', message: 'URL del endpoint:', validate: (v) => v.length > 0 || 'Requerido' },
91
- { type: 'input', name: 'responseMessage', message: 'Mensaje de respuesta:', default: '' },
81
+ const svc = await inquirer.prompt([
82
+ { type: 'input', name: 'intent', message: 'Service name/intent:', validate: (v) => v.length > 0 || 'Required' },
83
+ { type: 'input', name: 'reference', message: 'Keywords:', default: '' },
84
+ { type: 'list', name: 'method', message: 'HTTP method:', choices: ['GET', 'POST'] },
85
+ { type: 'input', name: 'endpoint', message: 'Endpoint URL:', validate: (v) => v.length > 0 || 'Required' },
86
+ { type: 'input', name: 'responseMessage', message: 'Response message:', default: '' },
92
87
  ]);
93
88
  const newService = {
94
89
  intent: svc.intent,
@@ -105,32 +100,32 @@ exports.toolsCommand = new commander_1.Command('tools')
105
100
  };
106
101
  const updatedServices = [...services, newService];
107
102
  const { id: _i2, _id: _o2, ...updatedConfig } = { ...agentData, services: updatedServices, useToolCalling: true };
108
- const updateSpinner = (0, ui_1.createSpinner)('Guardando servicio...');
103
+ const updateSpinner = createSpinner('Saving service...');
109
104
  updateSpinner.start();
110
105
  await agent.updateAgent(agentId, updatedConfig);
111
- updateSpinner.succeed(`Servicio "${svc.intent}" agregado`);
106
+ updateSpinner.succeed(`Service "${svc.intent}" added`);
112
107
  }
113
108
  if (action === 'add-action') {
114
- const act = await inquirer_1.default.prompt([
115
- { type: 'input', name: 'intent', message: 'Nombre/intent de la accion:', validate: (v) => v.length > 0 || 'Requerido' },
116
- { type: 'input', name: 'reference', message: 'Palabras clave:', default: '' },
109
+ const act = await inquirer.prompt([
110
+ { type: 'input', name: 'intent', message: 'Action name/intent:', validate: (v) => v.length > 0 || 'Required' },
111
+ { type: 'input', name: 'reference', message: 'Keywords:', default: '' },
117
112
  {
118
- type: 'list', name: 'actionType', message: 'Tipo de accion:',
113
+ type: 'list', name: 'actionType', message: 'Action type:',
119
114
  choices: [
120
- { name: 'Agendar evento', value: 'action.event.add' },
121
- { name: 'Actualizar evento (reagendar)', value: 'action.event.update' },
122
- { name: 'Listar eventos', value: 'action.event.list' },
123
- { name: 'Eliminar evento (cancelar)', value: 'action.event.delete' },
124
- { name: 'Agregar tag', value: 'action.tag' },
125
- { name: 'Cambiar stage', value: 'action.stage' },
126
- { name: 'Derivar a agente humano', value: 'action.agentShutDown' },
127
- { name: 'Marcar como resuelto', value: 'action.solved' },
128
- { name: 'Asignar agente', value: 'action.asign' },
129
- { name: 'Segmentacion', value: 'action.segmentation' },
115
+ { name: 'Schedule event', value: 'action.event.add' },
116
+ { name: 'Update event (reschedule)', value: 'action.event.update' },
117
+ { name: 'List events', value: 'action.event.list' },
118
+ { name: 'Delete event (cancel)', value: 'action.event.delete' },
119
+ { name: 'Add tag', value: 'action.tag' },
120
+ { name: 'Change stage', value: 'action.stage' },
121
+ { name: 'Hand off to human agent', value: 'action.agentShutDown' },
122
+ { name: 'Mark as resolved', value: 'action.solved' },
123
+ { name: 'Assign agent', value: 'action.asign' },
124
+ { name: 'Segmentation', value: 'action.segmentation' },
130
125
  ],
131
126
  },
132
- { type: 'input', name: 'actionValue', message: 'Valor (opcional):', default: '' },
133
- { type: 'input', name: 'responseMessage', message: 'Mensaje de respuesta:', default: '' },
127
+ { type: 'input', name: 'actionValue', message: 'Value (optional):', default: '' },
128
+ { type: 'input', name: 'responseMessage', message: 'Response message:', default: '' },
134
129
  ]);
135
130
  const newAction = {
136
131
  intent: act.intent,
@@ -142,15 +137,19 @@ exports.toolsCommand = new commander_1.Command('tools')
142
137
  };
143
138
  const updatedActions = [...actions, newAction];
144
139
  const { id: _i3, _id: _o3, ...updatedConfig } = { ...agentData, actions: updatedActions, useToolCalling: true };
145
- const updateSpinner = (0, ui_1.createSpinner)('Guardando accion...');
140
+ const updateSpinner = createSpinner('Saving action...');
146
141
  updateSpinner.start();
147
142
  await agent.updateAgent(agentId, updatedConfig);
148
- updateSpinner.succeed(`Accion "${act.intent}" agregada`);
143
+ updateSpinner.succeed(`Action "${act.intent}" added`);
149
144
  }
150
145
  }
151
146
  catch (error) {
152
- const message = error instanceof Error ? error.message : 'Error desconocido';
153
- logger_1.logger.error(message);
147
+ const message = error instanceof Error ? error.message : 'Unknown error';
148
+ logger.error(message);
154
149
  process.exit(1);
155
150
  }
156
151
  });
152
+ addExamples(toolsCommand, [
153
+ { description: 'View services/actions and add new ones interactively',
154
+ command: 'plazbot agent tools agt_AbcDef123' },
155
+ ]);
@@ -1,52 +1,53 @@
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.updateCommand = 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 promises_1 = __importDefault(require("fs/promises"));
12
- exports.updateCommand = new commander_1.Command('update')
13
- .description('Actualiza un agente existente en Plazbot')
14
- .argument('<agentId>', 'ID del agente a actualizar')
15
- .argument('<configPath>', 'Ruta al archivo de configuración JSON del agente')
16
- .option('--dev', 'Usar ambiente de desarrollo', false)
1
+ import { Command } from 'commander';
2
+ import { Agent } from 'plazbot';
3
+ import { getStoredCredentials } from '../../utils/credentials.js';
4
+ import { logger } from '../../utils/logger.js';
5
+ import { addExamples } from '../../utils/help.js';
6
+ import fs from 'fs/promises';
7
+ export const updateCommand = new Command('update')
8
+ .description('Update an existing agent in Plazbot')
9
+ .argument('<agentId>', 'Agent ID to update')
10
+ .argument('<configPath>', 'Path to the agent JSON configuration file')
11
+ .option('--dev', 'Use development environment', false)
17
12
  .action(async (agentId, configPath, options) => {
18
13
  try {
19
14
  // Obtener credenciales guardadas
20
- const credentials = await (0, credentials_1.getStoredCredentials)();
15
+ const credentials = await getStoredCredentials();
21
16
  // Leer archivo de configuración del agente
22
17
  let agentConfig;
23
18
  try {
24
- const fileContent = await promises_1.default.readFile(configPath, 'utf-8');
19
+ const fileContent = await fs.readFile(configPath, 'utf-8');
25
20
  agentConfig = JSON.parse(fileContent);
26
21
  }
27
22
  catch (error) {
28
- const errorMessage = error instanceof Error ? error.message : 'Error desconocido';
29
- throw new Error(`Error al leer el archivo de configuración: ${errorMessage}`);
23
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
24
+ throw new Error(`Error reading configuration file: ${errorMessage}`);
30
25
  }
31
26
  // Crear instancia del agente con las credenciales guardadas
32
- const agent = new plazbot_1.Agent({
27
+ const agent = new Agent({
33
28
  workspaceId: credentials.workspace,
34
29
  apiKey: credentials.apiKey,
35
30
  zone: credentials.zone,
36
31
  ...(options.dev && { customUrl: "http://localhost:5090" })
37
32
  });
38
- logger_1.logger.dim('Actualizando agente...');
33
+ logger.dim('Updating agent...');
39
34
  // Actualizar el agente
40
35
  const result = await agent.updateAgent(agentId, agentConfig);
41
- logger_1.logger.success('Agente actualizado exitosamente');
42
- logger_1.logger.info(`Mensaje: ${result.message}`);
36
+ logger.success('Agent updated successfully');
37
+ logger.info(`Message: ${result.message}`);
43
38
  if (options.dev) {
44
- logger_1.logger.warning('Ambiente: desarrollo');
39
+ logger.warning('Environment: development');
45
40
  }
46
41
  }
47
42
  catch (error) {
48
- const message = error instanceof Error ? error.message : 'Error desconocido al actualizar el agente';
49
- logger_1.logger.error(message);
43
+ const message = error instanceof Error ? error.message : 'Unknown error while updating the agent';
44
+ logger.error(message);
50
45
  process.exit(1);
51
46
  }
52
47
  });
48
+ addExamples(updateCommand, [
49
+ { description: 'Push a new configuration to the agent',
50
+ command: 'plazbot agent update agt_AbcDef123 ./agent.json' },
51
+ { description: 'Tip: export → edit → update workflow',
52
+ command: 'plazbot agent export agt_AbcDef123 -o agent.json && plazbot agent update agt_AbcDef123 ./agent.json' },
53
+ ]);
@@ -0,0 +1,127 @@
1
+ import { Command } from 'commander';
2
+ import { readFileSync, existsSync } from 'node:fs';
3
+ import { resolve, dirname, join } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import Ajv from 'ajv';
6
+ import addFormats from 'ajv-formats';
7
+ import chalk from 'chalk';
8
+ import { logger } from '../../utils/logger.js';
9
+ import { addExamples } from '../../utils/help.js';
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+ // El schema se copia a dist/schemas durante el build.
13
+ // Buscar primero en dist/schemas (produccion) y luego en src/schemas (dev/ts-node).
14
+ function loadSchema() {
15
+ const candidates = [
16
+ join(__dirname, '..', '..', 'schemas', 'agent.config.schema.json'), // dist/commands/agent -> dist/schemas
17
+ join(__dirname, '..', '..', '..', 'src', 'schemas', 'agent.config.schema.json'), // fallback dev
18
+ ];
19
+ for (const candidate of candidates) {
20
+ if (existsSync(candidate)) {
21
+ return JSON.parse(readFileSync(candidate, 'utf-8'));
22
+ }
23
+ }
24
+ throw new Error('No se encontro el schema agent.config.schema.json. Reinstala el CLI.');
25
+ }
26
+ // Traduce una ruta de AJV (e.g. "/actions/0/action/2") en migas legibles
27
+ // estilo "acciones -> 0 -> action -> 2".
28
+ function humanizePath(instancePath) {
29
+ if (!instancePath || instancePath === '')
30
+ return '(raiz)';
31
+ return instancePath
32
+ .replace(/^\//, '')
33
+ .split('/')
34
+ .filter(Boolean)
35
+ .join(' -> ');
36
+ }
37
+ function formatError(err) {
38
+ const path = humanizePath(err.instancePath);
39
+ const keyword = err.keyword;
40
+ let detail = err.message || 'error de validacion';
41
+ if (keyword === 'required' && err.params && err.params.missingProperty) {
42
+ detail = `debe tener la propiedad requerida '${err.params.missingProperty}'`;
43
+ }
44
+ else if (keyword === 'enum' && err.params && err.params.allowedValues) {
45
+ const allowed = err.params.allowedValues;
46
+ detail = `debe ser uno de: ${allowed.join(', ')}`;
47
+ }
48
+ else if (keyword === 'type' && err.params && err.params.type) {
49
+ detail = `debe ser de tipo ${err.params.type}`;
50
+ }
51
+ else if (keyword === 'minLength') {
52
+ detail = 'no puede estar vacio';
53
+ }
54
+ else if (keyword === 'pattern') {
55
+ detail = `no cumple el patron ${err.params.pattern}`;
56
+ }
57
+ return `${path}: ${detail}`;
58
+ }
59
+ export const validateCommand = new Command('validate')
60
+ .description('Validate an agent JSON file against the official schema')
61
+ .argument('<file>', 'Path to the agent JSON file')
62
+ .option('--strict', 'Fail on additional unknown properties', false)
63
+ .option('--raw', 'Print raw AJV errors as JSON', false)
64
+ .action(async (file, options) => {
65
+ try {
66
+ const filePath = resolve(process.cwd(), file);
67
+ if (!existsSync(filePath)) {
68
+ logger.error(`No existe el archivo: ${filePath}`);
69
+ process.exit(1);
70
+ }
71
+ let data;
72
+ try {
73
+ data = JSON.parse(readFileSync(filePath, 'utf-8'));
74
+ }
75
+ catch (parseErr) {
76
+ const msg = parseErr instanceof Error ? parseErr.message : 'JSON invalido';
77
+ logger.error(`JSON con sintaxis invalida: ${msg}`);
78
+ process.exit(1);
79
+ }
80
+ const schema = loadSchema();
81
+ const ajv = new Ajv({
82
+ allErrors: true,
83
+ strict: false,
84
+ strictTypes: false,
85
+ });
86
+ addFormats(ajv);
87
+ const validate = ajv.compile(schema);
88
+ const ok = validate(data);
89
+ if (ok) {
90
+ console.log();
91
+ console.log(chalk.hex('#66BB6A')(' Schema valido'));
92
+ const name = data?.name ? ` (${data.name})` : '';
93
+ console.log(chalk.gray(` El agente${name} cumple con el schema oficial.`));
94
+ console.log();
95
+ return;
96
+ }
97
+ // Filtrar errores AJV redundantes generados por allOf/if-then:
98
+ // "must match 'then' schema" siempre acompana a un error real con misma path.
99
+ const rawErrors = validate.errors || [];
100
+ const errors = rawErrors.filter(e => e.keyword !== 'if' && !/match "then" schema/.test(e.message || ''));
101
+ if (options.raw) {
102
+ console.log(JSON.stringify(errors, null, 2));
103
+ process.exit(1);
104
+ }
105
+ console.log();
106
+ console.log(chalk.hex('#EF5350')(` Schema invalido (${errors.length} ${errors.length === 1 ? 'error' : 'errores'}):`));
107
+ console.log();
108
+ errors.forEach((err, i) => {
109
+ console.log(chalk.hex('#EF5350')(` ${i + 1}. ${formatError(err)}`));
110
+ });
111
+ console.log();
112
+ console.log(chalk.gray(' Sugerencia: usa --raw para inspeccionar los errores AJV en JSON.'));
113
+ console.log();
114
+ process.exit(1);
115
+ }
116
+ catch (error) {
117
+ const message = error instanceof Error ? error.message : 'Error desconocido';
118
+ logger.error(message);
119
+ process.exit(1);
120
+ }
121
+ });
122
+ addExamples(validateCommand, [
123
+ { description: 'Validate an exported agent file against the schema',
124
+ command: 'plazbot agent validate ./agent.json' },
125
+ { description: 'Print raw AJV errors as JSON for tooling',
126
+ command: 'plazbot agent validate ./agent.json --raw' },
127
+ ]);