plazbot-cli 0.4.0 → 0.5.0

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 (76) hide show
  1. package/README.md +67 -111
  2. package/dist/cli.js +26 -11
  3. package/dist/commands/agent/ai-config.js +264 -63
  4. package/dist/commands/agent/chat.js +16 -11
  5. package/dist/commands/agent/copy.js +49 -13
  6. package/dist/commands/agent/create.js +62 -17
  7. package/dist/commands/agent/delete.js +50 -39
  8. package/dist/commands/agent/enable-widget.js +47 -27
  9. package/dist/commands/agent/export.js +179 -88
  10. package/dist/commands/agent/files.js +155 -73
  11. package/dist/commands/agent/get.js +24 -16
  12. package/dist/commands/agent/index.js +12 -10
  13. package/dist/commands/agent/list.js +20 -11
  14. package/dist/commands/agent/monitor.js +101 -53
  15. package/dist/commands/agent/on-message.js +55 -32
  16. package/dist/commands/agent/set.js +230 -82
  17. package/dist/commands/agent/templates.js +259 -156
  18. package/dist/commands/agent/tools.js +356 -123
  19. package/dist/commands/agent/update.js +69 -28
  20. package/dist/commands/agent/validate.js +72 -40
  21. package/dist/commands/agent/wizard.js +240 -329
  22. package/dist/commands/auth/browser-login.js +37 -31
  23. package/dist/commands/auth/login.js +49 -45
  24. package/dist/commands/auth/logout.js +20 -11
  25. package/dist/commands/auth/status.js +36 -12
  26. package/dist/commands/auth/workspace.js +61 -27
  27. package/dist/commands/portal/add-agent.js +106 -45
  28. package/dist/commands/portal/add-link.js +25 -28
  29. package/dist/commands/portal/clear-links.js +39 -19
  30. package/dist/commands/portal/create.js +66 -37
  31. package/dist/commands/portal/delete.js +40 -45
  32. package/dist/commands/portal/get.js +21 -54
  33. package/dist/commands/portal/index.js +12 -12
  34. package/dist/commands/portal/list.js +34 -52
  35. package/dist/commands/portal/shared.js +92 -0
  36. package/dist/commands/portal/update.js +100 -70
  37. package/dist/commands/whatsapp/broadcast.js +169 -77
  38. package/dist/commands/whatsapp/channels.js +167 -65
  39. package/dist/commands/whatsapp/chat.js +45 -46
  40. package/dist/commands/whatsapp/connect-flow.js +16 -15
  41. package/dist/commands/whatsapp/connect.js +36 -21
  42. package/dist/commands/whatsapp/delete-webhook.js +42 -25
  43. package/dist/commands/whatsapp/index.js +15 -16
  44. package/dist/commands/whatsapp/register-webhook.js +43 -26
  45. package/dist/commands/whatsapp/send-template.js +62 -61
  46. package/dist/commands/whatsapp/send.js +46 -33
  47. package/dist/commands/whatsapp/setup.js +62 -52
  48. package/dist/commands/whatsapp/shared.js +75 -0
  49. package/dist/commands/whatsapp/widget.js +82 -45
  50. package/dist/commands/workers/deploy.js +80 -58
  51. package/dist/commands/workers/index.js +8 -8
  52. package/dist/commands/workers/list.js +42 -20
  53. package/dist/commands/workers/logs.js +139 -36
  54. package/dist/commands/workers/remove.js +45 -47
  55. package/dist/commands/workers/secret.js +159 -83
  56. package/dist/commands/workers/test.js +108 -60
  57. package/dist/schemas/agent.config.schema.json +183 -8
  58. package/dist/studio/api/sseClient.js +1 -1
  59. package/dist/studio/api/studioApi.js +8 -0
  60. package/dist/studio/components/App.js +12 -0
  61. package/dist/studio/components/Footer.js +1 -1
  62. package/dist/studio/index.js +77 -14
  63. package/dist/studio/runOneShot.js +62 -23
  64. package/dist/studio/runRepl.js +5 -5
  65. package/dist/studio/slash/handlers.js +11 -8
  66. package/dist/studio/state/store.js +1 -1
  67. package/dist/utils/agent-errors.js +14 -11
  68. package/dist/utils/agent-patch.js +60 -0
  69. package/dist/utils/banner.js +9 -5
  70. package/dist/utils/confirm.js +31 -0
  71. package/dist/utils/credentials.js +13 -3
  72. package/dist/utils/logger.js +13 -10
  73. package/dist/utils/output.js +78 -0
  74. package/dist/utils/phone.js +22 -0
  75. package/dist/utils/ui.js +14 -11
  76. package/package.json +2 -2
@@ -2,44 +2,63 @@ import { Command } from 'commander';
2
2
  import { Agent } from 'plazbot';
3
3
  import { getStoredCredentials } from '../../utils/credentials.js';
4
4
  import { logger } from '../../utils/logger.js';
5
- import { addExamples } from '../../utils/help.js';
5
+ import { addExamples, addNotes } from '../../utils/help.js';
6
6
  import { createSpinner, createTable, theme, section } from '../../utils/ui.js';
7
+ import { jsonOption, isJsonMode, printJson, fail, CliError } from '../../utils/output.js';
8
+ import { addYesOption, confirmAction } from '../../utils/confirm.js';
9
+ function buildAgent(credentials, dev) {
10
+ return new Agent({
11
+ workspaceId: credentials.workspace,
12
+ apiKey: credentials.apiKey,
13
+ zone: credentials.zone,
14
+ ...(dev && { customUrl: "http://localhost:5090" })
15
+ });
16
+ }
7
17
  const filesGroup = new Command('files')
8
18
  .description('Manage files in the agent knowledge base');
9
19
  addExamples(filesGroup, [
10
20
  { description: 'List the knowledge-base files of an agent',
11
- command: 'plazbot agent files list agt_AbcDef123' },
12
- { description: 'Add a remote PDF/DOC to the knowledge base',
13
- command: 'plazbot agent files add agt_AbcDef123 -u https://files.example.com/manual.pdf -r manual -t docs,onboarding' },
21
+ command: 'plazbot agent files list age_AbcDef123' },
22
+ { description: 'Add a remote PDF/DOC/DOCX to the knowledge base',
23
+ command: 'plazbot agent files add age_AbcDef123 -u https://files.example.com/manual.pdf -r manual -t docs,onboarding' },
14
24
  { description: 'Check whether a file finished processing',
15
- command: 'plazbot agent files status file_AbcDef123' },
25
+ command: 'plazbot agent files status fil_AbcDef123' },
16
26
  { description: 'Remove a file from the knowledge base',
17
- command: 'plazbot agent files delete agt_AbcDef123 file_AbcDef123' },
27
+ command: 'plazbot agent files delete age_AbcDef123 fil_AbcDef123' },
18
28
  ]);
19
29
  // Listar archivos
20
- filesGroup.command('list')
21
- .description('List agent files')
30
+ const listCmd = filesGroup.command('list')
31
+ .description('List the files in the knowledge base of an agent')
22
32
  .argument('<agentId>', 'Agent ID')
33
+ .addOption(jsonOption('Print the files as a JSON array (fileId, name, tags)'))
23
34
  .option('--dev', 'Use development environment', false)
24
35
  .action(async (agentId, options) => {
25
36
  try {
26
37
  const credentials = await getStoredCredentials();
27
- const agent = new Agent({
28
- workspaceId: credentials.workspace,
29
- apiKey: credentials.apiKey,
30
- zone: credentials.zone,
31
- ...(options.dev && { customUrl: "http://localhost:5090" })
32
- });
38
+ const agent = buildAgent(credentials, options.dev);
33
39
  const spinner = createSpinner('Loading files...');
34
40
  spinner.start();
35
- const _res = await agent.getAgentById({ id: agentId });
36
- const agentData = _res.agent || _res.data || _res;
37
- spinner.stop();
38
- const files = agentData.files || [];
41
+ let agentData;
42
+ try {
43
+ const res = await agent.getAgentById({ id: agentId });
44
+ agentData = res?.agent || res?.data || res || {};
45
+ }
46
+ finally {
47
+ spinner.stop();
48
+ }
49
+ const files = Array.isArray(agentData.files) ? agentData.files : [];
50
+ if (isJsonMode()) {
51
+ printJson(files.map((f) => ({
52
+ fileId: f.fileId || f.id || null,
53
+ name: f.name || f.reference || null,
54
+ tags: Array.isArray(f.tags) ? f.tags : [],
55
+ })));
56
+ return;
57
+ }
39
58
  console.log(section('Files - ' + (agentData.name || agentId)));
40
59
  if (files.length === 0) {
41
- console.log(theme.muted('\n No files in the knowledge base'));
42
- console.log(theme.muted(' Use: plazbot agent files add <agentId> --url <url>\n'));
60
+ console.log(theme.muted('\n No files in the knowledge base.'));
61
+ console.log(theme.muted(` Add one with: plazbot agent files add ${agentId} -u <url>\n`));
43
62
  return;
44
63
  }
45
64
  const rows = files.map((f) => [
@@ -50,102 +69,165 @@ filesGroup.command('list')
50
69
  console.log(createTable(['ID', 'Name', 'Tags'], rows));
51
70
  }
52
71
  catch (error) {
53
- const message = error instanceof Error ? error.message : 'Unknown error';
54
- logger.error(message);
55
- process.exit(1);
72
+ fail(error);
56
73
  }
57
74
  });
75
+ addExamples(listCmd, [
76
+ { description: 'List the files of an agent', command: 'plazbot agent files list age_AbcDef123' },
77
+ { description: 'Print the files as JSON', command: 'plazbot agent files list age_AbcDef123 --json' },
78
+ ]);
58
79
  // Agregar archivo
59
- filesGroup.command('add')
60
- .description('Add a file to the knowledge base')
80
+ const addCmd = filesGroup.command('add')
81
+ .description('Add a remote file (PDF, DOC, DOCX) to the knowledge base')
61
82
  .argument('<agentId>', 'Agent ID')
62
- .requiredOption('-u, --url <url>', 'File URL (PDF, DOC, DOCX)')
63
- .option('-r, --reference <name>', 'Reference name', 'documento')
64
- .option('-t, --tags <tags>', 'Comma-separated tags', '')
83
+ .requiredOption('-u, --url <url>', 'Public http(s) URL of the file (PDF, DOC, DOCX)')
84
+ .option('-r, --reference <name>', 'Reference name shown in the knowledge base (default: the file name)')
85
+ .option('-t, --tags <tags>', 'Comma-separated tags, e.g. docs,onboarding', '')
86
+ .addOption(jsonOption('Print the result as JSON ({"fileId","agentId","reference","status"})'))
65
87
  .option('--dev', 'Use development environment', false)
66
88
  .action(async (agentId, options) => {
67
89
  try {
90
+ let parsed;
91
+ try {
92
+ parsed = new URL(options.url);
93
+ }
94
+ catch {
95
+ throw new CliError(`Invalid URL "${options.url}".`, 'invalid_url', 'Pass a public link, e.g. -u https://files.example.com/manual.pdf');
96
+ }
97
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
98
+ throw new CliError('The file URL must start with http:// or https://.', 'invalid_url');
99
+ }
100
+ const fileName = decodeURIComponent(parsed.pathname.split('/').pop() || '');
101
+ const ext = fileName.includes('.') ? fileName.split('.').pop().toLowerCase() : '';
102
+ if (ext && !['pdf', 'doc', 'docx'].includes(ext)) {
103
+ logger.warning(`The file extension ".${ext}" may not be supported (expected PDF, DOC or DOCX).`);
104
+ }
105
+ const reference = options.reference?.trim() || fileName.replace(/\.[^.]+$/, '') || 'document';
68
106
  const credentials = await getStoredCredentials();
69
- const agent = new Agent({
70
- workspaceId: credentials.workspace,
71
- apiKey: credentials.apiKey,
72
- zone: credentials.zone,
73
- ...(options.dev && { customUrl: "http://localhost:5090" })
74
- });
75
- const spinner = createSpinner('Uploading file...');
107
+ const agent = buildAgent(credentials, options.dev);
108
+ const spinner = createSpinner('Adding file...');
76
109
  spinner.start();
77
- const tags = options.tags ? options.tags.split(',').map((t) => t.trim()) : [];
78
- const result = await agent.addFile({
79
- fileUrl: options.url,
80
- reference: options.reference,
81
- agentId,
82
- tags,
83
- });
110
+ const tags = options.tags ? options.tags.split(',').map((t) => t.trim()).filter(Boolean) : [];
111
+ let result;
112
+ try {
113
+ result = await agent.addFile({ fileUrl: options.url, reference, agentId, tags });
114
+ }
115
+ catch (err) {
116
+ spinner.fail('Could not add the file');
117
+ throw err;
118
+ }
119
+ if (result?.success === false) {
120
+ spinner.fail('Could not add the file');
121
+ throw new CliError(result.message || 'The API rejected the file.', 'add_file_failed');
122
+ }
84
123
  spinner.succeed('File added');
124
+ if (isJsonMode()) {
125
+ printJson({ fileId: result?.fileId ?? null, agentId, reference, status: 'processing' });
126
+ return;
127
+ }
128
+ logger.label('Reference', reference);
85
129
  if (result?.fileId) {
86
130
  logger.label('File ID', result.fileId);
87
- logger.dim('The file is being processed. Check status with:');
131
+ logger.dim('The file is being processed. Check the status with:');
88
132
  logger.dim(`plazbot agent files status ${result.fileId}`);
89
133
  }
90
134
  }
91
135
  catch (error) {
92
- const message = error instanceof Error ? error.message : 'Unknown error';
93
- logger.error(message);
94
- process.exit(1);
136
+ fail(error);
95
137
  }
96
138
  });
139
+ addExamples(addCmd, [
140
+ { description: 'Add a PDF manual',
141
+ command: 'plazbot agent files add age_AbcDef123 -u https://files.example.com/manual.pdf' },
142
+ { description: 'Add a file with a reference name and tags',
143
+ command: 'plazbot agent files add age_AbcDef123 -u https://files.example.com/prices.docx -r prices -t sales,2026' },
144
+ ]);
145
+ addNotes(addCmd, [
146
+ 'The URL must be publicly reachable. Processing is asynchronous: check it with "plazbot agent files status <fileId>".',
147
+ ]);
97
148
  // Verificar estado
98
- filesGroup.command('status')
149
+ const statusCmd = filesGroup.command('status')
99
150
  .description('Check the processing status of a file')
100
- .argument('<fileId>', 'File ID')
151
+ .argument('<fileId>', 'File ID (from "files add" or "files list")')
152
+ .addOption(jsonOption('Print the status as JSON ({"fileId","status"})'))
101
153
  .option('--dev', 'Use development environment', false)
102
154
  .action(async (fileId, options) => {
103
155
  try {
104
156
  const credentials = await getStoredCredentials();
105
- const agent = new Agent({
106
- workspaceId: credentials.workspace,
107
- apiKey: credentials.apiKey,
108
- zone: credentials.zone,
109
- ...(options.dev && { customUrl: "http://localhost:5090" })
110
- });
157
+ const agent = buildAgent(credentials, options.dev);
111
158
  const spinner = createSpinner('Checking...');
112
159
  spinner.start();
113
- const result = await agent.validateFile({ fileId });
114
- spinner.stop();
160
+ let result;
161
+ try {
162
+ result = await agent.validateFile({ fileId });
163
+ }
164
+ finally {
165
+ spinner.stop();
166
+ }
167
+ // La API devuelve status truthy cuando el archivo ya fue procesado
168
+ const raw = result?.status;
169
+ const processing = !raw || (typeof raw === 'string' && /process|pending|queue/i.test(raw));
170
+ const status = processing ? 'processing' : 'completed';
171
+ if (isJsonMode()) {
172
+ printJson({ fileId, status });
173
+ return;
174
+ }
115
175
  logger.title('File status');
116
176
  logger.label('File ID', fileId);
117
- logger.label('Status', result?.status ? 'Completed' : 'Processing');
177
+ logger.label('Status', status === 'completed' ? 'Completed' : 'Processing');
118
178
  }
119
179
  catch (error) {
120
- const message = error instanceof Error ? error.message : 'Unknown error';
121
- logger.error(message);
122
- process.exit(1);
180
+ fail(error);
123
181
  }
124
182
  });
183
+ addExamples(statusCmd, [
184
+ { description: 'Check a file', command: 'plazbot agent files status fil_AbcDef123' },
185
+ { description: 'Check a file and print JSON', command: 'plazbot agent files status fil_AbcDef123 --json' },
186
+ ]);
125
187
  // Eliminar archivo
126
- filesGroup.command('delete')
188
+ const deleteCmd = filesGroup.command('delete')
127
189
  .description('Delete a file from the knowledge base')
128
190
  .argument('<agentId>', 'Agent ID')
129
191
  .argument('<fileId>', 'File ID')
130
- .option('--dev', 'Use development environment', false)
131
- .action(async (agentId, fileId, options) => {
192
+ .addOption(jsonOption('Print the result as JSON ({"agentId","fileId","deleted"})'))
193
+ .option('--dev', 'Use development environment', false);
194
+ addYesOption(deleteCmd);
195
+ deleteCmd.action(async (agentId, fileId, options) => {
132
196
  try {
197
+ const ok = await confirmAction(`Delete file ${fileId} from agent ${agentId}? This cannot be undone.`, options);
198
+ if (!ok) {
199
+ logger.dim('Aborted.');
200
+ process.exit(1);
201
+ }
133
202
  const credentials = await getStoredCredentials();
134
- const agent = new Agent({
135
- workspaceId: credentials.workspace,
136
- apiKey: credentials.apiKey,
137
- zone: credentials.zone,
138
- ...(options.dev && { customUrl: "http://localhost:5090" })
139
- });
203
+ const agent = buildAgent(credentials, options.dev);
140
204
  const spinner = createSpinner('Deleting file...');
141
205
  spinner.start();
142
- await agent.deleteFile({ fileId, agentId });
206
+ let result;
207
+ try {
208
+ result = await agent.deleteFile({ fileId, agentId });
209
+ }
210
+ catch (err) {
211
+ spinner.fail('Could not delete the file');
212
+ throw err;
213
+ }
214
+ if (result?.success === false) {
215
+ spinner.fail('Could not delete the file');
216
+ throw new CliError(result.message || 'The API rejected the request.', 'delete_file_failed');
217
+ }
143
218
  spinner.succeed('File deleted');
219
+ if (isJsonMode()) {
220
+ printJson({ agentId, fileId, deleted: true });
221
+ }
144
222
  }
145
223
  catch (error) {
146
- const message = error instanceof Error ? error.message : 'Unknown error';
147
- logger.error(message);
148
- process.exit(1);
224
+ fail(error);
149
225
  }
150
226
  });
227
+ addExamples(deleteCmd, [
228
+ { description: 'Delete a file (asks for confirmation)',
229
+ command: 'plazbot agent files delete age_AbcDef123 fil_AbcDef123' },
230
+ { description: 'Delete without prompting (scripts and CI)',
231
+ command: 'plazbot agent files delete age_AbcDef123 fil_AbcDef123 --yes' },
232
+ ]);
151
233
  export const filesCommand = filesGroup;
@@ -1,24 +1,33 @@
1
- import { Command } from 'commander';
1
+ import { Command, Option } from 'commander';
2
2
  import { Agent } from 'plazbot';
3
3
  import { getStoredCredentials } from '../../utils/credentials.js';
4
4
  import { logger } from '../../utils/logger.js';
5
5
  import { addExamples } from '../../utils/help.js';
6
6
  import { describeAgentLoadError } from '../../utils/agent-errors.js';
7
+ import { jsonOption, isJsonMode, setJsonMode, printJson, fail, CliError } from '../../utils/output.js';
7
8
  import chalk from 'chalk';
8
9
  export const getCommand = new Command('get')
9
10
  .description('Get detailed information about a specific agent')
10
11
  .argument('<agentId>', 'Agent ID to fetch')
11
12
  .option('-w, --workspace <id>', 'Workspace ID (overrides local config)')
12
13
  .option('-z, --zone <zone>', 'Zone LA or EU (overrides local config)')
13
- .option('--raw', 'Show full unformatted JSON', false)
14
+ // Legacy alias of --json
15
+ .addOption(new Option('--raw', 'Alias of --json').default(false).hideHelp())
16
+ .addOption(jsonOption('Print the agent as JSON'))
14
17
  .option('--dev', 'Use development environment', false)
15
18
  .action(async (agentId, options) => {
19
+ if (options.raw)
20
+ setJsonMode(true);
16
21
  try {
17
22
  const credentials = await getStoredCredentials();
18
23
  const effectiveWorkspace = options.workspace || credentials.workspace;
19
- const effectiveZone = (options.zone?.toUpperCase() === 'EU' ? 'EU' : options.zone?.toUpperCase() === 'LA' ? 'LA' : credentials.zone);
24
+ const zoneOverride = options.zone?.toUpperCase();
25
+ if (zoneOverride && zoneOverride !== 'LA' && zoneOverride !== 'EU') {
26
+ throw new CliError(`Invalid zone "${options.zone}".`, 'invalid_zone', 'Use -z LA or -z EU.');
27
+ }
28
+ const effectiveZone = (zoneOverride || credentials.zone);
20
29
  if (options.workspace || options.zone) {
21
- console.log(chalk.hex('#FFA726')(`\n Support mode: workspace=${effectiveWorkspace} zone=${effectiveZone}`));
30
+ logger.warning(`Support mode: workspace=${effectiveWorkspace} zone=${effectiveZone}`);
22
31
  }
23
32
  const agent = new Agent({
24
33
  workspaceId: effectiveWorkspace,
@@ -29,9 +38,9 @@ export const getCommand = new Command('get')
29
38
  // El SDK retorna { success, agent: {...} }
30
39
  const response = await agent.getAgentById({ id: agentId });
31
40
  const agentData = response.agent || response.data || response;
32
- // Modo JSON crudo
33
- if (options.raw) {
34
- console.log(JSON.stringify(agentData, null, 2));
41
+ // Modo JSON (--json o el legado --raw)
42
+ if (isJsonMode()) {
43
+ printJson(agentData);
35
44
  return;
36
45
  }
37
46
  const label = (key, value) => {
@@ -177,13 +186,15 @@ export const getCommand = new Command('get')
177
186
  });
178
187
  }
179
188
  console.log();
180
- console.log(chalk.gray(' Use --raw to see the full JSON'));
189
+ console.log(chalk.gray(' Use --json to see the full JSON'));
181
190
  console.log();
182
191
  if (options.dev) {
183
192
  logger.warning('Environment: development');
184
193
  }
185
194
  }
186
195
  catch (error) {
196
+ if (isJsonMode() || error instanceof CliError)
197
+ fail(error);
187
198
  const credentials = await getStoredCredentials().catch(() => null);
188
199
  if (credentials) {
189
200
  logger.error(describeAgentLoadError(error, agentId, credentials, {
@@ -191,19 +202,16 @@ export const getCommand = new Command('get')
191
202
  workspaceOverride: options.workspace,
192
203
  zoneOverride: options.zone,
193
204
  }));
205
+ process.exit(1);
194
206
  }
195
- else {
196
- const message = error instanceof Error ? error.message : 'Unknown error while fetching the agent';
197
- logger.error(message);
198
- }
199
- process.exit(1);
207
+ fail(error);
200
208
  }
201
209
  });
202
210
  addExamples(getCommand, [
203
211
  { description: 'Show the agent in a human-friendly layout',
204
- command: 'plazbot agent get agt_AbcDef123' },
212
+ command: 'plazbot agent get age_AbcDef123' },
205
213
  { description: 'Dump the full raw JSON (useful for piping to jq)',
206
- command: 'plazbot agent get agt_AbcDef123 --raw' },
214
+ command: 'plazbot agent get age_AbcDef123 --json' },
207
215
  { description: 'Inspect an agent from another workspace (support mode)',
208
- command: 'plazbot agent get agt_AbcDef123 -w wok_Other123 -z LA' },
216
+ command: 'plazbot agent get age_AbcDef123 -w wok_Other123 -z LA' },
209
217
  ]);
@@ -18,7 +18,7 @@ import { monitorCommand } from './monitor.js';
18
18
  import { exportCommand, crossCopyCommand } from './export.js';
19
19
  import { validateCommand } from './validate.js';
20
20
  export const agentCommands = new Command('agent')
21
- .description('Commands related to AI agents')
21
+ .description('Create, configure, test and monitor AI agents')
22
22
  .addCommand(listCommand)
23
23
  .addCommand(getCommand)
24
24
  .addCommand(deleteCommand)
@@ -40,14 +40,16 @@ export const agentCommands = new Command('agent')
40
40
  addExamples(agentCommands, [
41
41
  { description: 'List agents in the active workspace',
42
42
  command: 'plazbot agent list' },
43
- { description: 'Chat interactively with an agent',
44
- command: 'plazbot agent chat agt_AbcDef123' },
45
- { description: 'Create an agent from a JSON template',
43
+ { description: 'Create an agent from a JSON file',
46
44
  command: 'plazbot agent create ./agent.json' },
47
- { description: 'Export an agent and copy it to another workspace',
48
- command: 'plazbot agent cross-copy agt_AbcDef123 --from-workspace wok_Source --to-workspace wok_Target' },
49
- { description: 'Monitor activity of an agent in real time',
50
- command: 'plazbot agent monitor agt_AbcDef123' },
51
- { description: 'Validate a local agent JSON file against the schema',
52
- command: 'plazbot agent validate ./agent.json' },
45
+ { description: 'Chat interactively with an agent',
46
+ command: 'plazbot agent chat age_AbcDef123' },
47
+ { description: 'Ask a single question (scripts)',
48
+ command: 'plazbot agent message age_AbcDef123 -q "What plans do you offer?" --json' },
49
+ { description: 'Export, edit and update an agent',
50
+ command: 'plazbot agent export age_AbcDef123 -o agent.json && plazbot agent update age_AbcDef123 agent.json' },
51
+ { description: 'Copy an agent to another workspace',
52
+ command: 'plazbot agent cross-copy age_AbcDef123 --from-workspace wok_Source123 --to-workspace wok_Target456' },
53
+ { description: 'Monitor the activity of an agent in real time',
54
+ command: 'plazbot agent monitor age_AbcDef123' },
53
55
  ]);
@@ -3,33 +3,43 @@ import { Agent } from 'plazbot';
3
3
  import { getStoredCredentials } from '../../utils/credentials.js';
4
4
  import { logger } from '../../utils/logger.js';
5
5
  import { addExamples } from '../../utils/help.js';
6
+ import { jsonOption, isJsonMode, printJson, fail } from '../../utils/output.js';
6
7
  export const listCommand = new Command('list')
7
8
  .description('List all agents in the workspace')
9
+ .addOption(jsonOption('Print the agents as a JSON array (id, name, enable, description, createdAt)'))
8
10
  .option('--dev', 'Use development environment (localhost:5090)', false)
9
11
  .action(async (options) => {
10
12
  try {
11
- // Obtener credenciales guardadas
12
13
  const credentials = await getStoredCredentials();
13
- // Crear instancia del agente con las credenciales guardadas
14
14
  const agent = new Agent({
15
15
  workspaceId: credentials.workspace,
16
16
  apiKey: credentials.apiKey,
17
17
  zone: credentials.zone,
18
18
  ...(options.dev && { customUrl: "http://localhost:5090" })
19
19
  });
20
- // Obtener lista de agentes
21
- const agents = await agent.getAgents();
20
+ const agents = (await agent.getAgents()) || [];
21
+ if (isJsonMode()) {
22
+ printJson(agents.map((a) => ({
23
+ id: a.id,
24
+ name: a.name,
25
+ enable: a.enable,
26
+ description: a.description,
27
+ createdAt: a.createdAt,
28
+ })));
29
+ return;
30
+ }
22
31
  if (agents.length === 0) {
23
- logger.info('No agents found in this workspace');
32
+ logger.info('No agents found in this workspace.');
33
+ logger.dim('Create one with: plazbot agent create');
24
34
  return;
25
35
  }
26
- logger.info('\nAgents:');
36
+ logger.info(`\nAgents (${agents.length}):`);
27
37
  logger.doubleDivider();
28
38
  agents.forEach((a, index) => {
29
39
  logger.info(`${index + 1}. ID: ${a.id}`);
30
40
  logger.info(` Name: ${a.name}`);
31
41
  logger.info(` Status: ${a.enable ? 'Active' : 'Inactive'}`);
32
- logger.info(` Description: ${a.description}`);
42
+ logger.info(` Description: ${a.description || '—'}`);
33
43
  logger.info(` Created: ${a.createdAt ? new Date(a.createdAt).toLocaleString() : 'N/A'}`);
34
44
  logger.divider();
35
45
  });
@@ -38,12 +48,11 @@ export const listCommand = new Command('list')
38
48
  }
39
49
  }
40
50
  catch (error) {
41
- const message = error instanceof Error ? error.message : 'Unknown error while listing agents';
42
- logger.error(message);
43
- process.exit(1);
51
+ fail(error);
44
52
  }
45
53
  });
46
54
  addExamples(listCommand, [
47
55
  { description: 'List every agent in the active workspace', command: 'plazbot agent list' },
48
- { description: 'List against a local backend (dev mode)', command: 'plazbot agent list --dev' },
56
+ { description: 'Print the agents as JSON', command: 'plazbot agent list --json' },
57
+ { description: 'Get only the agent IDs (for scripts)', command: "plazbot agent list --json | jq -r '.[].id'" },
49
58
  ]);