plazbot-cli 0.2.26 → 0.3.2

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 +53 -52
  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 +86 -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 +22 -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 +39 -31
  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 +93 -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,18 +1,19 @@
1
1
  import { Command } from 'commander';
2
2
  import fs from 'fs/promises';
3
3
  import path from 'path';
4
- import { getStoredCredentials } from '../../utils/credentials';
5
- import { createApiClient } from '../../utils/api';
6
- import { logger } from '../../utils/logger';
7
- import { createSpinner, createTable, theme } from '../../utils/ui';
8
- import { WorkerDeployOptions, WorkerDeployResult } from '../../types/workers';
4
+ import { getStoredCredentials } from '../../utils/credentials.js';
5
+ import { createApiClient } from '../../utils/api.js';
6
+ import { logger } from '../../utils/logger.js';
7
+ import { addExamples } from '../../utils/help.js';
8
+ import { createSpinner, createTable, theme } from '../../utils/ui.js';
9
+ import { WorkerDeployOptions, WorkerDeployResult } from '../../types/workers.js';
9
10
 
10
11
  export const deployCommand = new Command('deploy')
11
- .description('Despliega un worker al workspace de Plazbot')
12
- .argument('[file]', 'Archivo TypeScript del worker (ej: ./workers/mi-tool.ts)')
13
- .option('-n, --name <name>', 'Nombre del worker (sobreescribe el del archivo)')
14
- .option('-d, --description <desc>', 'Descripcion del worker')
15
- .option('--dev', 'Usar ambiente de desarrollo', false)
12
+ .description('Deploy a worker to the Plazbot workspace')
13
+ .argument('[file]', 'Worker TypeScript file (e.g.: ./workers/my-tool.ts)')
14
+ .option('-n, --name <name>', 'Worker name (overrides the one in the file)')
15
+ .option('-d, --description <desc>', 'Worker description')
16
+ .option('--dev', 'Use development environment', false)
16
17
  .action(async (file: string | undefined, options: WorkerDeployOptions) => {
17
18
  try {
18
19
  const credentials = await getStoredCredentials();
@@ -21,9 +22,9 @@ export const deployCommand = new Command('deploy')
21
22
  const files = await resolveWorkerFiles(file);
22
23
 
23
24
  if (files.length === 0) {
24
- logger.error('No se encontraron archivos de workers para desplegar');
25
- logger.dim('Uso: plazbot workers deploy ./workers/mi-tool.ts');
26
- logger.dim(' o: plazbot workers deploy (busca en ./workers/ automaticamente)');
25
+ logger.error('No worker files found to deploy');
26
+ logger.dim('Usage: plazbot workers deploy ./workers/my-tool.ts');
27
+ logger.dim(' or: plazbot workers deploy (searches ./workers/ automatically)');
27
28
  process.exit(1);
28
29
  }
29
30
 
@@ -34,14 +35,14 @@ export const deployCommand = new Command('deploy')
34
35
  dev: options.dev,
35
36
  });
36
37
 
37
- logger.title(`Desplegando ${files.length} worker${files.length > 1 ? 's' : ''}`);
38
+ logger.title(`Deploying ${files.length} worker${files.length > 1 ? 's' : ''}`);
38
39
  console.log();
39
40
 
40
41
  const results: { file: string; result?: WorkerDeployResult; error?: string }[] = [];
41
42
 
42
43
  for (const filePath of files) {
43
44
  const fileName = path.basename(filePath);
44
- const spinner = createSpinner(`Desplegando ${fileName}...`);
45
+ const spinner = createSpinner(`Deploying ${fileName}...`);
45
46
  spinner.start();
46
47
 
47
48
  try {
@@ -61,7 +62,7 @@ export const deployCommand = new Command('deploy')
61
62
  results.push({ file: fileName, result: data });
62
63
 
63
64
  } catch (error: any) {
64
- const msg = error.response?.data?.message || error.message || 'Error desconocido';
65
+ const msg = error.response?.data?.message || error.message || 'Unknown error';
65
66
  spinner.fail(`${fileName}: ${msg}`);
66
67
  results.push({ file: fileName, error: msg });
67
68
  }
@@ -73,7 +74,7 @@ export const deployCommand = new Command('deploy')
73
74
  const failed = results.filter(r => r.error);
74
75
 
75
76
  if (success.length > 0) {
76
- logger.success(`${success.length} worker${success.length > 1 ? 's' : ''} desplegado${success.length > 1 ? 's' : ''}`);
77
+ logger.success(`${success.length} worker${success.length > 1 ? 's' : ''} deployed`);
77
78
 
78
79
  const rows = success.map(r => [
79
80
  r.result!.name,
@@ -83,13 +84,13 @@ export const deployCommand = new Command('deploy')
83
84
  ]);
84
85
 
85
86
  console.log(createTable(
86
- ['Nombre', 'Tipo', 'Estado', 'URL/Cron'],
87
+ ['Name', 'Type', 'Status', 'URL/Cron'],
87
88
  rows,
88
89
  ));
89
90
  }
90
91
 
91
92
  if (failed.length > 0) {
92
- logger.warning(`${failed.length} worker${failed.length > 1 ? 's' : ''} fallaron`);
93
+ logger.warning(`${failed.length} worker${failed.length > 1 ? 's' : ''} failed`);
93
94
  failed.forEach(f => logger.dim(` ${f.file}: ${f.error}`));
94
95
  }
95
96
 
@@ -106,16 +107,27 @@ export const deployCommand = new Command('deploy')
106
107
  console.log();
107
108
 
108
109
  if (options.dev) {
109
- logger.warning('Ambiente: desarrollo');
110
+ logger.warning('Environment: development');
110
111
  }
111
112
 
112
113
  } catch (error) {
113
- const message = error instanceof Error ? error.message : 'Error desconocido';
114
+ const message = error instanceof Error ? error.message : 'Unknown error';
114
115
  logger.error(message);
115
116
  process.exit(1);
116
117
  }
117
118
  });
118
119
 
120
+ addExamples(deployCommand, [
121
+ { description: 'Deploy a single worker file',
122
+ command: 'plazbot workers deploy ./workers/my-tool.ts' },
123
+ { description: 'Deploy every TypeScript file inside ./workers automatically',
124
+ command: 'plazbot workers deploy' },
125
+ { description: 'Deploy with a custom name and description',
126
+ command: 'plazbot workers deploy ./workers/cron.ts -n "Daily Report" -d "Generates daily KPIs"' },
127
+ { description: 'Deploy against the local backend',
128
+ command: 'plazbot workers deploy ./workers/test.ts --dev' },
129
+ ]);
130
+
119
131
  // Resuelve los archivos a desplegar
120
132
  async function resolveWorkerFiles(file?: string): Promise<string[]> {
121
133
  if (file) {
@@ -125,7 +137,7 @@ async function resolveWorkerFiles(file?: string): Promise<string[]> {
125
137
  await fs.access(resolved);
126
138
  return [resolved];
127
139
  } catch {
128
- throw new Error(`Archivo no encontrado: ${file}`);
140
+ throw new Error(`File not found: ${file}`);
129
141
  }
130
142
  }
131
143
 
@@ -1,16 +1,30 @@
1
1
  import { Command } from 'commander';
2
- import { deployCommand } from './deploy';
3
- import { listCommand } from './list';
4
- import { logsCommand } from './logs';
5
- import { removeCommand } from './remove';
6
- import { secretCommand } from './secret';
7
- import { testCommand } from './test';
2
+ import { addExamples } from '../../utils/help.js';
3
+ import { deployCommand } from './deploy.js';
4
+ import { listCommand } from './list.js';
5
+ import { logsCommand } from './logs.js';
6
+ import { removeCommand } from './remove.js';
7
+ import { secretCommand } from './secret.js';
8
+ import { testCommand } from './test.js';
8
9
 
9
10
  export const workersCommands = new Command('workers')
10
- .description('Comandos para gestionar workers (tools, syncs, schedules, webhooks)')
11
+ .description('Commands to manage workers (tools, syncs, schedules, webhooks)')
11
12
  .addCommand(deployCommand)
12
13
  .addCommand(listCommand)
13
14
  .addCommand(logsCommand)
14
15
  .addCommand(removeCommand)
15
16
  .addCommand(secretCommand)
16
17
  .addCommand(testCommand);
18
+
19
+ addExamples(workersCommands, [
20
+ { description: 'Deploy every worker file in ./workers automatically',
21
+ command: 'plazbot workers deploy' },
22
+ { description: 'List active workers',
23
+ command: 'plazbot workers list -s active' },
24
+ { description: 'Run a worker with a JSON payload',
25
+ command: 'plazbot workers test my-tool -p \'{"product":"iPhone 15"}\'' },
26
+ { description: 'Save a secret for workers (plz.env.KEY)',
27
+ command: 'plazbot workers secret set STRIPE_API_KEY sk_live_xxxxx' },
28
+ { description: 'View the last 100 executions of a worker',
29
+ command: 'plazbot workers logs my-tool -l 100' },
30
+ ]);
@@ -1,15 +1,16 @@
1
1
  import { Command } from 'commander';
2
- import { getStoredCredentials } from '../../utils/credentials';
3
- import { createApiClient } from '../../utils/api';
4
- import { logger } from '../../utils/logger';
5
- import { createSpinner, createTable, theme, statusBadge, formatDate } from '../../utils/ui';
6
- import { WorkerListOptions, WorkerListItem } from '../../types/workers';
2
+ import { getStoredCredentials } from '../../utils/credentials.js';
3
+ import { createApiClient } from '../../utils/api.js';
4
+ import { logger } from '../../utils/logger.js';
5
+ import { addExamples } from '../../utils/help.js';
6
+ import { createSpinner, createTable, theme, statusBadge, formatDate } from '../../utils/ui.js';
7
+ import { WorkerListOptions, WorkerListItem } from '../../types/workers.js';
7
8
 
8
9
  export const listCommand = new Command('list')
9
- .description('Lista todos los workers del workspace')
10
- .option('-t, --type <type>', 'Filtrar por tipo (tool, worker, sync, schedule, webhook)')
11
- .option('-s, --status <status>', 'Filtrar por estado (active, inactive, error)')
12
- .option('--dev', 'Usar ambiente de desarrollo', false)
10
+ .description('List all workers in the workspace')
11
+ .option('-t, --type <type>', 'Filter by type (tool, worker, sync, schedule, webhook)')
12
+ .option('-s, --status <status>', 'Filter by status (active, inactive, error)')
13
+ .option('--dev', 'Use development environment', false)
13
14
  .action(async (options: WorkerListOptions) => {
14
15
  try {
15
16
  const credentials = await getStoredCredentials();
@@ -20,7 +21,7 @@ export const listCommand = new Command('list')
20
21
  dev: options.dev,
21
22
  });
22
23
 
23
- const spinner = createSpinner('Obteniendo workers...');
24
+ const spinner = createSpinner('Fetching workers...');
24
25
  spinner.start();
25
26
 
26
27
  const params: Record<string, string> = {};
@@ -33,8 +34,8 @@ export const listCommand = new Command('list')
33
34
  spinner.stop();
34
35
 
35
36
  if (!workers || workers.length === 0) {
36
- logger.info('\n No se encontraron workers en este workspace');
37
- logger.dim(' Despliega tu primer worker: plazbot workers deploy ./workers/mi-tool.ts');
37
+ logger.info('\n No workers found in this workspace');
38
+ logger.dim(' Deploy your first worker: plazbot workers deploy ./workers/my-tool.ts');
38
39
  console.log();
39
40
  return;
40
41
  }
@@ -44,9 +45,9 @@ export const listCommand = new Command('list')
44
45
  const rows = workers.map(w => [
45
46
  w.name,
46
47
  typeLabel(w.type),
47
- w.status === 'active' ? theme.success('activo')
48
+ w.status === 'active' ? theme.success('active')
48
49
  : w.status === 'error' ? theme.error('error')
49
- : theme.muted('inactivo'),
50
+ : theme.muted('inactive'),
50
51
  `${w.executionCount}`,
51
52
  w.errorCount > 0 ? theme.error(`${w.errorCount}`) : theme.muted('0'),
52
53
  w.avgDurationMs > 0 ? `${w.avgDurationMs}ms` : '—',
@@ -54,7 +55,7 @@ export const listCommand = new Command('list')
54
55
  ]);
55
56
 
56
57
  console.log(createTable(
57
- ['Nombre', 'Tipo', 'Estado', 'Ejecuciones', 'Errores', 'Duracion', 'Ultima ejecucion'],
58
+ ['Name', 'Type', 'Status', 'Executions', 'Errors', 'Duration', 'Last execution'],
58
59
  rows,
59
60
  ));
60
61
 
@@ -62,25 +63,36 @@ export const listCommand = new Command('list')
62
63
  const errored = workers.filter(w => w.status === 'error');
63
64
  if (errored.length > 0) {
64
65
  console.log();
65
- logger.warning('Workers con error:');
66
+ logger.warning('Workers with errors:');
66
67
  errored.forEach(w => {
67
- logger.dim(` ${w.name}: ${w.lastError || 'sin detalles'}`);
68
+ logger.dim(` ${w.name}: ${w.lastError || 'no details'}`);
68
69
  });
69
70
  }
70
71
 
71
72
  console.log();
72
73
 
73
74
  if (options.dev) {
74
- logger.warning('Ambiente: desarrollo');
75
+ logger.warning('Environment: development');
75
76
  }
76
77
 
77
78
  } catch (error) {
78
- const message = error instanceof Error ? error.message : 'Error desconocido';
79
+ const message = error instanceof Error ? error.message : 'Unknown error';
79
80
  logger.error(message);
80
81
  process.exit(1);
81
82
  }
82
83
  });
83
84
 
85
+ addExamples(listCommand, [
86
+ { description: 'List every worker in the workspace',
87
+ command: 'plazbot workers list' },
88
+ { description: 'Only show schedules',
89
+ command: 'plazbot workers list -t schedule' },
90
+ { description: 'Show only workers with errors',
91
+ command: 'plazbot workers list -s error' },
92
+ { description: 'Filter active webhooks',
93
+ command: 'plazbot workers list -t webhook -s active' },
94
+ ]);
95
+
84
96
  function typeLabel(type: string): string {
85
97
  const labels: Record<string, string> = {
86
98
  tool: theme.secondary('tool'),
@@ -1,16 +1,17 @@
1
1
  import { Command } from 'commander';
2
- import { getStoredCredentials } from '../../utils/credentials';
3
- import { createApiClient } from '../../utils/api';
4
- import { logger } from '../../utils/logger';
5
- import { createSpinner, createTable, theme, formatDate } from '../../utils/ui';
6
- import { WorkerLogsOptions, WorkerLogItem } from '../../types/workers';
2
+ import { getStoredCredentials } from '../../utils/credentials.js';
3
+ import { createApiClient } from '../../utils/api.js';
4
+ import { logger } from '../../utils/logger.js';
5
+ import { addExamples } from '../../utils/help.js';
6
+ import { createSpinner, createTable, theme, formatDate } from '../../utils/ui.js';
7
+ import { WorkerLogsOptions, WorkerLogItem } from '../../types/workers.js';
7
8
 
8
9
  export const logsCommand = new Command('logs')
9
- .description('Ver logs de ejecucion de un worker')
10
- .argument('<name>', 'Nombre del worker')
11
- .option('-l, --limit <number>', 'Numero de logs a mostrar', '20')
12
- .option('-s, --status <status>', 'Filtrar por estado (success, error, timeout)')
13
- .option('--dev', 'Usar ambiente de desarrollo', false)
10
+ .description('View execution logs for a worker')
11
+ .argument('<name>', 'Worker name')
12
+ .option('-l, --limit <number>', 'Number of logs to display', '20')
13
+ .option('-s, --status <status>', 'Filter by status (success, error, timeout)')
14
+ .option('--dev', 'Use development environment', false)
14
15
  .action(async (name: string, options: WorkerLogsOptions) => {
15
16
  try {
16
17
  const credentials = await getStoredCredentials();
@@ -21,7 +22,7 @@ export const logsCommand = new Command('logs')
21
22
  dev: options.dev,
22
23
  });
23
24
 
24
- const spinner = createSpinner(`Obteniendo logs de "${name}"...`);
25
+ const spinner = createSpinner(`Fetching logs for "${name}"...`);
25
26
  spinner.start();
26
27
 
27
28
  const params: Record<string, string> = {
@@ -35,12 +36,12 @@ export const logsCommand = new Command('logs')
35
36
  spinner.stop();
36
37
 
37
38
  if (!logs || logs.length === 0) {
38
- logger.info(`\n No se encontraron logs para "${name}"`);
39
+ logger.info(`\n No logs found for "${name}"`);
39
40
  console.log();
40
41
  return;
41
42
  }
42
43
 
43
- logger.title(`Logs de "${name}" (${logs.length})`);
44
+ logger.title(`Logs for "${name}" (${logs.length})`);
44
45
 
45
46
  const rows = logs.map(log => [
46
47
  formatDate(log.createdAt),
@@ -53,7 +54,7 @@ export const logsCommand = new Command('logs')
53
54
  ]);
54
55
 
55
56
  console.log(createTable(
56
- ['Fecha', 'Estado', 'Duracion', 'Origen', 'Error'],
57
+ ['Date', 'Status', 'Duration', 'Source', 'Error'],
57
58
  rows,
58
59
  ));
59
60
 
@@ -63,26 +64,35 @@ export const logsCommand = new Command('logs')
63
64
  const avgDuration = Math.round(logs.reduce((sum, l) => sum + l.durationMs, 0) / logs.length);
64
65
 
65
66
  console.log();
66
- logger.label('Exitosos', theme.success(`${successCount}`));
67
- logger.label('Errores', errorCount > 0 ? theme.error(`${errorCount}`) : theme.muted('0'));
68
- logger.label('Duracion promedio', `${avgDuration}ms`);
67
+ logger.label('Successful', theme.success(`${successCount}`));
68
+ logger.label('Errors', errorCount > 0 ? theme.error(`${errorCount}`) : theme.muted('0'));
69
+ logger.label('Average duration', `${avgDuration}ms`);
69
70
  console.log();
70
71
 
71
72
  if (options.dev) {
72
- logger.warning('Ambiente: desarrollo');
73
+ logger.warning('Environment: development');
73
74
  }
74
75
 
75
76
  } catch (error: any) {
76
77
  if (error.response?.status === 404) {
77
- logger.error(`Worker "${name}" no encontrado`);
78
+ logger.error(`Worker "${name}" not found`);
78
79
  } else {
79
- const message = error instanceof Error ? error.message : 'Error desconocido';
80
+ const message = error instanceof Error ? error.message : 'Unknown error';
80
81
  logger.error(message);
81
82
  }
82
83
  process.exit(1);
83
84
  }
84
85
  });
85
86
 
87
+ addExamples(logsCommand, [
88
+ { description: 'Show the last 20 executions of a worker',
89
+ command: 'plazbot workers logs my-tool' },
90
+ { description: 'Get the last 100 executions',
91
+ command: 'plazbot workers logs my-tool -l 100' },
92
+ { description: 'Only show failed executions',
93
+ command: 'plazbot workers logs my-tool -s error' },
94
+ ]);
95
+
86
96
  function truncate(text: string, max: number): string {
87
97
  if (text.length <= max) return text;
88
98
  return text.substring(0, max - 3) + '...';
@@ -1,16 +1,17 @@
1
1
  import { Command } from 'commander';
2
- import { getStoredCredentials } from '../../utils/credentials';
3
- import { createApiClient } from '../../utils/api';
4
- import { logger } from '../../utils/logger';
5
- import { createSpinner } from '../../utils/ui';
6
- import { WorkerRemoveOptions } from '../../types/workers';
2
+ import { getStoredCredentials } from '../../utils/credentials.js';
3
+ import { createApiClient } from '../../utils/api.js';
4
+ import { logger } from '../../utils/logger.js';
5
+ import { addExamples } from '../../utils/help.js';
6
+ import { createSpinner } from '../../utils/ui.js';
7
+ import { WorkerRemoveOptions } from '../../types/workers.js';
7
8
  import readline from 'readline';
8
9
 
9
10
  export const removeCommand = new Command('remove')
10
- .description('Elimina un worker del workspace')
11
- .argument('<name>', 'Nombre del worker a eliminar')
12
- .option('-f, --force', 'Eliminar sin confirmacion', false)
13
- .option('--dev', 'Usar ambiente de desarrollo', false)
11
+ .description('Delete a worker from the workspace')
12
+ .argument('<name>', 'Name of the worker to delete')
13
+ .option('-f, --force', 'Delete without confirmation', false)
14
+ .option('--dev', 'Use development environment', false)
14
15
  .action(async (name: string, options: WorkerRemoveOptions) => {
15
16
  try {
16
17
  const credentials = await getStoredCredentials();
@@ -22,7 +23,7 @@ export const removeCommand = new Command('remove')
22
23
  });
23
24
 
24
25
  // Verificar que el worker existe
25
- const spinner = createSpinner(`Buscando worker "${name}"...`);
26
+ const spinner = createSpinner(`Looking up worker "${name}"...`);
26
27
  spinner.start();
27
28
 
28
29
  let workerInfo: any;
@@ -33,7 +34,7 @@ export const removeCommand = new Command('remove')
33
34
  } catch (error: any) {
34
35
  spinner.stop();
35
36
  if (error.response?.status === 404) {
36
- logger.error(`Worker "${name}" no encontrado`);
37
+ logger.error(`Worker "${name}" not found`);
37
38
  } else {
38
39
  logger.error(error.response?.data?.message || error.message);
39
40
  }
@@ -41,45 +42,52 @@ export const removeCommand = new Command('remove')
41
42
  }
42
43
 
43
44
  // Mostrar info del worker
44
- logger.warning(`\n Vas a eliminar el siguiente worker:`);
45
+ logger.warning(`\n You are about to delete the following worker:`);
45
46
  logger.divider();
46
- logger.label('Nombre', workerInfo.name);
47
- logger.label('Tipo', workerInfo.type);
48
- logger.label('Estado', workerInfo.status);
49
- logger.label('Ejecuciones', `${workerInfo.executionCount || 0}`);
47
+ logger.label('Name', workerInfo.name);
48
+ logger.label('Type', workerInfo.type);
49
+ logger.label('Status', workerInfo.status);
50
+ logger.label('Executions', `${workerInfo.executionCount || 0}`);
50
51
  logger.divider();
51
52
 
52
53
  // Confirmacion
53
54
  if (!options.force) {
54
55
  const confirmed = await askConfirmation(
55
- `Eliminar worker "${name}"? Esta accion no se puede deshacer (y/N): `
56
+ `Delete worker "${name}"? This action cannot be undone (y/N): `
56
57
  );
57
58
 
58
59
  if (!confirmed) {
59
- logger.info('\n Operacion cancelada');
60
+ logger.info('\n Operation cancelled');
60
61
  process.exit(0);
61
62
  }
62
63
  }
63
64
 
64
- const deleteSpinner = createSpinner(`Eliminando "${name}"...`);
65
+ const deleteSpinner = createSpinner(`Deleting "${name}"...`);
65
66
  deleteSpinner.start();
66
67
 
67
68
  await api.delete(`/api/worker/${encodeURIComponent(name)}`);
68
69
 
69
- deleteSpinner.succeed(`Worker "${name}" eliminado`);
70
+ deleteSpinner.succeed(`Worker "${name}" deleted`);
70
71
  console.log();
71
72
 
72
73
  if (options.dev) {
73
- logger.warning('Ambiente: desarrollo');
74
+ logger.warning('Environment: development');
74
75
  }
75
76
 
76
77
  } catch (error) {
77
- const message = error instanceof Error ? error.message : 'Error desconocido';
78
+ const message = error instanceof Error ? error.message : 'Unknown error';
78
79
  logger.error(message);
79
80
  process.exit(1);
80
81
  }
81
82
  });
82
83
 
84
+ addExamples(removeCommand, [
85
+ { description: 'Delete a worker with confirmation prompt',
86
+ command: 'plazbot workers remove my-tool' },
87
+ { description: 'Delete without confirmation (scripts/CI)',
88
+ command: 'plazbot workers remove my-tool -f' },
89
+ ]);
90
+
83
91
  function askConfirmation(question: string): Promise<boolean> {
84
92
  return new Promise((resolve) => {
85
93
  const rl = readline.createInterface({