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.
- package/CLAUDE.md +34 -5
- package/README.md +21 -0
- package/dist/cli.js +32 -20
- package/dist/commands/agent/ai-config.js +98 -50
- package/dist/commands/agent/chat.js +80 -74
- package/dist/commands/agent/copy.js +23 -21
- package/dist/commands/agent/create.js +42 -72
- package/dist/commands/agent/delete.js +29 -30
- package/dist/commands/agent/enable-widget.js +30 -26
- package/dist/commands/agent/export.js +90 -77
- package/dist/commands/agent/files.js +68 -60
- package/dist/commands/agent/get.js +101 -87
- package/dist/commands/agent/index.js +53 -39
- package/dist/commands/agent/list.js +26 -24
- package/dist/commands/agent/monitor.js +91 -86
- package/dist/commands/agent/on-message.js +40 -37
- package/dist/commands/agent/set.js +62 -59
- package/dist/commands/agent/templates.js +109 -108
- package/dist/commands/agent/tools.js +64 -65
- package/dist/commands/agent/update.js +28 -27
- package/dist/commands/agent/validate.js +127 -0
- package/dist/commands/agent/wizard.js +152 -159
- package/dist/commands/auth/index.js +7 -10
- package/dist/commands/auth/login.js +50 -37
- package/dist/commands/auth/logout.js +16 -14
- package/dist/commands/auth/status.js +19 -16
- package/dist/commands/portal/add-agent.js +26 -24
- package/dist/commands/portal/add-link.js +21 -17
- package/dist/commands/portal/clear-links.js +17 -15
- package/dist/commands/portal/create.js +25 -21
- package/dist/commands/portal/delete.js +31 -30
- package/dist/commands/portal/get.js +33 -31
- package/dist/commands/portal/index.js +30 -22
- package/dist/commands/portal/list.js +34 -30
- package/dist/commands/portal/update.js +41 -33
- package/dist/commands/whatsapp/broadcast.js +40 -37
- package/dist/commands/whatsapp/channels.js +40 -34
- package/dist/commands/whatsapp/chat.js +33 -32
- package/dist/commands/whatsapp/connect.js +53 -52
- package/dist/commands/whatsapp/delete-webhook.js +19 -17
- package/dist/commands/whatsapp/index.js +35 -25
- package/dist/commands/whatsapp/register-webhook.js +21 -19
- package/dist/commands/whatsapp/send-template.js +39 -31
- package/dist/commands/whatsapp/send.js +27 -23
- package/dist/commands/whatsapp/widget.js +35 -31
- package/dist/commands/workers/deploy.js +49 -44
- package/dist/commands/workers/index.js +28 -18
- package/dist/commands/workers/list.js +43 -35
- package/dist/commands/workers/logs.js +38 -32
- package/dist/commands/workers/remove.js +38 -37
- package/dist/commands/workers/secret.js +63 -58
- package/dist/commands/workers/test.js +44 -36
- package/dist/schemas/agent.config.schema.json +569 -0
- package/dist/studio/api/sseClient.js +97 -0
- package/dist/studio/api/studioApi.js +25 -0
- package/dist/studio/api/types.js +16 -0
- package/dist/studio/components/AgentPanel.js +35 -0
- package/dist/studio/components/App.js +214 -0
- package/dist/studio/components/ChatLog.js +59 -0
- package/dist/studio/components/Footer.js +11 -0
- package/dist/studio/components/Header.js +8 -0
- package/dist/studio/components/Input.js +15 -0
- package/dist/studio/components/Message.js +56 -0
- package/dist/studio/components/Suggestions.js +11 -0
- package/dist/studio/components/ToolCall.js +33 -0
- package/dist/studio/components/WhatsappConnectCard.js +57 -0
- package/dist/studio/index.js +42 -0
- package/dist/studio/render/json.js +16 -0
- package/dist/studio/render/markdown.js +86 -0
- package/dist/studio/render/steps.js +58 -0
- package/dist/studio/runOneShot.js +96 -0
- package/dist/studio/runRepl.js +52 -0
- package/dist/studio/slash/handlers.js +199 -0
- package/dist/studio/slash/parser.js +46 -0
- package/dist/studio/slash/registry.js +16 -0
- package/dist/studio/state/store.js +181 -0
- package/dist/studio/whatsapp/api.js +63 -0
- package/dist/studio/whatsapp/polling.js +77 -0
- package/dist/studio/whatsapp/types.js +31 -0
- package/dist/types/agent.js +1 -2
- package/dist/types/auth.js +1 -2
- package/dist/types/common.js +1 -2
- package/dist/types/message.js +1 -2
- package/dist/types/portal.js +1 -2
- package/dist/types/workers.js +1 -2
- package/dist/utils/agent-errors.js +46 -0
- package/dist/utils/api.js +8 -9
- package/dist/utils/banner.js +33 -34
- package/dist/utils/credentials.js +12 -20
- package/dist/utils/help.js +44 -0
- package/dist/utils/logger.js +13 -19
- package/dist/utils/ui.js +35 -49
- package/package.json +22 -10
- package/src/cli.ts +24 -8
- package/src/commands/agent/ai-config.ts +89 -34
- package/src/commands/agent/chat.ts +49 -37
- package/src/commands/agent/copy.ts +19 -13
- package/src/commands/agent/create.ts +32 -22
- package/src/commands/agent/delete.ts +24 -18
- package/src/commands/agent/enable-widget.ts +31 -23
- package/src/commands/agent/export.ts +72 -51
- package/src/commands/agent/files.ts +51 -39
- package/src/commands/agent/get.ts +86 -66
- package/src/commands/agent/index.ts +36 -18
- package/src/commands/agent/list.ts +22 -16
- package/src/commands/agent/monitor.ts +67 -56
- package/src/commands/agent/on-message.ts +36 -27
- package/src/commands/agent/set.ts +47 -37
- package/src/commands/agent/templates.ts +90 -82
- package/src/commands/agent/tools.ts +53 -47
- package/src/commands/agent/update.ts +28 -20
- package/src/commands/agent/validate.ts +135 -0
- package/src/commands/agent/wizard.ts +114 -114
- package/src/commands/auth/index.ts +3 -3
- package/src/commands/auth/login.ts +44 -29
- package/src/commands/auth/logout.ts +16 -10
- package/src/commands/auth/status.ts +14 -8
- package/src/commands/portal/add-agent.ts +23 -17
- package/src/commands/portal/add-link.ts +17 -9
- package/src/commands/portal/clear-links.ts +13 -7
- package/src/commands/portal/create.ts +20 -12
- package/src/commands/portal/delete.ts +28 -20
- package/src/commands/portal/get.ts +25 -19
- package/src/commands/portal/index.ts +22 -10
- package/src/commands/portal/list.ts +27 -19
- package/src/commands/portal/update.ts +38 -26
- package/src/commands/whatsapp/broadcast.ts +28 -18
- package/src/commands/whatsapp/channels.ts +31 -20
- package/src/commands/whatsapp/chat.ts +20 -12
- package/src/commands/whatsapp/connect.ts +39 -31
- package/src/commands/whatsapp/delete-webhook.ts +15 -9
- package/src/commands/whatsapp/index.ts +24 -10
- package/src/commands/whatsapp/register-webhook.ts +16 -10
- package/src/commands/whatsapp/send-template.ts +33 -21
- package/src/commands/whatsapp/send.ts +23 -15
- package/src/commands/whatsapp/widget.ts +25 -17
- package/src/commands/workers/deploy.ts +34 -22
- package/src/commands/workers/index.ts +21 -7
- package/src/commands/workers/list.ts +31 -19
- package/src/commands/workers/logs.ts +30 -20
- package/src/commands/workers/remove.ts +30 -22
- package/src/commands/workers/secret.ts +46 -34
- package/src/commands/workers/test.ts +34 -22
- package/src/schemas/agent.config.schema.json +569 -0
- package/src/studio/api/sseClient.ts +91 -0
- package/src/studio/api/studioApi.ts +27 -0
- package/src/studio/api/types.ts +96 -0
- package/src/studio/components/App.tsx +266 -0
- package/src/studio/components/ChatLog.tsx +95 -0
- package/src/studio/components/Footer.tsx +38 -0
- package/src/studio/components/Header.tsx +39 -0
- package/src/studio/components/Input.tsx +32 -0
- package/src/studio/components/Message.tsx +87 -0
- package/src/studio/components/Suggestions.tsx +26 -0
- package/src/studio/components/ToolCall.tsx +58 -0
- package/src/studio/components/WhatsappConnectCard.tsx +139 -0
- package/src/studio/index.ts +58 -0
- package/src/studio/render/markdown.ts +93 -0
- package/src/studio/render/steps.ts +57 -0
- package/src/studio/runOneShot.ts +114 -0
- package/src/studio/runRepl.tsx +76 -0
- package/src/studio/slash/handlers.ts +226 -0
- package/src/studio/slash/parser.ts +41 -0
- package/src/studio/slash/registry.ts +54 -0
- package/src/studio/state/store.ts +273 -0
- package/src/studio/whatsapp/api.ts +96 -0
- package/src/studio/whatsapp/polling.ts +93 -0
- package/src/studio/whatsapp/types.ts +80 -0
- package/src/types/agent.ts +1 -1
- package/src/types/auth.ts +4 -3
- package/src/types/portal.ts +1 -1
- package/src/types/workers.ts +1 -1
- package/src/utils/agent-errors.ts +67 -0
- package/src/utils/api.ts +6 -0
- package/src/utils/banner.ts +14 -9
- package/src/utils/credentials.ts +6 -5
- package/src/utils/help.ts +51 -0
- package/tsconfig.json +9 -6
|
@@ -1,42 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.
|
|
11
|
-
.
|
|
12
|
-
.requiredOption('-m, --message <text>', 'Mensaje a enviar')
|
|
13
|
-
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { Message } 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 { createSpinner } from '../../utils/ui.js';
|
|
7
|
+
export const sendMessageCommand = new Command('send-message')
|
|
8
|
+
.description('Send a direct WhatsApp message')
|
|
9
|
+
.requiredOption('-t, --to <phone>', 'Phone number (with country code, e.g.: 51912345678)')
|
|
10
|
+
.requiredOption('-m, --message <text>', 'Message to send')
|
|
11
|
+
.option('--dev', 'Use development environment', false)
|
|
14
12
|
.action(async (options) => {
|
|
15
13
|
try {
|
|
16
|
-
const credentials = await
|
|
17
|
-
const messageClient = new
|
|
14
|
+
const credentials = await getStoredCredentials();
|
|
15
|
+
const messageClient = new Message({
|
|
18
16
|
workspaceId: credentials.workspace,
|
|
19
17
|
apiKey: credentials.apiKey,
|
|
20
18
|
zone: credentials.zone,
|
|
21
19
|
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
22
20
|
});
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const spinner =
|
|
21
|
+
logger.title('Sending WhatsApp message');
|
|
22
|
+
logger.label('Destination', options.to);
|
|
23
|
+
logger.label('Message', options.message);
|
|
24
|
+
const spinner = createSpinner('Sending...');
|
|
27
25
|
spinner.start();
|
|
28
26
|
const response = await messageClient.onWhatsappMessage({
|
|
29
27
|
message: options.message,
|
|
30
28
|
to: options.to
|
|
31
29
|
});
|
|
32
|
-
spinner.succeed('
|
|
30
|
+
spinner.succeed('Message sent successfully');
|
|
33
31
|
if (options.dev) {
|
|
34
|
-
|
|
32
|
+
logger.warning('Environment: development');
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
35
|
catch (error) {
|
|
38
|
-
const message = error?.message || '
|
|
39
|
-
|
|
36
|
+
const message = error?.message || 'Unknown error while sending the message';
|
|
37
|
+
logger.error(message);
|
|
40
38
|
process.exit(1);
|
|
41
39
|
}
|
|
42
40
|
});
|
|
41
|
+
addExamples(sendMessageCommand, [
|
|
42
|
+
{ description: 'Send a quick WhatsApp message',
|
|
43
|
+
command: 'plazbot whatsapp send-message -t 51912345678 -m "Hello from Plazbot"' },
|
|
44
|
+
{ description: 'Send through the development backend',
|
|
45
|
+
command: 'plazbot whatsapp send-message -t 51912345678 -m "Hi" --dev' },
|
|
46
|
+
]);
|
|
@@ -1,64 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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 { createSpinner } from '../../utils/ui.js';
|
|
7
|
+
const widgetGroup = new Command('widget')
|
|
8
|
+
.description('Manage WhatsApp widget');
|
|
9
|
+
addExamples(widgetGroup, [
|
|
10
|
+
{ description: 'Enable the WhatsApp click-to-chat widget on an agent',
|
|
11
|
+
command: 'plazbot whatsapp widget enable agt_AbcDef123 -u https://wa.me/51912345678' },
|
|
12
|
+
{ description: 'Disable the widget',
|
|
13
|
+
command: 'plazbot whatsapp widget disable agt_AbcDef123' },
|
|
14
|
+
]);
|
|
11
15
|
widgetGroup.command('enable')
|
|
12
|
-
.description('
|
|
13
|
-
.argument('<agentId>', 'ID
|
|
14
|
-
.requiredOption('-u, --url <url>', 'URL
|
|
15
|
-
.option('--dev', '
|
|
16
|
+
.description('Enable the WhatsApp widget on an agent')
|
|
17
|
+
.argument('<agentId>', 'Agent ID')
|
|
18
|
+
.requiredOption('-u, --url <url>', 'WhatsApp URL (e.g.: https://wa.me/51912345678)')
|
|
19
|
+
.option('--dev', 'Use development environment', false)
|
|
16
20
|
.action(async (agentId, options) => {
|
|
17
21
|
try {
|
|
18
|
-
const credentials = await
|
|
19
|
-
const agent = new
|
|
22
|
+
const credentials = await getStoredCredentials();
|
|
23
|
+
const agent = new Agent({
|
|
20
24
|
workspaceId: credentials.workspace,
|
|
21
25
|
apiKey: credentials.apiKey,
|
|
22
26
|
zone: credentials.zone,
|
|
23
27
|
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
24
28
|
});
|
|
25
|
-
const spinner =
|
|
29
|
+
const spinner = createSpinner('Enabling WhatsApp widget...');
|
|
26
30
|
spinner.start();
|
|
27
31
|
await agent.updateAgent(agentId, {
|
|
28
32
|
enableWhatsappWidget: true,
|
|
29
33
|
urlWhatsappWidget: options.url,
|
|
30
34
|
});
|
|
31
|
-
spinner.succeed('
|
|
32
|
-
|
|
35
|
+
spinner.succeed('WhatsApp widget enabled');
|
|
36
|
+
logger.label('URL', options.url);
|
|
33
37
|
}
|
|
34
38
|
catch (error) {
|
|
35
|
-
const message = error instanceof Error ? error.message : '
|
|
36
|
-
|
|
39
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
40
|
+
logger.error(message);
|
|
37
41
|
process.exit(1);
|
|
38
42
|
}
|
|
39
43
|
});
|
|
40
44
|
widgetGroup.command('disable')
|
|
41
|
-
.description('
|
|
42
|
-
.argument('<agentId>', 'ID
|
|
43
|
-
.option('--dev', '
|
|
45
|
+
.description('Disable the WhatsApp widget on an agent')
|
|
46
|
+
.argument('<agentId>', 'Agent ID')
|
|
47
|
+
.option('--dev', 'Use development environment', false)
|
|
44
48
|
.action(async (agentId, options) => {
|
|
45
49
|
try {
|
|
46
|
-
const credentials = await
|
|
47
|
-
const agent = new
|
|
50
|
+
const credentials = await getStoredCredentials();
|
|
51
|
+
const agent = new Agent({
|
|
48
52
|
workspaceId: credentials.workspace,
|
|
49
53
|
apiKey: credentials.apiKey,
|
|
50
54
|
zone: credentials.zone,
|
|
51
55
|
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
52
56
|
});
|
|
53
|
-
const spinner =
|
|
57
|
+
const spinner = createSpinner('Disabling WhatsApp widget...');
|
|
54
58
|
spinner.start();
|
|
55
59
|
await agent.updateAgent(agentId, { enableWhatsappWidget: false });
|
|
56
|
-
spinner.succeed('
|
|
60
|
+
spinner.succeed('WhatsApp widget disabled');
|
|
57
61
|
}
|
|
58
62
|
catch (error) {
|
|
59
|
-
const message = error instanceof Error ? error.message : '
|
|
60
|
-
|
|
63
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
64
|
+
logger.error(message);
|
|
61
65
|
process.exit(1);
|
|
62
66
|
}
|
|
63
67
|
});
|
|
64
|
-
|
|
68
|
+
export const widgetCommand = widgetGroup;
|
|
@@ -1,49 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
.description('Despliega un worker al workspace de Plazbot')
|
|
16
|
-
.argument('[file]', 'Archivo TypeScript del worker (ej: ./workers/mi-tool.ts)')
|
|
17
|
-
.option('-n, --name <name>', 'Nombre del worker (sobreescribe el del archivo)')
|
|
18
|
-
.option('-d, --description <desc>', 'Descripcion del worker')
|
|
19
|
-
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
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
|
+
export const deployCommand = new Command('deploy')
|
|
10
|
+
.description('Deploy a worker to the Plazbot workspace')
|
|
11
|
+
.argument('[file]', 'Worker TypeScript file (e.g.: ./workers/my-tool.ts)')
|
|
12
|
+
.option('-n, --name <name>', 'Worker name (overrides the one in the file)')
|
|
13
|
+
.option('-d, --description <desc>', 'Worker description')
|
|
14
|
+
.option('--dev', 'Use development environment', false)
|
|
20
15
|
.action(async (file, options) => {
|
|
21
16
|
try {
|
|
22
|
-
const credentials = await
|
|
17
|
+
const credentials = await getStoredCredentials();
|
|
23
18
|
// Buscar archivos de workers
|
|
24
19
|
const files = await resolveWorkerFiles(file);
|
|
25
20
|
if (files.length === 0) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
logger.error('No worker files found to deploy');
|
|
22
|
+
logger.dim('Usage: plazbot workers deploy ./workers/my-tool.ts');
|
|
23
|
+
logger.dim(' or: plazbot workers deploy (searches ./workers/ automatically)');
|
|
29
24
|
process.exit(1);
|
|
30
25
|
}
|
|
31
|
-
const api =
|
|
26
|
+
const api = createApiClient({
|
|
32
27
|
apiKey: credentials.apiKey,
|
|
33
28
|
workspace: credentials.workspace,
|
|
34
29
|
zone: credentials.zone,
|
|
35
30
|
dev: options.dev,
|
|
36
31
|
});
|
|
37
|
-
|
|
32
|
+
logger.title(`Deploying ${files.length} worker${files.length > 1 ? 's' : ''}`);
|
|
38
33
|
console.log();
|
|
39
34
|
const results = [];
|
|
40
35
|
for (const filePath of files) {
|
|
41
|
-
const fileName =
|
|
42
|
-
const spinner =
|
|
36
|
+
const fileName = path.basename(filePath);
|
|
37
|
+
const spinner = createSpinner(`Deploying ${fileName}...`);
|
|
43
38
|
spinner.start();
|
|
44
39
|
try {
|
|
45
40
|
// Leer archivo fuente
|
|
46
|
-
const sourceCode = await
|
|
41
|
+
const sourceCode = await fs.readFile(filePath, 'utf-8');
|
|
47
42
|
// Enviar al API
|
|
48
43
|
const response = await api.post('/api/worker/deploy', {
|
|
49
44
|
sourceCode,
|
|
@@ -56,7 +51,7 @@ exports.deployCommand = new commander_1.Command('deploy')
|
|
|
56
51
|
results.push({ file: fileName, result: data });
|
|
57
52
|
}
|
|
58
53
|
catch (error) {
|
|
59
|
-
const msg = error.response?.data?.message || error.message || '
|
|
54
|
+
const msg = error.response?.data?.message || error.message || 'Unknown error';
|
|
60
55
|
spinner.fail(`${fileName}: ${msg}`);
|
|
61
56
|
results.push({ file: fileName, error: msg });
|
|
62
57
|
}
|
|
@@ -66,59 +61,69 @@ exports.deployCommand = new commander_1.Command('deploy')
|
|
|
66
61
|
const success = results.filter(r => r.result);
|
|
67
62
|
const failed = results.filter(r => r.error);
|
|
68
63
|
if (success.length > 0) {
|
|
69
|
-
|
|
64
|
+
logger.success(`${success.length} worker${success.length > 1 ? 's' : ''} deployed`);
|
|
70
65
|
const rows = success.map(r => [
|
|
71
66
|
r.result.name,
|
|
72
67
|
r.result.type,
|
|
73
68
|
r.result.status,
|
|
74
69
|
r.result.webhookUrl || r.result.cronExpression || '—',
|
|
75
70
|
]);
|
|
76
|
-
console.log(
|
|
71
|
+
console.log(createTable(['Name', 'Type', 'Status', 'URL/Cron'], rows));
|
|
77
72
|
}
|
|
78
73
|
if (failed.length > 0) {
|
|
79
|
-
|
|
80
|
-
failed.forEach(f =>
|
|
74
|
+
logger.warning(`${failed.length} worker${failed.length > 1 ? 's' : ''} failed`);
|
|
75
|
+
failed.forEach(f => logger.dim(` ${f.file}: ${f.error}`));
|
|
81
76
|
}
|
|
82
77
|
// Mostrar webhook URLs si hay
|
|
83
78
|
const webhooks = success.filter(r => r.result.webhookUrl);
|
|
84
79
|
if (webhooks.length > 0) {
|
|
85
80
|
console.log();
|
|
86
|
-
|
|
81
|
+
logger.title('Webhook URLs');
|
|
87
82
|
webhooks.forEach(w => {
|
|
88
|
-
|
|
83
|
+
logger.label(w.result.name, theme.secondary(w.result.webhookUrl));
|
|
89
84
|
});
|
|
90
85
|
}
|
|
91
86
|
console.log();
|
|
92
87
|
if (options.dev) {
|
|
93
|
-
|
|
88
|
+
logger.warning('Environment: development');
|
|
94
89
|
}
|
|
95
90
|
}
|
|
96
91
|
catch (error) {
|
|
97
|
-
const message = error instanceof Error ? error.message : '
|
|
98
|
-
|
|
92
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
93
|
+
logger.error(message);
|
|
99
94
|
process.exit(1);
|
|
100
95
|
}
|
|
101
96
|
});
|
|
97
|
+
addExamples(deployCommand, [
|
|
98
|
+
{ description: 'Deploy a single worker file',
|
|
99
|
+
command: 'plazbot workers deploy ./workers/my-tool.ts' },
|
|
100
|
+
{ description: 'Deploy every TypeScript file inside ./workers automatically',
|
|
101
|
+
command: 'plazbot workers deploy' },
|
|
102
|
+
{ description: 'Deploy with a custom name and description',
|
|
103
|
+
command: 'plazbot workers deploy ./workers/cron.ts -n "Daily Report" -d "Generates daily KPIs"' },
|
|
104
|
+
{ description: 'Deploy against the local backend',
|
|
105
|
+
command: 'plazbot workers deploy ./workers/test.ts --dev' },
|
|
106
|
+
]);
|
|
102
107
|
// Resuelve los archivos a desplegar
|
|
103
108
|
async function resolveWorkerFiles(file) {
|
|
104
109
|
if (file) {
|
|
105
110
|
// Archivo especifico
|
|
106
|
-
const resolved =
|
|
111
|
+
const resolved = path.resolve(file);
|
|
107
112
|
try {
|
|
108
|
-
await
|
|
113
|
+
await fs.access(resolved);
|
|
109
114
|
return [resolved];
|
|
110
115
|
}
|
|
111
116
|
catch {
|
|
112
|
-
throw new Error(`
|
|
117
|
+
throw new Error(`File not found: ${file}`);
|
|
113
118
|
}
|
|
114
119
|
}
|
|
115
120
|
// Buscar en ./workers/ automaticamente
|
|
116
|
-
const workersDir =
|
|
121
|
+
const workersDir = path.resolve('workers');
|
|
117
122
|
try {
|
|
118
|
-
const entries = await
|
|
123
|
+
const entries = await fs.readdir(workersDir);
|
|
119
124
|
const tsFiles = entries
|
|
120
125
|
.filter(e => e.endsWith('.ts') && !e.endsWith('.d.ts'))
|
|
121
|
-
.map(e =>
|
|
126
|
+
.map(e => path.join(workersDir, e));
|
|
122
127
|
return tsFiles;
|
|
123
128
|
}
|
|
124
129
|
catch {
|
|
@@ -1,18 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
.
|
|
13
|
-
.addCommand(
|
|
14
|
-
.addCommand(
|
|
15
|
-
.addCommand(
|
|
16
|
-
.addCommand(
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { Command } from 'commander';
|
|
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';
|
|
9
|
+
export const workersCommands = new Command('workers')
|
|
10
|
+
.description('Commands to manage workers (tools, syncs, schedules, webhooks)')
|
|
11
|
+
.addCommand(deployCommand)
|
|
12
|
+
.addCommand(listCommand)
|
|
13
|
+
.addCommand(logsCommand)
|
|
14
|
+
.addCommand(removeCommand)
|
|
15
|
+
.addCommand(secretCommand)
|
|
16
|
+
.addCommand(testCommand);
|
|
17
|
+
addExamples(workersCommands, [
|
|
18
|
+
{ description: 'Deploy every worker file in ./workers automatically',
|
|
19
|
+
command: 'plazbot workers deploy' },
|
|
20
|
+
{ description: 'List active workers',
|
|
21
|
+
command: 'plazbot workers list -s active' },
|
|
22
|
+
{ description: 'Run a worker with a JSON payload',
|
|
23
|
+
command: 'plazbot workers test my-tool -p \'{"product":"iPhone 15"}\'' },
|
|
24
|
+
{ description: 'Save a secret for workers (plz.env.KEY)',
|
|
25
|
+
command: 'plazbot workers secret set STRIPE_API_KEY sk_live_xxxxx' },
|
|
26
|
+
{ description: 'View the last 100 executions of a worker',
|
|
27
|
+
command: 'plazbot workers logs my-tool -l 100' },
|
|
28
|
+
]);
|
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.
|
|
11
|
-
.option('
|
|
12
|
-
.option('-s, --status <status>', 'Filtrar por estado (active, inactive, error)')
|
|
13
|
-
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
1
|
+
import { Command } from 'commander';
|
|
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
|
+
export const listCommand = new Command('list')
|
|
8
|
+
.description('List all workers in the workspace')
|
|
9
|
+
.option('-t, --type <type>', 'Filter by type (tool, worker, sync, schedule, webhook)')
|
|
10
|
+
.option('-s, --status <status>', 'Filter by status (active, inactive, error)')
|
|
11
|
+
.option('--dev', 'Use development environment', false)
|
|
14
12
|
.action(async (options) => {
|
|
15
13
|
try {
|
|
16
|
-
const credentials = await
|
|
17
|
-
const api =
|
|
14
|
+
const credentials = await getStoredCredentials();
|
|
15
|
+
const api = createApiClient({
|
|
18
16
|
apiKey: credentials.apiKey,
|
|
19
17
|
workspace: credentials.workspace,
|
|
20
18
|
zone: credentials.zone,
|
|
21
19
|
dev: options.dev,
|
|
22
20
|
});
|
|
23
|
-
const spinner =
|
|
21
|
+
const spinner = createSpinner('Fetching workers...');
|
|
24
22
|
spinner.start();
|
|
25
23
|
const params = {};
|
|
26
24
|
if (options.type)
|
|
@@ -31,51 +29,61 @@ exports.listCommand = new commander_1.Command('list')
|
|
|
31
29
|
const workers = response.data;
|
|
32
30
|
spinner.stop();
|
|
33
31
|
if (!workers || workers.length === 0) {
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
logger.info('\n No workers found in this workspace');
|
|
33
|
+
logger.dim(' Deploy your first worker: plazbot workers deploy ./workers/my-tool.ts');
|
|
36
34
|
console.log();
|
|
37
35
|
return;
|
|
38
36
|
}
|
|
39
|
-
|
|
37
|
+
logger.title(`Workers (${workers.length})`);
|
|
40
38
|
const rows = workers.map(w => [
|
|
41
39
|
w.name,
|
|
42
40
|
typeLabel(w.type),
|
|
43
|
-
w.status === 'active' ?
|
|
44
|
-
: w.status === 'error' ?
|
|
45
|
-
:
|
|
41
|
+
w.status === 'active' ? theme.success('active')
|
|
42
|
+
: w.status === 'error' ? theme.error('error')
|
|
43
|
+
: theme.muted('inactive'),
|
|
46
44
|
`${w.executionCount}`,
|
|
47
|
-
w.errorCount > 0 ?
|
|
45
|
+
w.errorCount > 0 ? theme.error(`${w.errorCount}`) : theme.muted('0'),
|
|
48
46
|
w.avgDurationMs > 0 ? `${w.avgDurationMs}ms` : '—',
|
|
49
|
-
w.lastExecutedAt ?
|
|
47
|
+
w.lastExecutedAt ? formatDate(w.lastExecutedAt) : '—',
|
|
50
48
|
]);
|
|
51
|
-
console.log(
|
|
49
|
+
console.log(createTable(['Name', 'Type', 'Status', 'Executions', 'Errors', 'Duration', 'Last execution'], rows));
|
|
52
50
|
// Mostrar workers con error
|
|
53
51
|
const errored = workers.filter(w => w.status === 'error');
|
|
54
52
|
if (errored.length > 0) {
|
|
55
53
|
console.log();
|
|
56
|
-
|
|
54
|
+
logger.warning('Workers with errors:');
|
|
57
55
|
errored.forEach(w => {
|
|
58
|
-
|
|
56
|
+
logger.dim(` ${w.name}: ${w.lastError || 'no details'}`);
|
|
59
57
|
});
|
|
60
58
|
}
|
|
61
59
|
console.log();
|
|
62
60
|
if (options.dev) {
|
|
63
|
-
|
|
61
|
+
logger.warning('Environment: development');
|
|
64
62
|
}
|
|
65
63
|
}
|
|
66
64
|
catch (error) {
|
|
67
|
-
const message = error instanceof Error ? error.message : '
|
|
68
|
-
|
|
65
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
66
|
+
logger.error(message);
|
|
69
67
|
process.exit(1);
|
|
70
68
|
}
|
|
71
69
|
});
|
|
70
|
+
addExamples(listCommand, [
|
|
71
|
+
{ description: 'List every worker in the workspace',
|
|
72
|
+
command: 'plazbot workers list' },
|
|
73
|
+
{ description: 'Only show schedules',
|
|
74
|
+
command: 'plazbot workers list -t schedule' },
|
|
75
|
+
{ description: 'Show only workers with errors',
|
|
76
|
+
command: 'plazbot workers list -s error' },
|
|
77
|
+
{ description: 'Filter active webhooks',
|
|
78
|
+
command: 'plazbot workers list -t webhook -s active' },
|
|
79
|
+
]);
|
|
72
80
|
function typeLabel(type) {
|
|
73
81
|
const labels = {
|
|
74
|
-
tool:
|
|
75
|
-
worker:
|
|
76
|
-
sync:
|
|
77
|
-
schedule:
|
|
78
|
-
webhook:
|
|
82
|
+
tool: theme.secondary('tool'),
|
|
83
|
+
worker: theme.primary('worker'),
|
|
84
|
+
sync: theme.accent('sync'),
|
|
85
|
+
schedule: theme.muted('schedule'),
|
|
86
|
+
webhook: theme.warning('webhook'),
|
|
79
87
|
};
|
|
80
88
|
return labels[type] || type;
|
|
81
89
|
}
|
|
@@ -1,27 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.
|
|
11
|
-
.
|
|
12
|
-
.option('
|
|
13
|
-
.option('-s, --status <status>', 'Filtrar por estado (success, error, timeout)')
|
|
14
|
-
.option('--dev', 'Usar ambiente de desarrollo', false)
|
|
1
|
+
import { Command } from 'commander';
|
|
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
|
+
export const logsCommand = new Command('logs')
|
|
8
|
+
.description('View execution logs for a worker')
|
|
9
|
+
.argument('<name>', 'Worker name')
|
|
10
|
+
.option('-l, --limit <number>', 'Number of logs to display', '20')
|
|
11
|
+
.option('-s, --status <status>', 'Filter by status (success, error, timeout)')
|
|
12
|
+
.option('--dev', 'Use development environment', false)
|
|
15
13
|
.action(async (name, options) => {
|
|
16
14
|
try {
|
|
17
|
-
const credentials = await
|
|
18
|
-
const api =
|
|
15
|
+
const credentials = await getStoredCredentials();
|
|
16
|
+
const api = createApiClient({
|
|
19
17
|
apiKey: credentials.apiKey,
|
|
20
18
|
workspace: credentials.workspace,
|
|
21
19
|
zone: credentials.zone,
|
|
22
20
|
dev: options.dev,
|
|
23
21
|
});
|
|
24
|
-
const spinner =
|
|
22
|
+
const spinner = createSpinner(`Fetching logs for "${name}"...`);
|
|
25
23
|
spinner.start();
|
|
26
24
|
const params = {
|
|
27
25
|
limit: String(options.limit || 20),
|
|
@@ -32,45 +30,53 @@ exports.logsCommand = new commander_1.Command('logs')
|
|
|
32
30
|
const logs = response.data;
|
|
33
31
|
spinner.stop();
|
|
34
32
|
if (!logs || logs.length === 0) {
|
|
35
|
-
|
|
33
|
+
logger.info(`\n No logs found for "${name}"`);
|
|
36
34
|
console.log();
|
|
37
35
|
return;
|
|
38
36
|
}
|
|
39
|
-
|
|
37
|
+
logger.title(`Logs for "${name}" (${logs.length})`);
|
|
40
38
|
const rows = logs.map(log => [
|
|
41
|
-
|
|
42
|
-
log.status === 'success' ?
|
|
43
|
-
: log.status === 'error' ?
|
|
44
|
-
:
|
|
39
|
+
formatDate(log.createdAt),
|
|
40
|
+
log.status === 'success' ? theme.success('ok')
|
|
41
|
+
: log.status === 'error' ? theme.error('error')
|
|
42
|
+
: theme.warning('timeout'),
|
|
45
43
|
`${log.durationMs}ms`,
|
|
46
44
|
log.triggerSource || '—',
|
|
47
|
-
log.error ?
|
|
45
|
+
log.error ? theme.error(truncate(log.error, 40)) : '—',
|
|
48
46
|
]);
|
|
49
|
-
console.log(
|
|
47
|
+
console.log(createTable(['Date', 'Status', 'Duration', 'Source', 'Error'], rows));
|
|
50
48
|
// Resumen
|
|
51
49
|
const successCount = logs.filter(l => l.status === 'success').length;
|
|
52
50
|
const errorCount = logs.filter(l => l.status === 'error').length;
|
|
53
51
|
const avgDuration = Math.round(logs.reduce((sum, l) => sum + l.durationMs, 0) / logs.length);
|
|
54
52
|
console.log();
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
logger.label('Successful', theme.success(`${successCount}`));
|
|
54
|
+
logger.label('Errors', errorCount > 0 ? theme.error(`${errorCount}`) : theme.muted('0'));
|
|
55
|
+
logger.label('Average duration', `${avgDuration}ms`);
|
|
58
56
|
console.log();
|
|
59
57
|
if (options.dev) {
|
|
60
|
-
|
|
58
|
+
logger.warning('Environment: development');
|
|
61
59
|
}
|
|
62
60
|
}
|
|
63
61
|
catch (error) {
|
|
64
62
|
if (error.response?.status === 404) {
|
|
65
|
-
|
|
63
|
+
logger.error(`Worker "${name}" not found`);
|
|
66
64
|
}
|
|
67
65
|
else {
|
|
68
|
-
const message = error instanceof Error ? error.message : '
|
|
69
|
-
|
|
66
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
67
|
+
logger.error(message);
|
|
70
68
|
}
|
|
71
69
|
process.exit(1);
|
|
72
70
|
}
|
|
73
71
|
});
|
|
72
|
+
addExamples(logsCommand, [
|
|
73
|
+
{ description: 'Show the last 20 executions of a worker',
|
|
74
|
+
command: 'plazbot workers logs my-tool' },
|
|
75
|
+
{ description: 'Get the last 100 executions',
|
|
76
|
+
command: 'plazbot workers logs my-tool -l 100' },
|
|
77
|
+
{ description: 'Only show failed executions',
|
|
78
|
+
command: 'plazbot workers logs my-tool -s error' },
|
|
79
|
+
]);
|
|
74
80
|
function truncate(text, max) {
|
|
75
81
|
if (text.length <= max)
|
|
76
82
|
return text;
|