plazbot-cli 0.2.25 → 0.3.1
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 +59 -55
- 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 +32 -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 +21 -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 +48 -36
- 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 +32 -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,28 +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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
console.log(
|
|
121
|
-
console.log(
|
|
122
|
-
console.log(
|
|
112
|
+
const W = 54;
|
|
113
|
+
const pad = (text) => text + ' '.repeat(Math.max(0, W - text.length));
|
|
114
|
+
const border = chalk.hex('#25D366');
|
|
115
|
+
console.log(border(' ┌' + '─'.repeat(W) + '┐'));
|
|
116
|
+
console.log(border(' │') + chalk.bold(pad(' Open this link in your browser:')) + border('│'));
|
|
117
|
+
console.log(border(' │') + ' '.repeat(W) + border('│'));
|
|
118
|
+
console.log(border(' │') + chalk.hex('#22d3ee')(pad(` ${shortUrl}`)) + border('│'));
|
|
119
|
+
console.log(border(' │') + ' '.repeat(W) + border('│'));
|
|
120
|
+
console.log(border(' │') + chalk.gray(pad(' Scan the QR code from your WhatsApp')) + border('│'));
|
|
123
121
|
if (expiresAt) {
|
|
124
|
-
console.log(
|
|
122
|
+
console.log(border(' │') + chalk.gray(pad(` Expires: ${expiresAt}`)) + border('│'));
|
|
125
123
|
}
|
|
126
|
-
console.log(
|
|
124
|
+
console.log(border(' └' + '─'.repeat(W) + '┘'));
|
|
127
125
|
console.log();
|
|
128
126
|
// Guardar IDs actuales para detectar nuevos
|
|
129
127
|
const prevIds = new Set(allIntegrations.map((i) => i.id));
|
|
130
128
|
// Polling para detectar nueva integracion
|
|
131
|
-
const pollSpinner = (
|
|
129
|
+
const pollSpinner = ora({ text: chalk.gray('Waiting for connection... (Ctrl+C to cancel)'), spinner: 'dots', color: 'cyan' }).start();
|
|
132
130
|
const POLL_INTERVAL = 5000;
|
|
133
131
|
const MAX_POLLS = 60; // 5 minutos
|
|
134
132
|
let detected = null;
|
|
@@ -145,39 +143,45 @@ exports.whatsappConnectCommand = new commander_1.Command('connect')
|
|
|
145
143
|
}
|
|
146
144
|
catch { }
|
|
147
145
|
const elapsed = Math.floor(((i + 1) * POLL_INTERVAL) / 1000);
|
|
148
|
-
pollSpinner.text =
|
|
146
|
+
pollSpinner.text = chalk.gray(`Waiting for connection... ${elapsed}s (Ctrl+C to cancel)`);
|
|
149
147
|
}
|
|
150
148
|
if (detected) {
|
|
151
149
|
const detectedName = getIntegrationLabel(detected);
|
|
152
|
-
pollSpinner.succeed(
|
|
150
|
+
pollSpinner.succeed(chalk.hex('#4ade80')(`Connection detected: ${detectedName}`));
|
|
153
151
|
// Activar la integracion
|
|
154
|
-
const actSpinner = (
|
|
152
|
+
const actSpinner = ora({ text: chalk.gray('Activating integration...'), spinner: 'dots', color: 'green' }).start();
|
|
155
153
|
const activated = await activateIntegration(baseUrl, credentials.workspace, detected.id, headers);
|
|
156
154
|
if (activated) {
|
|
157
|
-
actSpinner.succeed(
|
|
155
|
+
actSpinner.succeed(chalk.hex('#4ade80')('Integration activated successfully'));
|
|
158
156
|
}
|
|
159
157
|
else {
|
|
160
|
-
actSpinner.warn(
|
|
158
|
+
actSpinner.warn(chalk.hex('#FFA726')('Could not activate automatically. Activate it from the platform.'));
|
|
161
159
|
}
|
|
162
160
|
console.log();
|
|
163
|
-
console.log(
|
|
164
|
-
console.log(
|
|
161
|
+
console.log(theme.success(' WhatsApp connected successfully'));
|
|
162
|
+
console.log(theme.muted(` Number: ${detectedName}`));
|
|
165
163
|
console.log();
|
|
166
|
-
console.log(
|
|
167
|
-
console.log(
|
|
168
|
-
console.log(
|
|
169
|
-
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'));
|
|
170
168
|
console.log();
|
|
171
169
|
}
|
|
172
170
|
else {
|
|
173
|
-
pollSpinner.warn(
|
|
174
|
-
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'));
|
|
175
173
|
console.log();
|
|
176
174
|
}
|
|
177
175
|
}
|
|
178
176
|
catch (error) {
|
|
179
|
-
const message = error instanceof Error ? error.message : '
|
|
180
|
-
|
|
177
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
178
|
+
logger.error(message);
|
|
181
179
|
process.exit(1);
|
|
182
180
|
}
|
|
183
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 [];
|