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,65 +1,60 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
14
|
-
exports.whatsappChatCommand = new commander_1.Command('chat')
|
|
15
|
-
.description('Chat interactivo directo por WhatsApp')
|
|
16
|
-
.argument('<phone>', 'Numero de telefono destino (con codigo de pais)')
|
|
17
|
-
.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
|
+
import readline from 'readline';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
export const whatsappChatCommand = new Command('chat')
|
|
10
|
+
.description('Interactive direct chat over WhatsApp')
|
|
11
|
+
.argument('<phone>', 'Destination phone number (with country code)')
|
|
12
|
+
.option('--dev', 'Use development environment', false)
|
|
18
13
|
.action(async (phone, options) => {
|
|
19
14
|
try {
|
|
20
|
-
const credentials = await
|
|
21
|
-
const messageClient = new
|
|
15
|
+
const credentials = await getStoredCredentials();
|
|
16
|
+
const messageClient = new Message({
|
|
22
17
|
workspaceId: credentials.workspace,
|
|
23
18
|
apiKey: credentials.apiKey,
|
|
24
19
|
zone: credentials.zone,
|
|
25
20
|
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
26
21
|
});
|
|
27
|
-
const rl =
|
|
22
|
+
const rl = readline.createInterface({
|
|
28
23
|
input: process.stdin,
|
|
29
24
|
output: process.stdout,
|
|
30
25
|
});
|
|
31
26
|
console.clear();
|
|
32
27
|
console.log();
|
|
33
|
-
console.log(
|
|
34
|
-
console.log(
|
|
35
|
-
console.log(
|
|
36
|
-
console.log(
|
|
37
|
-
console.log(
|
|
28
|
+
console.log(chalk.hex('#25D366')(' ┌' + '─'.repeat(50) + '┐'));
|
|
29
|
+
console.log(chalk.hex('#25D366')(' │') + chalk.bold(` WhatsApp Chat`).padEnd(60) + chalk.hex('#25D366')('│'));
|
|
30
|
+
console.log(chalk.hex('#25D366')(' │') + chalk.gray(` Destination: ${phone}`).padEnd(60) + chalk.hex('#25D366')('│'));
|
|
31
|
+
console.log(chalk.hex('#25D366')(' │') + chalk.gray(' /exit to quit').padEnd(60) + chalk.hex('#25D366')('│'));
|
|
32
|
+
console.log(chalk.hex('#25D366')(' └' + '─'.repeat(50) + '┘'));
|
|
38
33
|
console.log();
|
|
39
34
|
const ask = () => {
|
|
40
|
-
rl.question(
|
|
35
|
+
rl.question(chalk.hex('#25D366')(' > '), async (message) => {
|
|
41
36
|
if (!message.trim()) {
|
|
42
37
|
ask();
|
|
43
38
|
return;
|
|
44
39
|
}
|
|
45
40
|
if (message.toLowerCase() === '/exit') {
|
|
46
|
-
console.log(
|
|
41
|
+
console.log(chalk.gray('\n Chat ended.\n'));
|
|
47
42
|
rl.close();
|
|
48
43
|
return;
|
|
49
44
|
}
|
|
50
45
|
try {
|
|
51
|
-
const spinner =
|
|
46
|
+
const spinner = createSpinner('Sending...');
|
|
52
47
|
spinner.start();
|
|
53
48
|
await messageClient.onWhatsappMessage({
|
|
54
49
|
message,
|
|
55
50
|
to: phone,
|
|
56
51
|
});
|
|
57
|
-
spinner.succeed('
|
|
52
|
+
spinner.succeed('Sent');
|
|
58
53
|
ask();
|
|
59
54
|
}
|
|
60
55
|
catch (error) {
|
|
61
56
|
const msg = error instanceof Error ? error.message : 'Error';
|
|
62
|
-
console.log(
|
|
57
|
+
console.log(chalk.hex('#EF5350')(` ✖ ${msg}`));
|
|
63
58
|
ask();
|
|
64
59
|
}
|
|
65
60
|
});
|
|
@@ -67,8 +62,14 @@ exports.whatsappChatCommand = new commander_1.Command('chat')
|
|
|
67
62
|
ask();
|
|
68
63
|
}
|
|
69
64
|
catch (error) {
|
|
70
|
-
const message = error instanceof Error ? error.message : '
|
|
71
|
-
|
|
65
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
66
|
+
logger.error(message);
|
|
72
67
|
process.exit(1);
|
|
73
68
|
}
|
|
74
69
|
});
|
|
70
|
+
addExamples(whatsappChatCommand, [
|
|
71
|
+
{ description: 'Open an interactive chat with a WhatsApp number',
|
|
72
|
+
command: 'plazbot whatsapp chat 51912345678' },
|
|
73
|
+
{ description: 'Chat through the development backend',
|
|
74
|
+
command: 'plazbot whatsapp chat 51912345678 --dev' },
|
|
75
|
+
]);
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const ora_1 = __importDefault(require("ora"));
|
|
10
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
-
const credentials_1 = require("../../utils/credentials");
|
|
12
|
-
const logger_1 = require("../../utils/logger");
|
|
13
|
-
const ui_1 = require("../../utils/ui");
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { getStoredCredentials } from '../../utils/credentials.js';
|
|
6
|
+
import { logger } from '../../utils/logger.js';
|
|
7
|
+
import { addExamples } from '../../utils/help.js';
|
|
8
|
+
import { theme, section } from '../../utils/ui.js';
|
|
14
9
|
function getBaseUrl(zone, dev) {
|
|
15
10
|
if (dev)
|
|
16
11
|
return 'http://localhost:5090';
|
|
@@ -26,7 +21,7 @@ function getIntegrationLabel(ig) {
|
|
|
26
21
|
}
|
|
27
22
|
async function fetchWorkspaceIntegrations(baseUrl, workspaceId, headers) {
|
|
28
23
|
try {
|
|
29
|
-
const wkRes = await
|
|
24
|
+
const wkRes = await axios.get(`${baseUrl}/api/workspace/${workspaceId}`, { headers });
|
|
30
25
|
const wsData = Array.isArray(wkRes.data) ? wkRes.data[0] : wkRes.data;
|
|
31
26
|
return wsData?.integrations || [];
|
|
32
27
|
}
|
|
@@ -36,20 +31,20 @@ async function fetchWorkspaceIntegrations(baseUrl, workspaceId, headers) {
|
|
|
36
31
|
}
|
|
37
32
|
async function activateIntegration(baseUrl, workspaceId, integrationId, headers) {
|
|
38
33
|
try {
|
|
39
|
-
const res = await
|
|
34
|
+
const res = await axios.post(`${baseUrl}/api/workspace/${workspaceId}/integrations/${integrationId}/activate`, { isActive: true }, { headers });
|
|
40
35
|
return res.data?.success === true;
|
|
41
36
|
}
|
|
42
37
|
catch {
|
|
43
38
|
return false;
|
|
44
39
|
}
|
|
45
40
|
}
|
|
46
|
-
|
|
47
|
-
.description('
|
|
48
|
-
.option('--dev', '
|
|
49
|
-
.option('--business', '
|
|
41
|
+
export const whatsappConnectCommand = new Command('connect')
|
|
42
|
+
.description('Connect a WhatsApp number to the workspace (without creating an agent)')
|
|
43
|
+
.option('--dev', 'Use development environment', false)
|
|
44
|
+
.option('--business', 'Connect as WhatsApp Business', false)
|
|
50
45
|
.action(async (options) => {
|
|
51
46
|
try {
|
|
52
|
-
const credentials = await
|
|
47
|
+
const credentials = await getStoredCredentials();
|
|
53
48
|
const baseUrl = getBaseUrl(credentials.zone, options.dev);
|
|
54
49
|
const headers = {
|
|
55
50
|
'Authorization': `Bearer ${credentials.apiKey}`,
|
|
@@ -58,29 +53,29 @@ exports.whatsappConnectCommand = new commander_1.Command('connect')
|
|
|
58
53
|
};
|
|
59
54
|
const channelType = options.business ? 'whatsapp_business' : 'whatsapp';
|
|
60
55
|
const channelLabel = options.business ? 'WhatsApp Business' : 'WhatsApp';
|
|
61
|
-
console.log(
|
|
56
|
+
console.log(section(`Connect ${channelLabel}`));
|
|
62
57
|
console.log();
|
|
63
58
|
// Cargar integraciones existentes
|
|
64
|
-
const loadSpinner = (
|
|
59
|
+
const loadSpinner = ora({ text: chalk.gray('Loading existing integrations...'), spinner: 'dots', color: 'green' }).start();
|
|
65
60
|
const allIntegrations = await fetchWorkspaceIntegrations(baseUrl, credentials.workspace, headers);
|
|
66
61
|
const existing = allIntegrations.filter((ig) => ig.type === 'whatsapp');
|
|
67
62
|
loadSpinner.stop();
|
|
68
63
|
if (existing.length > 0) {
|
|
69
|
-
console.log(
|
|
64
|
+
console.log(theme.muted(` ${existing.length} number(s) already connected:`));
|
|
70
65
|
existing.forEach((ig) => {
|
|
71
66
|
const label = getIntegrationLabel(ig);
|
|
72
|
-
const status = ig.isActive ?
|
|
73
|
-
console.log(` ${
|
|
67
|
+
const status = ig.isActive ? chalk.hex('#66BB6A')('active') : chalk.hex('#EF5350')('inactive');
|
|
68
|
+
console.log(` ${theme.muted('•')} ${label} ${status}`);
|
|
74
69
|
});
|
|
75
70
|
console.log();
|
|
76
71
|
}
|
|
77
72
|
// Obtener o generar link de onboarding (mismo flujo que Plazbot Front)
|
|
78
73
|
const ONBOARDING_SHORT_DOMAIN = 'https://co.plzb.link';
|
|
79
|
-
const spinner = (
|
|
74
|
+
const spinner = ora({ text: chalk.gray('Fetching connection link...'), spinner: 'dots', color: 'green' }).start();
|
|
80
75
|
let linkData = null;
|
|
81
76
|
// 1. Intentar obtener link existente (GET)
|
|
82
77
|
try {
|
|
83
|
-
const getRes = await
|
|
78
|
+
const getRes = await axios.get(`${baseUrl}/api/workspace/${credentials.workspace}/onboarding-link`, { headers, params: { type: channelType } });
|
|
84
79
|
linkData = getRes.data?.data ?? null;
|
|
85
80
|
}
|
|
86
81
|
catch {
|
|
@@ -89,7 +84,7 @@ exports.whatsappConnectCommand = new commander_1.Command('connect')
|
|
|
89
84
|
// 2. Si existe pero esta expirado, regenerar
|
|
90
85
|
if (linkData?.expiresAt && new Date(linkData.expiresAt) < new Date()) {
|
|
91
86
|
try {
|
|
92
|
-
const regenRes = await
|
|
87
|
+
const regenRes = await axios.post(`${baseUrl}/api/workspace/${credentials.workspace}/onboarding-link/regenerate`, { type: channelType }, { headers });
|
|
93
88
|
linkData = regenRes.data?.data ?? null;
|
|
94
89
|
}
|
|
95
90
|
catch {
|
|
@@ -99,7 +94,7 @@ exports.whatsappConnectCommand = new commander_1.Command('connect')
|
|
|
99
94
|
// 3. Si no existe, generar uno nuevo (POST)
|
|
100
95
|
if (!linkData?.token) {
|
|
101
96
|
try {
|
|
102
|
-
const createRes = await
|
|
97
|
+
const createRes = await axios.post(`${baseUrl}/api/workspace/${credentials.workspace}/onboarding-link`, { type: channelType }, { headers });
|
|
103
98
|
linkData = createRes.data?.data ?? null;
|
|
104
99
|
}
|
|
105
100
|
catch {
|
|
@@ -107,31 +102,31 @@ exports.whatsappConnectCommand = new commander_1.Command('connect')
|
|
|
107
102
|
}
|
|
108
103
|
}
|
|
109
104
|
if (!linkData?.token) {
|
|
110
|
-
spinner.fail(
|
|
105
|
+
spinner.fail(chalk.hex('#EF5350')('Could not obtain the connection link'));
|
|
111
106
|
process.exit(1);
|
|
112
107
|
}
|
|
113
108
|
const shortUrl = `${ONBOARDING_SHORT_DOMAIN}/${linkData.token}`;
|
|
114
|
-
const expiresAt = linkData.expiresAt ? new Date(linkData.expiresAt).toLocaleDateString('
|
|
109
|
+
const expiresAt = linkData.expiresAt ? new Date(linkData.expiresAt).toLocaleDateString('en-US', { day: 'numeric', month: 'long', year: 'numeric' }) : '';
|
|
115
110
|
spinner.stop();
|
|
116
111
|
// Mostrar link
|
|
117
112
|
const W = 54;
|
|
118
113
|
const pad = (text) => text + ' '.repeat(Math.max(0, W - text.length));
|
|
119
|
-
const border =
|
|
114
|
+
const border = chalk.hex('#25D366');
|
|
120
115
|
console.log(border(' ┌' + '─'.repeat(W) + '┐'));
|
|
121
|
-
console.log(border(' │') +
|
|
116
|
+
console.log(border(' │') + chalk.bold(pad(' Open this link in your browser:')) + border('│'));
|
|
122
117
|
console.log(border(' │') + ' '.repeat(W) + border('│'));
|
|
123
|
-
console.log(border(' │') +
|
|
118
|
+
console.log(border(' │') + chalk.hex('#22d3ee')(pad(` ${shortUrl}`)) + border('│'));
|
|
124
119
|
console.log(border(' │') + ' '.repeat(W) + border('│'));
|
|
125
|
-
console.log(border(' │') +
|
|
120
|
+
console.log(border(' │') + chalk.gray(pad(' Scan the QR code from your WhatsApp')) + border('│'));
|
|
126
121
|
if (expiresAt) {
|
|
127
|
-
console.log(border(' │') +
|
|
122
|
+
console.log(border(' │') + chalk.gray(pad(` Expires: ${expiresAt}`)) + border('│'));
|
|
128
123
|
}
|
|
129
124
|
console.log(border(' └' + '─'.repeat(W) + '┘'));
|
|
130
125
|
console.log();
|
|
131
126
|
// Guardar IDs actuales para detectar nuevos
|
|
132
127
|
const prevIds = new Set(allIntegrations.map((i) => i.id));
|
|
133
128
|
// Polling para detectar nueva integracion
|
|
134
|
-
const pollSpinner = (
|
|
129
|
+
const pollSpinner = ora({ text: chalk.gray('Waiting for connection... (Ctrl+C to cancel)'), spinner: 'dots', color: 'cyan' }).start();
|
|
135
130
|
const POLL_INTERVAL = 5000;
|
|
136
131
|
const MAX_POLLS = 60; // 5 minutos
|
|
137
132
|
let detected = null;
|
|
@@ -148,39 +143,45 @@ exports.whatsappConnectCommand = new commander_1.Command('connect')
|
|
|
148
143
|
}
|
|
149
144
|
catch { }
|
|
150
145
|
const elapsed = Math.floor(((i + 1) * POLL_INTERVAL) / 1000);
|
|
151
|
-
pollSpinner.text =
|
|
146
|
+
pollSpinner.text = chalk.gray(`Waiting for connection... ${elapsed}s (Ctrl+C to cancel)`);
|
|
152
147
|
}
|
|
153
148
|
if (detected) {
|
|
154
149
|
const detectedName = getIntegrationLabel(detected);
|
|
155
|
-
pollSpinner.succeed(
|
|
150
|
+
pollSpinner.succeed(chalk.hex('#4ade80')(`Connection detected: ${detectedName}`));
|
|
156
151
|
// Activar la integracion
|
|
157
|
-
const actSpinner = (
|
|
152
|
+
const actSpinner = ora({ text: chalk.gray('Activating integration...'), spinner: 'dots', color: 'green' }).start();
|
|
158
153
|
const activated = await activateIntegration(baseUrl, credentials.workspace, detected.id, headers);
|
|
159
154
|
if (activated) {
|
|
160
|
-
actSpinner.succeed(
|
|
155
|
+
actSpinner.succeed(chalk.hex('#4ade80')('Integration activated successfully'));
|
|
161
156
|
}
|
|
162
157
|
else {
|
|
163
|
-
actSpinner.warn(
|
|
158
|
+
actSpinner.warn(chalk.hex('#FFA726')('Could not activate automatically. Activate it from the platform.'));
|
|
164
159
|
}
|
|
165
160
|
console.log();
|
|
166
|
-
console.log(
|
|
167
|
-
console.log(
|
|
161
|
+
console.log(theme.success(' WhatsApp connected successfully'));
|
|
162
|
+
console.log(theme.muted(` Number: ${detectedName}`));
|
|
168
163
|
console.log();
|
|
169
|
-
console.log(
|
|
170
|
-
console.log(
|
|
171
|
-
console.log(
|
|
172
|
-
console.log(
|
|
164
|
+
console.log(theme.muted(' You can now:'));
|
|
165
|
+
console.log(theme.muted(' plazbot whatsapp send-message Send a message'));
|
|
166
|
+
console.log(theme.muted(' plazbot whatsapp chat <phone> Interactive chat'));
|
|
167
|
+
console.log(theme.muted(' plazbot whatsapp assign <phone> <agentId> Assign to an agent'));
|
|
173
168
|
console.log();
|
|
174
169
|
}
|
|
175
170
|
else {
|
|
176
|
-
pollSpinner.warn(
|
|
177
|
-
console.log(
|
|
171
|
+
pollSpinner.warn(chalk.hex('#FFA726')('Timeout: no connection detected within 5 minutes.'));
|
|
172
|
+
console.log(theme.muted(' You can try again with: plazbot whatsapp connect'));
|
|
178
173
|
console.log();
|
|
179
174
|
}
|
|
180
175
|
}
|
|
181
176
|
catch (error) {
|
|
182
|
-
const message = error instanceof Error ? error.message : '
|
|
183
|
-
|
|
177
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
178
|
+
logger.error(message);
|
|
184
179
|
process.exit(1);
|
|
185
180
|
}
|
|
186
181
|
});
|
|
182
|
+
addExamples(whatsappConnectCommand, [
|
|
183
|
+
{ description: 'Generate a QR connection link for WhatsApp',
|
|
184
|
+
command: 'plazbot whatsapp connect' },
|
|
185
|
+
{ description: 'Connect a WhatsApp Business number',
|
|
186
|
+
command: 'plazbot whatsapp connect --business' },
|
|
187
|
+
]);
|
|
@@ -1,32 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
.
|
|
10
|
-
.requiredOption('-n, --number <phone>', 'Número de WhatsApp (con código de país, ej: 51912345678)')
|
|
11
|
-
.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
|
+
export const deleteWebhookCommand = new Command('delete-webhook')
|
|
7
|
+
.description('Delete the WhatsApp webhook')
|
|
8
|
+
.requiredOption('-n, --number <phone>', 'WhatsApp number (with country code, e.g.: 51912345678)')
|
|
9
|
+
.option('--dev', 'Use development environment', false)
|
|
12
10
|
.action(async (options) => {
|
|
13
11
|
try {
|
|
14
|
-
const credentials = await
|
|
15
|
-
const messageClient = new
|
|
12
|
+
const credentials = await getStoredCredentials();
|
|
13
|
+
const messageClient = new Message({
|
|
16
14
|
workspaceId: credentials.workspace,
|
|
17
15
|
apiKey: credentials.apiKey,
|
|
18
16
|
zone: credentials.zone,
|
|
19
17
|
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
20
18
|
});
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
logger.title('Deleting WhatsApp webhook');
|
|
20
|
+
logger.label('Number', options.number);
|
|
23
21
|
await messageClient.deleteWebhook({
|
|
24
22
|
number: options.number
|
|
25
23
|
});
|
|
26
|
-
|
|
24
|
+
logger.success('Webhook deleted successfully');
|
|
27
25
|
}
|
|
28
26
|
catch (error) {
|
|
29
|
-
|
|
27
|
+
logger.error(error.message);
|
|
30
28
|
process.exit(1);
|
|
31
29
|
}
|
|
32
30
|
});
|
|
31
|
+
addExamples(deleteWebhookCommand, [
|
|
32
|
+
{ description: 'Remove the webhook from a WhatsApp number',
|
|
33
|
+
command: 'plazbot whatsapp delete-webhook -n 51912345678' },
|
|
34
|
+
]);
|
|
@@ -1,25 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
.
|
|
16
|
-
.addCommand(
|
|
17
|
-
.addCommand(
|
|
18
|
-
.addCommand(
|
|
19
|
-
.addCommand(
|
|
20
|
-
.addCommand(
|
|
21
|
-
.addCommand(
|
|
22
|
-
.addCommand(
|
|
23
|
-
.addCommand(
|
|
24
|
-
|
|
25
|
-
|
|
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
|
+
export const whatsappCommands = new Command('whatsapp')
|
|
13
|
+
.description('WhatsApp commands: messages, templates, broadcast and more')
|
|
14
|
+
.addCommand(whatsappConnectCommand)
|
|
15
|
+
.addCommand(sendMessageCommand)
|
|
16
|
+
.addCommand(sendTemplateCommand)
|
|
17
|
+
.addCommand(registerWebhookCommand)
|
|
18
|
+
.addCommand(deleteWebhookCommand)
|
|
19
|
+
.addCommand(broadcastCommand)
|
|
20
|
+
.addCommand(whatsappChatCommand)
|
|
21
|
+
.addCommand(widgetCommand)
|
|
22
|
+
.addCommand(channelsCommand)
|
|
23
|
+
.addCommand(assignCommand);
|
|
24
|
+
addExamples(whatsappCommands, [
|
|
25
|
+
{ description: 'Connect a WhatsApp number to the workspace',
|
|
26
|
+
command: 'plazbot whatsapp connect' },
|
|
27
|
+
{ description: 'Send a quick message',
|
|
28
|
+
command: 'plazbot whatsapp send-message -t 51912345678 -m "Hello"' },
|
|
29
|
+
{ description: 'Send a template with variables',
|
|
30
|
+
command: 'plazbot whatsapp send-template -p 51912345678 -t welcome --var name=Anna' },
|
|
31
|
+
{ description: 'Open an interactive chat',
|
|
32
|
+
command: 'plazbot whatsapp chat 51912345678' },
|
|
33
|
+
{ description: 'Assign a number to an agent',
|
|
34
|
+
command: 'plazbot whatsapp assign 51912345678 agt_AbcDef123' },
|
|
35
|
+
]);
|
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
.
|
|
10
|
-
.
|
|
11
|
-
.requiredOption('-u, --url <webhook>', 'URL del webhook')
|
|
12
|
-
.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
|
+
export const registerWebhookCommand = new Command('register-webhook')
|
|
7
|
+
.description('Register a webhook for WhatsApp')
|
|
8
|
+
.requiredOption('-n, --number <phone>', 'WhatsApp number (with country code, e.g.: 51912345678)')
|
|
9
|
+
.requiredOption('-u, --url <webhook>', 'Webhook URL')
|
|
10
|
+
.option('--dev', 'Use development environment', false)
|
|
13
11
|
.action(async (options) => {
|
|
14
12
|
try {
|
|
15
|
-
const credentials = await
|
|
16
|
-
const messageClient = new
|
|
13
|
+
const credentials = await getStoredCredentials();
|
|
14
|
+
const messageClient = new Message({
|
|
17
15
|
workspaceId: credentials.workspace,
|
|
18
16
|
apiKey: credentials.apiKey,
|
|
19
17
|
zone: credentials.zone,
|
|
20
18
|
...(options.dev && { customUrl: "http://localhost:5090" })
|
|
21
19
|
});
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
logger.title('Registering WhatsApp webhook');
|
|
21
|
+
logger.label('Number', options.number);
|
|
22
|
+
logger.label('URL', options.url);
|
|
25
23
|
await messageClient.registerWebhook({
|
|
26
24
|
number: options.number,
|
|
27
25
|
webhookUrl: options.url
|
|
28
26
|
});
|
|
29
|
-
|
|
27
|
+
logger.success('Webhook registered successfully');
|
|
30
28
|
}
|
|
31
29
|
catch (error) {
|
|
32
|
-
|
|
30
|
+
logger.error(error.message);
|
|
33
31
|
process.exit(1);
|
|
34
32
|
}
|
|
35
33
|
});
|
|
34
|
+
addExamples(registerWebhookCommand, [
|
|
35
|
+
{ description: 'Register an inbound webhook for a WhatsApp number',
|
|
36
|
+
command: 'plazbot whatsapp register-webhook -n 51912345678 -u https://api.example.com/webhooks/whatsapp' },
|
|
37
|
+
]);
|
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.
|
|
11
|
-
.
|
|
12
|
-
.
|
|
13
|
-
.option('--
|
|
14
|
-
.option('--
|
|
15
|
-
.option('--
|
|
16
|
-
.option('--file-name <name>', 'Nombre del archivo adjunto')
|
|
17
|
-
.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 sendTemplateCommand = new Command('send-template')
|
|
8
|
+
.description('Send a WhatsApp template message with variables')
|
|
9
|
+
.requiredOption('-p, --phone <number>', 'Phone number (with country code)')
|
|
10
|
+
.requiredOption('-t, --template <name>', 'Template name')
|
|
11
|
+
.option('--var <vars...>', 'Body variables (format: name=value)')
|
|
12
|
+
.option('--header-var <vars...>', 'Header variables (format: name=value)')
|
|
13
|
+
.option('--file-url <url>', 'Attachment file URL')
|
|
14
|
+
.option('--file-name <name>', 'Attachment file name')
|
|
15
|
+
.option('--dev', 'Use development environment', false)
|
|
18
16
|
.action(async (options) => {
|
|
19
17
|
try {
|
|
20
|
-
const credentials = await
|
|
21
|
-
const messageClient = new
|
|
18
|
+
const credentials = await getStoredCredentials();
|
|
19
|
+
const messageClient = new Message({
|
|
22
20
|
workspaceId: credentials.workspace,
|
|
23
21
|
apiKey: credentials.apiKey,
|
|
24
22
|
zone: credentials.zone,
|
|
@@ -30,21 +28,21 @@ exports.sendTemplateCommand = new commander_1.Command('send-template')
|
|
|
30
28
|
// Archivo adjunto
|
|
31
29
|
const file = options.fileUrl ? {
|
|
32
30
|
fileUrl: options.fileUrl,
|
|
33
|
-
fileName: options.fileName || '
|
|
31
|
+
fileName: options.fileName || 'file',
|
|
34
32
|
} : undefined;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
logger.title('Sending WhatsApp template');
|
|
34
|
+
logger.label('Destination', options.phone);
|
|
35
|
+
logger.label('Template', options.template);
|
|
38
36
|
if (variablesBody.length > 0) {
|
|
39
|
-
|
|
37
|
+
logger.label('Body variables', variablesBody.map(v => `${v.variable}=${v.value}`).join(', '));
|
|
40
38
|
}
|
|
41
39
|
if (variablesHeader.length > 0) {
|
|
42
|
-
|
|
40
|
+
logger.label('Header variables', variablesHeader.map(v => `${v.variable}=${v.value}`).join(', '));
|
|
43
41
|
}
|
|
44
42
|
if (file) {
|
|
45
|
-
|
|
43
|
+
logger.label('File', file.fileUrl);
|
|
46
44
|
}
|
|
47
|
-
const spinner =
|
|
45
|
+
const spinner = createSpinner('Sending...');
|
|
48
46
|
spinner.start();
|
|
49
47
|
const params = {
|
|
50
48
|
to: options.phone,
|
|
@@ -57,17 +55,27 @@ exports.sendTemplateCommand = new commander_1.Command('send-template')
|
|
|
57
55
|
if (file)
|
|
58
56
|
params.file = file;
|
|
59
57
|
const response = await messageClient.onConversation(params);
|
|
60
|
-
spinner.succeed('Template
|
|
58
|
+
spinner.succeed('Template sent successfully');
|
|
61
59
|
if (options.dev) {
|
|
62
|
-
|
|
60
|
+
logger.warning('Environment: development');
|
|
63
61
|
}
|
|
64
62
|
}
|
|
65
63
|
catch (error) {
|
|
66
|
-
const message = error?.message || '
|
|
67
|
-
|
|
64
|
+
const message = error?.message || 'Unknown error while sending the template';
|
|
65
|
+
logger.error(message);
|
|
68
66
|
process.exit(1);
|
|
69
67
|
}
|
|
70
68
|
});
|
|
69
|
+
addExamples(sendTemplateCommand, [
|
|
70
|
+
{ description: 'Send a template with no variables',
|
|
71
|
+
command: 'plazbot whatsapp send-template -p 51912345678 -t welcome_message' },
|
|
72
|
+
{ description: 'Send a template with body variables',
|
|
73
|
+
command: 'plazbot whatsapp send-template -p 51912345678 -t order_status --var name=Anna code=PB-123' },
|
|
74
|
+
{ description: 'Send a template with an attached PDF',
|
|
75
|
+
command: 'plazbot whatsapp send-template -p 51912345678 -t invoice_template --file-url https://files.example.com/inv.pdf --file-name invoice.pdf' },
|
|
76
|
+
{ description: 'Send a template with header and body variables',
|
|
77
|
+
command: 'plazbot whatsapp send-template -p 51912345678 -t promo --header-var image=https://img.example.com/banner.png --var amount=20' },
|
|
78
|
+
]);
|
|
71
79
|
function parseVariables(vars) {
|
|
72
80
|
if (!vars)
|
|
73
81
|
return [];
|