plazbot-cli 0.3.6 → 0.4.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.
- package/README.md +38 -2
- package/dist/commands/agent/export.js +25 -2
- package/dist/commands/auth/browser-login.js +121 -0
- package/dist/commands/auth/index.js +5 -1
- package/dist/commands/auth/login.js +1 -3
- package/dist/commands/auth/logout.js +4 -3
- package/dist/commands/auth/status.js +8 -5
- package/dist/commands/auth/workspace.js +73 -0
- package/dist/commands/whatsapp/connect-flow.js +137 -0
- package/dist/commands/whatsapp/connect.js +26 -160
- package/dist/commands/whatsapp/index.js +4 -0
- package/dist/commands/whatsapp/setup.js +242 -0
- package/dist/studio/components/App.js +1 -1
- package/dist/studio/runOneShot.js +2 -2
- package/dist/studio/runRepl.js +1 -1
- package/dist/utils/agent-errors.js +2 -2
- package/dist/utils/banner.js +10 -9
- package/dist/utils/credentials.js +31 -3
- package/dist/utils/open-browser.js +17 -0
- package/package.json +14 -6
- package/.claude/settings.local.json +0 -15
- package/CLAUDE.md +0 -121
- package/agent.config.json +0 -21
- package/dist/studio/components/AgentPanel.js +0 -35
- package/dist/studio/render/json.js +0 -16
- package/dist/studio/whatsapp/api.js +0 -63
- package/dist/studio/whatsapp/polling.js +0 -77
- package/dist/studio/whatsapp/types.js +0 -31
- package/src/cli.ts +0 -57
- package/src/commands/agent/ai-config.ts +0 -164
- package/src/commands/agent/chat.ts +0 -225
- package/src/commands/agent/copy.ts +0 -46
- package/src/commands/agent/create.ts +0 -103
- package/src/commands/agent/delete.ts +0 -71
- package/src/commands/agent/enable-widget.ts +0 -67
- package/src/commands/agent/export.ts +0 -408
- package/src/commands/agent/files.ts +0 -171
- package/src/commands/agent/get.ts +0 -233
- package/src/commands/agent/index.ts +0 -55
- package/src/commands/agent/list.ts +0 -58
- package/src/commands/agent/monitor.ts +0 -375
- package/src/commands/agent/on-message.ts +0 -82
- package/src/commands/agent/set.ts +0 -149
- package/src/commands/agent/templates.ts +0 -892
- package/src/commands/agent/tools.ts +0 -168
- package/src/commands/agent/update.ts +0 -61
- package/src/commands/agent/validate.ts +0 -135
- package/src/commands/agent/wizard.ts +0 -756
- package/src/commands/auth/index.ts +0 -10
- package/src/commands/auth/login.ts +0 -72
- package/src/commands/auth/logout.ts +0 -28
- package/src/commands/auth/status.ts +0 -28
- package/src/commands/portal/add-agent.ts +0 -66
- package/src/commands/portal/add-link.ts +0 -47
- package/src/commands/portal/clear-links.ts +0 -33
- package/src/commands/portal/create.ts +0 -58
- package/src/commands/portal/delete.ts +0 -70
- package/src/commands/portal/get.ts +0 -77
- package/src/commands/portal/index.ts +0 -32
- package/src/commands/portal/list.ts +0 -79
- package/src/commands/portal/update.ts +0 -93
- package/src/commands/whatsapp/broadcast.ts +0 -110
- package/src/commands/whatsapp/channels.ts +0 -109
- package/src/commands/whatsapp/chat.ts +0 -85
- package/src/commands/whatsapp/connect.ts +0 -220
- package/src/commands/whatsapp/delete-webhook.ts +0 -43
- package/src/commands/whatsapp/index.ts +0 -37
- package/src/commands/whatsapp/register-webhook.ts +0 -47
- package/src/commands/whatsapp/send-template.ts +0 -94
- package/src/commands/whatsapp/send.ts +0 -55
- package/src/commands/whatsapp/widget.ts +0 -75
- package/src/commands/workers/deploy.ts +0 -156
- package/src/commands/workers/index.ts +0 -30
- package/src/commands/workers/list.ts +0 -105
- package/src/commands/workers/logs.ts +0 -99
- package/src/commands/workers/remove.ts +0 -103
- package/src/commands/workers/secret.ts +0 -191
- package/src/commands/workers/test.ts +0 -145
- package/src/schemas/agent.config.schema.json +0 -569
- package/src/studio/api/sseClient.ts +0 -91
- package/src/studio/api/studioApi.ts +0 -27
- package/src/studio/api/types.ts +0 -96
- package/src/studio/components/App.tsx +0 -274
- package/src/studio/components/ChatLog.tsx +0 -121
- package/src/studio/components/ConnectCard.tsx +0 -171
- package/src/studio/components/Footer.tsx +0 -38
- package/src/studio/components/Header.tsx +0 -39
- package/src/studio/components/Input.tsx +0 -176
- package/src/studio/components/Message.tsx +0 -87
- package/src/studio/components/Suggestions.tsx +0 -26
- package/src/studio/components/ToolCall.tsx +0 -58
- package/src/studio/connect/api.ts +0 -98
- package/src/studio/connect/polling.ts +0 -94
- package/src/studio/connect/types.ts +0 -141
- package/src/studio/index.ts +0 -58
- package/src/studio/render/markdown.ts +0 -93
- package/src/studio/render/steps.ts +0 -57
- package/src/studio/runOneShot.ts +0 -114
- package/src/studio/runRepl.tsx +0 -82
- package/src/studio/slash/handlers.ts +0 -226
- package/src/studio/slash/parser.ts +0 -41
- package/src/studio/slash/registry.ts +0 -54
- package/src/studio/state/store.ts +0 -279
- package/src/types/agent.ts +0 -63
- package/src/types/auth.ts +0 -9
- package/src/types/common.ts +0 -10
- package/src/types/message.ts +0 -34
- package/src/types/portal.ts +0 -56
- package/src/types/workers.ts +0 -86
- package/src/utils/agent-errors.ts +0 -67
- package/src/utils/api.ts +0 -35
- package/src/utils/banner.ts +0 -99
- package/src/utils/credentials.ts +0 -38
- package/src/utils/help.ts +0 -51
- package/src/utils/logger.ts +0 -40
- package/src/utils/ui.ts +0 -109
- package/tsconfig.json +0 -18
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { addExamples } from '../../utils/help.js';
|
|
3
|
-
import { sendMessageCommand } from './send.js';
|
|
4
|
-
import { sendTemplateCommand } from './send-template.js';
|
|
5
|
-
import { registerWebhookCommand } from './register-webhook.js';
|
|
6
|
-
import { deleteWebhookCommand } from './delete-webhook.js';
|
|
7
|
-
import { broadcastCommand } from './broadcast.js';
|
|
8
|
-
import { whatsappChatCommand } from './chat.js';
|
|
9
|
-
import { whatsappConnectCommand } from './connect.js';
|
|
10
|
-
import { widgetCommand } from './widget.js';
|
|
11
|
-
import { channelsCommand, assignCommand } from './channels.js';
|
|
12
|
-
|
|
13
|
-
export const whatsappCommands = new Command('whatsapp')
|
|
14
|
-
.description('WhatsApp commands: messages, templates, broadcast and more')
|
|
15
|
-
.addCommand(whatsappConnectCommand)
|
|
16
|
-
.addCommand(sendMessageCommand)
|
|
17
|
-
.addCommand(sendTemplateCommand)
|
|
18
|
-
.addCommand(registerWebhookCommand)
|
|
19
|
-
.addCommand(deleteWebhookCommand)
|
|
20
|
-
.addCommand(broadcastCommand)
|
|
21
|
-
.addCommand(whatsappChatCommand)
|
|
22
|
-
.addCommand(widgetCommand)
|
|
23
|
-
.addCommand(channelsCommand)
|
|
24
|
-
.addCommand(assignCommand);
|
|
25
|
-
|
|
26
|
-
addExamples(whatsappCommands, [
|
|
27
|
-
{ description: 'Connect a WhatsApp number to the workspace',
|
|
28
|
-
command: 'plazbot whatsapp connect' },
|
|
29
|
-
{ description: 'Send a quick message',
|
|
30
|
-
command: 'plazbot whatsapp send-message -t 51912345678 -m "Hello"' },
|
|
31
|
-
{ description: 'Send a template with variables',
|
|
32
|
-
command: 'plazbot whatsapp send-template -p 51912345678 -t welcome --var name=Anna' },
|
|
33
|
-
{ description: 'Open an interactive chat',
|
|
34
|
-
command: 'plazbot whatsapp chat 51912345678' },
|
|
35
|
-
{ description: 'Assign a number to an agent',
|
|
36
|
-
command: 'plazbot whatsapp assign 51912345678 agt_AbcDef123' },
|
|
37
|
-
]);
|
|
@@ -1,47 +0,0 @@
|
|
|
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
|
-
|
|
7
|
-
interface RegisterWebhookOptions {
|
|
8
|
-
dev?: boolean;
|
|
9
|
-
number: string;
|
|
10
|
-
url: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const registerWebhookCommand = new Command('register-webhook')
|
|
14
|
-
.description('Register a webhook for WhatsApp')
|
|
15
|
-
.requiredOption('-n, --number <phone>', 'WhatsApp number (with country code, e.g.: 51912345678)')
|
|
16
|
-
.requiredOption('-u, --url <webhook>', 'Webhook URL')
|
|
17
|
-
.option('--dev', 'Use development environment', false)
|
|
18
|
-
.action(async (options: RegisterWebhookOptions) => {
|
|
19
|
-
try {
|
|
20
|
-
const credentials = await getStoredCredentials();
|
|
21
|
-
const messageClient = new Message({
|
|
22
|
-
workspaceId: credentials.workspace,
|
|
23
|
-
apiKey: credentials.apiKey,
|
|
24
|
-
zone: credentials.zone,
|
|
25
|
-
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
logger.title('Registering WhatsApp webhook');
|
|
29
|
-
logger.label('Number', options.number);
|
|
30
|
-
logger.label('URL', options.url);
|
|
31
|
-
|
|
32
|
-
await messageClient.registerWebhook({
|
|
33
|
-
number: options.number,
|
|
34
|
-
webhookUrl: options.url
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
logger.success('Webhook registered successfully');
|
|
38
|
-
} catch (error: unknown) {
|
|
39
|
-
logger.error((error as Error).message);
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
addExamples(registerWebhookCommand, [
|
|
45
|
-
{ description: 'Register an inbound webhook for a WhatsApp number',
|
|
46
|
-
command: 'plazbot whatsapp register-webhook -n 51912345678 -u https://api.example.com/webhooks/whatsapp' },
|
|
47
|
-
]);
|
|
@@ -1,94 +0,0 @@
|
|
|
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
|
-
|
|
8
|
-
export const sendTemplateCommand = new Command('send-template')
|
|
9
|
-
.description('Send a WhatsApp template message with variables')
|
|
10
|
-
.requiredOption('-p, --phone <number>', 'Phone number (with country code)')
|
|
11
|
-
.requiredOption('-t, --template <name>', 'Template name')
|
|
12
|
-
.option('--var <vars...>', 'Body variables (format: name=value)')
|
|
13
|
-
.option('--header-var <vars...>', 'Header variables (format: name=value)')
|
|
14
|
-
.option('--file-url <url>', 'Attachment file URL')
|
|
15
|
-
.option('--file-name <name>', 'Attachment file name')
|
|
16
|
-
.option('--dev', 'Use development environment', false)
|
|
17
|
-
.action(async (options: any) => {
|
|
18
|
-
try {
|
|
19
|
-
const credentials = await getStoredCredentials();
|
|
20
|
-
|
|
21
|
-
const messageClient = new Message({
|
|
22
|
-
workspaceId: credentials.workspace,
|
|
23
|
-
apiKey: credentials.apiKey,
|
|
24
|
-
zone: credentials.zone,
|
|
25
|
-
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Parsear variables
|
|
29
|
-
const variablesBody = parseVariables(options.var);
|
|
30
|
-
const variablesHeader = parseVariables(options.headerVar);
|
|
31
|
-
|
|
32
|
-
// Archivo adjunto
|
|
33
|
-
const file = options.fileUrl ? {
|
|
34
|
-
fileUrl: options.fileUrl,
|
|
35
|
-
fileName: options.fileName || 'file',
|
|
36
|
-
} : undefined;
|
|
37
|
-
|
|
38
|
-
logger.title('Sending WhatsApp template');
|
|
39
|
-
logger.label('Destination', options.phone);
|
|
40
|
-
logger.label('Template', options.template);
|
|
41
|
-
if (variablesBody.length > 0) {
|
|
42
|
-
logger.label('Body variables', variablesBody.map(v => `${v.variable}=${v.value}`).join(', '));
|
|
43
|
-
}
|
|
44
|
-
if (variablesHeader.length > 0) {
|
|
45
|
-
logger.label('Header variables', variablesHeader.map(v => `${v.variable}=${v.value}`).join(', '));
|
|
46
|
-
}
|
|
47
|
-
if (file) {
|
|
48
|
-
logger.label('File', file.fileUrl);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const spinner = createSpinner('Sending...');
|
|
52
|
-
spinner.start();
|
|
53
|
-
|
|
54
|
-
const params: any = {
|
|
55
|
-
to: options.phone,
|
|
56
|
-
template: options.template,
|
|
57
|
-
};
|
|
58
|
-
if (variablesBody.length > 0) params.variablesBody = variablesBody;
|
|
59
|
-
if (variablesHeader.length > 0) params.variablesHeader = variablesHeader;
|
|
60
|
-
if (file) params.file = file;
|
|
61
|
-
|
|
62
|
-
const response = await messageClient.onConversation(params);
|
|
63
|
-
|
|
64
|
-
spinner.succeed('Template sent successfully');
|
|
65
|
-
|
|
66
|
-
if (options.dev) {
|
|
67
|
-
logger.warning('Environment: development');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
} catch (error: unknown) {
|
|
71
|
-
const message = (error as Error)?.message || 'Unknown error while sending the template';
|
|
72
|
-
logger.error(message);
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
addExamples(sendTemplateCommand, [
|
|
78
|
-
{ description: 'Send a template with no variables',
|
|
79
|
-
command: 'plazbot whatsapp send-template -p 51912345678 -t welcome_message' },
|
|
80
|
-
{ description: 'Send a template with body variables',
|
|
81
|
-
command: 'plazbot whatsapp send-template -p 51912345678 -t order_status --var name=Anna code=PB-123' },
|
|
82
|
-
{ description: 'Send a template with an attached PDF',
|
|
83
|
-
command: 'plazbot whatsapp send-template -p 51912345678 -t invoice_template --file-url https://files.example.com/inv.pdf --file-name invoice.pdf' },
|
|
84
|
-
{ description: 'Send a template with header and body variables',
|
|
85
|
-
command: 'plazbot whatsapp send-template -p 51912345678 -t promo --header-var image=https://img.example.com/banner.png --var amount=20' },
|
|
86
|
-
]);
|
|
87
|
-
|
|
88
|
-
function parseVariables(vars: string[] | undefined): { variable: string; value: string }[] {
|
|
89
|
-
if (!vars) return [];
|
|
90
|
-
return vars.map(v => {
|
|
91
|
-
const [variable, ...rest] = v.split('=');
|
|
92
|
-
return { variable: variable.trim(), value: rest.join('=').trim() };
|
|
93
|
-
}).filter(v => v.variable && v.value);
|
|
94
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
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 { DirectMessageCommandOptions } from '../../types/message.js';
|
|
7
|
-
import { createSpinner } from '../../utils/ui.js';
|
|
8
|
-
|
|
9
|
-
export const sendMessageCommand = new Command('send-message')
|
|
10
|
-
.description('Send a direct WhatsApp message')
|
|
11
|
-
.requiredOption('-t, --to <phone>', 'Phone number (with country code, e.g.: 51912345678)')
|
|
12
|
-
.requiredOption('-m, --message <text>', 'Message to send')
|
|
13
|
-
.option('--dev', 'Use development environment', false)
|
|
14
|
-
.action(async (options: DirectMessageCommandOptions) => {
|
|
15
|
-
try {
|
|
16
|
-
const credentials = await getStoredCredentials();
|
|
17
|
-
|
|
18
|
-
const messageClient = new Message({
|
|
19
|
-
workspaceId: credentials.workspace,
|
|
20
|
-
apiKey: credentials.apiKey,
|
|
21
|
-
zone: credentials.zone,
|
|
22
|
-
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
logger.title('Sending WhatsApp message');
|
|
26
|
-
logger.label('Destination', options.to);
|
|
27
|
-
logger.label('Message', options.message);
|
|
28
|
-
|
|
29
|
-
const spinner = createSpinner('Sending...');
|
|
30
|
-
spinner.start();
|
|
31
|
-
|
|
32
|
-
const response = await messageClient.onWhatsappMessage({
|
|
33
|
-
message: options.message,
|
|
34
|
-
to: options.to
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
spinner.succeed('Message sent successfully');
|
|
38
|
-
|
|
39
|
-
if (options.dev) {
|
|
40
|
-
logger.warning('Environment: development');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
} catch (error: unknown) {
|
|
44
|
-
const message = (error as Error)?.message || 'Unknown error while sending the message';
|
|
45
|
-
logger.error(message);
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
addExamples(sendMessageCommand, [
|
|
51
|
-
{ description: 'Send a quick WhatsApp message',
|
|
52
|
-
command: 'plazbot whatsapp send-message -t 51912345678 -m "Hello from Plazbot"' },
|
|
53
|
-
{ description: 'Send through the development backend',
|
|
54
|
-
command: 'plazbot whatsapp send-message -t 51912345678 -m "Hi" --dev' },
|
|
55
|
-
]);
|
|
@@ -1,75 +0,0 @@
|
|
|
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
|
-
|
|
8
|
-
const widgetGroup = new Command('widget')
|
|
9
|
-
.description('Manage WhatsApp widget');
|
|
10
|
-
|
|
11
|
-
addExamples(widgetGroup, [
|
|
12
|
-
{ description: 'Enable the WhatsApp click-to-chat widget on an agent',
|
|
13
|
-
command: 'plazbot whatsapp widget enable agt_AbcDef123 -u https://wa.me/51912345678' },
|
|
14
|
-
{ description: 'Disable the widget',
|
|
15
|
-
command: 'plazbot whatsapp widget disable agt_AbcDef123' },
|
|
16
|
-
]);
|
|
17
|
-
|
|
18
|
-
widgetGroup.command('enable')
|
|
19
|
-
.description('Enable the WhatsApp widget on an agent')
|
|
20
|
-
.argument('<agentId>', 'Agent ID')
|
|
21
|
-
.requiredOption('-u, --url <url>', 'WhatsApp URL (e.g.: https://wa.me/51912345678)')
|
|
22
|
-
.option('--dev', 'Use development environment', false)
|
|
23
|
-
.action(async (agentId: string, options: any) => {
|
|
24
|
-
try {
|
|
25
|
-
const credentials = await getStoredCredentials();
|
|
26
|
-
const agent = new Agent({
|
|
27
|
-
workspaceId: credentials.workspace,
|
|
28
|
-
apiKey: credentials.apiKey,
|
|
29
|
-
zone: credentials.zone,
|
|
30
|
-
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const spinner = createSpinner('Enabling WhatsApp widget...');
|
|
34
|
-
spinner.start();
|
|
35
|
-
await agent.updateAgent(agentId, {
|
|
36
|
-
enableWhatsappWidget: true,
|
|
37
|
-
urlWhatsappWidget: options.url,
|
|
38
|
-
});
|
|
39
|
-
spinner.succeed('WhatsApp widget enabled');
|
|
40
|
-
logger.label('URL', options.url);
|
|
41
|
-
|
|
42
|
-
} catch (error) {
|
|
43
|
-
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
44
|
-
logger.error(message);
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
widgetGroup.command('disable')
|
|
50
|
-
.description('Disable the WhatsApp widget on an agent')
|
|
51
|
-
.argument('<agentId>', 'Agent ID')
|
|
52
|
-
.option('--dev', 'Use development environment', false)
|
|
53
|
-
.action(async (agentId: string, options: any) => {
|
|
54
|
-
try {
|
|
55
|
-
const credentials = await getStoredCredentials();
|
|
56
|
-
const agent = new Agent({
|
|
57
|
-
workspaceId: credentials.workspace,
|
|
58
|
-
apiKey: credentials.apiKey,
|
|
59
|
-
zone: credentials.zone,
|
|
60
|
-
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const spinner = createSpinner('Disabling WhatsApp widget...');
|
|
64
|
-
spinner.start();
|
|
65
|
-
await agent.updateAgent(agentId, { enableWhatsappWidget: false });
|
|
66
|
-
spinner.succeed('WhatsApp widget disabled');
|
|
67
|
-
|
|
68
|
-
} catch (error) {
|
|
69
|
-
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
70
|
-
logger.error(message);
|
|
71
|
-
process.exit(1);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
export const widgetCommand = widgetGroup;
|
|
@@ -1,156 +0,0 @@
|
|
|
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
|
-
import { WorkerDeployOptions, WorkerDeployResult } from '../../types/workers.js';
|
|
10
|
-
|
|
11
|
-
export const deployCommand = new Command('deploy')
|
|
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)
|
|
17
|
-
.action(async (file: string | undefined, options: WorkerDeployOptions) => {
|
|
18
|
-
try {
|
|
19
|
-
const credentials = await getStoredCredentials();
|
|
20
|
-
|
|
21
|
-
// Buscar archivos de workers
|
|
22
|
-
const files = await resolveWorkerFiles(file);
|
|
23
|
-
|
|
24
|
-
if (files.length === 0) {
|
|
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)');
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const api = createApiClient({
|
|
32
|
-
apiKey: credentials.apiKey,
|
|
33
|
-
workspace: credentials.workspace,
|
|
34
|
-
zone: credentials.zone,
|
|
35
|
-
dev: options.dev,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
logger.title(`Deploying ${files.length} worker${files.length > 1 ? 's' : ''}`);
|
|
39
|
-
console.log();
|
|
40
|
-
|
|
41
|
-
const results: { file: string; result?: WorkerDeployResult; error?: string }[] = [];
|
|
42
|
-
|
|
43
|
-
for (const filePath of files) {
|
|
44
|
-
const fileName = path.basename(filePath);
|
|
45
|
-
const spinner = createSpinner(`Deploying ${fileName}...`);
|
|
46
|
-
spinner.start();
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
// Leer archivo fuente
|
|
50
|
-
const sourceCode = await fs.readFile(filePath, 'utf-8');
|
|
51
|
-
|
|
52
|
-
// Enviar al API
|
|
53
|
-
const response = await api.post('/api/worker/deploy', {
|
|
54
|
-
sourceCode,
|
|
55
|
-
fileName,
|
|
56
|
-
name: files.length === 1 ? options.name : undefined,
|
|
57
|
-
description: files.length === 1 ? options.description : undefined,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const data = response.data as WorkerDeployResult;
|
|
61
|
-
spinner.succeed(`${fileName} → ${data.name} (${data.type})`);
|
|
62
|
-
results.push({ file: fileName, result: data });
|
|
63
|
-
|
|
64
|
-
} catch (error: any) {
|
|
65
|
-
const msg = error.response?.data?.message || error.message || 'Unknown error';
|
|
66
|
-
spinner.fail(`${fileName}: ${msg}`);
|
|
67
|
-
results.push({ file: fileName, error: msg });
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Resumen
|
|
72
|
-
console.log();
|
|
73
|
-
const success = results.filter(r => r.result);
|
|
74
|
-
const failed = results.filter(r => r.error);
|
|
75
|
-
|
|
76
|
-
if (success.length > 0) {
|
|
77
|
-
logger.success(`${success.length} worker${success.length > 1 ? 's' : ''} deployed`);
|
|
78
|
-
|
|
79
|
-
const rows = success.map(r => [
|
|
80
|
-
r.result!.name,
|
|
81
|
-
r.result!.type,
|
|
82
|
-
r.result!.status,
|
|
83
|
-
r.result!.webhookUrl || r.result!.cronExpression || '—',
|
|
84
|
-
]);
|
|
85
|
-
|
|
86
|
-
console.log(createTable(
|
|
87
|
-
['Name', 'Type', 'Status', 'URL/Cron'],
|
|
88
|
-
rows,
|
|
89
|
-
));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (failed.length > 0) {
|
|
93
|
-
logger.warning(`${failed.length} worker${failed.length > 1 ? 's' : ''} failed`);
|
|
94
|
-
failed.forEach(f => logger.dim(` ${f.file}: ${f.error}`));
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Mostrar webhook URLs si hay
|
|
98
|
-
const webhooks = success.filter(r => r.result!.webhookUrl);
|
|
99
|
-
if (webhooks.length > 0) {
|
|
100
|
-
console.log();
|
|
101
|
-
logger.title('Webhook URLs');
|
|
102
|
-
webhooks.forEach(w => {
|
|
103
|
-
logger.label(w.result!.name, theme.secondary(w.result!.webhookUrl!));
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
console.log();
|
|
108
|
-
|
|
109
|
-
if (options.dev) {
|
|
110
|
-
logger.warning('Environment: development');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
} catch (error) {
|
|
114
|
-
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
115
|
-
logger.error(message);
|
|
116
|
-
process.exit(1);
|
|
117
|
-
}
|
|
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
|
-
|
|
131
|
-
// Resuelve los archivos a desplegar
|
|
132
|
-
async function resolveWorkerFiles(file?: string): Promise<string[]> {
|
|
133
|
-
if (file) {
|
|
134
|
-
// Archivo especifico
|
|
135
|
-
const resolved = path.resolve(file);
|
|
136
|
-
try {
|
|
137
|
-
await fs.access(resolved);
|
|
138
|
-
return [resolved];
|
|
139
|
-
} catch {
|
|
140
|
-
throw new Error(`File not found: ${file}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Buscar en ./workers/ automaticamente
|
|
145
|
-
const workersDir = path.resolve('workers');
|
|
146
|
-
try {
|
|
147
|
-
const entries = await fs.readdir(workersDir);
|
|
148
|
-
const tsFiles = entries
|
|
149
|
-
.filter(e => e.endsWith('.ts') && !e.endsWith('.d.ts'))
|
|
150
|
-
.map(e => path.join(workersDir, e));
|
|
151
|
-
|
|
152
|
-
return tsFiles;
|
|
153
|
-
} catch {
|
|
154
|
-
return [];
|
|
155
|
-
}
|
|
156
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
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
|
-
|
|
10
|
-
export const workersCommands = new Command('workers')
|
|
11
|
-
.description('Commands to manage workers (tools, syncs, schedules, webhooks)')
|
|
12
|
-
.addCommand(deployCommand)
|
|
13
|
-
.addCommand(listCommand)
|
|
14
|
-
.addCommand(logsCommand)
|
|
15
|
-
.addCommand(removeCommand)
|
|
16
|
-
.addCommand(secretCommand)
|
|
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,105 +0,0 @@
|
|
|
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, statusBadge, formatDate } from '../../utils/ui.js';
|
|
7
|
-
import { WorkerListOptions, WorkerListItem } from '../../types/workers.js';
|
|
8
|
-
|
|
9
|
-
export const listCommand = new Command('list')
|
|
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)
|
|
14
|
-
.action(async (options: WorkerListOptions) => {
|
|
15
|
-
try {
|
|
16
|
-
const credentials = await getStoredCredentials();
|
|
17
|
-
const api = createApiClient({
|
|
18
|
-
apiKey: credentials.apiKey,
|
|
19
|
-
workspace: credentials.workspace,
|
|
20
|
-
zone: credentials.zone,
|
|
21
|
-
dev: options.dev,
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const spinner = createSpinner('Fetching workers...');
|
|
25
|
-
spinner.start();
|
|
26
|
-
|
|
27
|
-
const params: Record<string, string> = {};
|
|
28
|
-
if (options.type) params.type = options.type;
|
|
29
|
-
if (options.status) params.status = options.status;
|
|
30
|
-
|
|
31
|
-
const response = await api.get('/api/worker', { params });
|
|
32
|
-
const workers: WorkerListItem[] = response.data;
|
|
33
|
-
|
|
34
|
-
spinner.stop();
|
|
35
|
-
|
|
36
|
-
if (!workers || workers.length === 0) {
|
|
37
|
-
logger.info('\n No workers found in this workspace');
|
|
38
|
-
logger.dim(' Deploy your first worker: plazbot workers deploy ./workers/my-tool.ts');
|
|
39
|
-
console.log();
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
logger.title(`Workers (${workers.length})`);
|
|
44
|
-
|
|
45
|
-
const rows = workers.map(w => [
|
|
46
|
-
w.name,
|
|
47
|
-
typeLabel(w.type),
|
|
48
|
-
w.status === 'active' ? theme.success('active')
|
|
49
|
-
: w.status === 'error' ? theme.error('error')
|
|
50
|
-
: theme.muted('inactive'),
|
|
51
|
-
`${w.executionCount}`,
|
|
52
|
-
w.errorCount > 0 ? theme.error(`${w.errorCount}`) : theme.muted('0'),
|
|
53
|
-
w.avgDurationMs > 0 ? `${w.avgDurationMs}ms` : '—',
|
|
54
|
-
w.lastExecutedAt ? formatDate(w.lastExecutedAt) : '—',
|
|
55
|
-
]);
|
|
56
|
-
|
|
57
|
-
console.log(createTable(
|
|
58
|
-
['Name', 'Type', 'Status', 'Executions', 'Errors', 'Duration', 'Last execution'],
|
|
59
|
-
rows,
|
|
60
|
-
));
|
|
61
|
-
|
|
62
|
-
// Mostrar workers con error
|
|
63
|
-
const errored = workers.filter(w => w.status === 'error');
|
|
64
|
-
if (errored.length > 0) {
|
|
65
|
-
console.log();
|
|
66
|
-
logger.warning('Workers with errors:');
|
|
67
|
-
errored.forEach(w => {
|
|
68
|
-
logger.dim(` ${w.name}: ${w.lastError || 'no details'}`);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
console.log();
|
|
73
|
-
|
|
74
|
-
if (options.dev) {
|
|
75
|
-
logger.warning('Environment: development');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
} catch (error) {
|
|
79
|
-
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
80
|
-
logger.error(message);
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
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
|
-
|
|
96
|
-
function typeLabel(type: string): string {
|
|
97
|
-
const labels: Record<string, string> = {
|
|
98
|
-
tool: theme.secondary('tool'),
|
|
99
|
-
worker: theme.primary('worker'),
|
|
100
|
-
sync: theme.accent('sync'),
|
|
101
|
-
schedule: theme.muted('schedule'),
|
|
102
|
-
webhook: theme.warning('webhook'),
|
|
103
|
-
};
|
|
104
|
-
return labels[type] || type;
|
|
105
|
-
}
|