plazbot-cli 0.2.26 → 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.
Files changed (178) hide show
  1. package/CLAUDE.md +34 -5
  2. package/README.md +21 -0
  3. package/dist/cli.js +32 -20
  4. package/dist/commands/agent/ai-config.js +98 -50
  5. package/dist/commands/agent/chat.js +80 -74
  6. package/dist/commands/agent/copy.js +23 -21
  7. package/dist/commands/agent/create.js +42 -72
  8. package/dist/commands/agent/delete.js +29 -30
  9. package/dist/commands/agent/enable-widget.js +30 -26
  10. package/dist/commands/agent/export.js +90 -77
  11. package/dist/commands/agent/files.js +68 -60
  12. package/dist/commands/agent/get.js +101 -87
  13. package/dist/commands/agent/index.js +53 -39
  14. package/dist/commands/agent/list.js +26 -24
  15. package/dist/commands/agent/monitor.js +91 -86
  16. package/dist/commands/agent/on-message.js +40 -37
  17. package/dist/commands/agent/set.js +62 -59
  18. package/dist/commands/agent/templates.js +109 -108
  19. package/dist/commands/agent/tools.js +64 -65
  20. package/dist/commands/agent/update.js +28 -27
  21. package/dist/commands/agent/validate.js +127 -0
  22. package/dist/commands/agent/wizard.js +152 -159
  23. package/dist/commands/auth/index.js +7 -10
  24. package/dist/commands/auth/login.js +50 -37
  25. package/dist/commands/auth/logout.js +16 -14
  26. package/dist/commands/auth/status.js +19 -16
  27. package/dist/commands/portal/add-agent.js +26 -24
  28. package/dist/commands/portal/add-link.js +21 -17
  29. package/dist/commands/portal/clear-links.js +17 -15
  30. package/dist/commands/portal/create.js +25 -21
  31. package/dist/commands/portal/delete.js +31 -30
  32. package/dist/commands/portal/get.js +33 -31
  33. package/dist/commands/portal/index.js +30 -22
  34. package/dist/commands/portal/list.js +34 -30
  35. package/dist/commands/portal/update.js +41 -33
  36. package/dist/commands/whatsapp/broadcast.js +40 -37
  37. package/dist/commands/whatsapp/channels.js +40 -34
  38. package/dist/commands/whatsapp/chat.js +33 -32
  39. package/dist/commands/whatsapp/connect.js +53 -52
  40. package/dist/commands/whatsapp/delete-webhook.js +19 -17
  41. package/dist/commands/whatsapp/index.js +35 -25
  42. package/dist/commands/whatsapp/register-webhook.js +21 -19
  43. package/dist/commands/whatsapp/send-template.js +39 -31
  44. package/dist/commands/whatsapp/send.js +27 -23
  45. package/dist/commands/whatsapp/widget.js +35 -31
  46. package/dist/commands/workers/deploy.js +49 -44
  47. package/dist/commands/workers/index.js +28 -18
  48. package/dist/commands/workers/list.js +43 -35
  49. package/dist/commands/workers/logs.js +38 -32
  50. package/dist/commands/workers/remove.js +38 -37
  51. package/dist/commands/workers/secret.js +63 -58
  52. package/dist/commands/workers/test.js +44 -36
  53. package/dist/schemas/agent.config.schema.json +569 -0
  54. package/dist/studio/api/sseClient.js +97 -0
  55. package/dist/studio/api/studioApi.js +25 -0
  56. package/dist/studio/api/types.js +16 -0
  57. package/dist/studio/components/AgentPanel.js +35 -0
  58. package/dist/studio/components/App.js +214 -0
  59. package/dist/studio/components/ChatLog.js +59 -0
  60. package/dist/studio/components/Footer.js +11 -0
  61. package/dist/studio/components/Header.js +8 -0
  62. package/dist/studio/components/Input.js +15 -0
  63. package/dist/studio/components/Message.js +56 -0
  64. package/dist/studio/components/Suggestions.js +11 -0
  65. package/dist/studio/components/ToolCall.js +33 -0
  66. package/dist/studio/components/WhatsappConnectCard.js +57 -0
  67. package/dist/studio/index.js +42 -0
  68. package/dist/studio/render/json.js +16 -0
  69. package/dist/studio/render/markdown.js +32 -0
  70. package/dist/studio/render/steps.js +58 -0
  71. package/dist/studio/runOneShot.js +96 -0
  72. package/dist/studio/runRepl.js +52 -0
  73. package/dist/studio/slash/handlers.js +199 -0
  74. package/dist/studio/slash/parser.js +46 -0
  75. package/dist/studio/slash/registry.js +16 -0
  76. package/dist/studio/state/store.js +181 -0
  77. package/dist/studio/whatsapp/api.js +63 -0
  78. package/dist/studio/whatsapp/polling.js +77 -0
  79. package/dist/studio/whatsapp/types.js +31 -0
  80. package/dist/types/agent.js +1 -2
  81. package/dist/types/auth.js +1 -2
  82. package/dist/types/common.js +1 -2
  83. package/dist/types/message.js +1 -2
  84. package/dist/types/portal.js +1 -2
  85. package/dist/types/workers.js +1 -2
  86. package/dist/utils/agent-errors.js +46 -0
  87. package/dist/utils/api.js +8 -9
  88. package/dist/utils/banner.js +33 -34
  89. package/dist/utils/credentials.js +12 -20
  90. package/dist/utils/help.js +44 -0
  91. package/dist/utils/logger.js +13 -19
  92. package/dist/utils/ui.js +35 -49
  93. package/package.json +21 -10
  94. package/src/cli.ts +24 -8
  95. package/src/commands/agent/ai-config.ts +89 -34
  96. package/src/commands/agent/chat.ts +49 -37
  97. package/src/commands/agent/copy.ts +19 -13
  98. package/src/commands/agent/create.ts +32 -22
  99. package/src/commands/agent/delete.ts +24 -18
  100. package/src/commands/agent/enable-widget.ts +31 -23
  101. package/src/commands/agent/export.ts +72 -51
  102. package/src/commands/agent/files.ts +51 -39
  103. package/src/commands/agent/get.ts +86 -66
  104. package/src/commands/agent/index.ts +36 -18
  105. package/src/commands/agent/list.ts +22 -16
  106. package/src/commands/agent/monitor.ts +67 -56
  107. package/src/commands/agent/on-message.ts +36 -27
  108. package/src/commands/agent/set.ts +47 -37
  109. package/src/commands/agent/templates.ts +90 -82
  110. package/src/commands/agent/tools.ts +53 -47
  111. package/src/commands/agent/update.ts +28 -20
  112. package/src/commands/agent/validate.ts +135 -0
  113. package/src/commands/agent/wizard.ts +114 -114
  114. package/src/commands/auth/index.ts +3 -3
  115. package/src/commands/auth/login.ts +44 -29
  116. package/src/commands/auth/logout.ts +16 -10
  117. package/src/commands/auth/status.ts +14 -8
  118. package/src/commands/portal/add-agent.ts +23 -17
  119. package/src/commands/portal/add-link.ts +17 -9
  120. package/src/commands/portal/clear-links.ts +13 -7
  121. package/src/commands/portal/create.ts +20 -12
  122. package/src/commands/portal/delete.ts +28 -20
  123. package/src/commands/portal/get.ts +25 -19
  124. package/src/commands/portal/index.ts +22 -10
  125. package/src/commands/portal/list.ts +27 -19
  126. package/src/commands/portal/update.ts +38 -26
  127. package/src/commands/whatsapp/broadcast.ts +28 -18
  128. package/src/commands/whatsapp/channels.ts +31 -20
  129. package/src/commands/whatsapp/chat.ts +20 -12
  130. package/src/commands/whatsapp/connect.ts +39 -31
  131. package/src/commands/whatsapp/delete-webhook.ts +15 -9
  132. package/src/commands/whatsapp/index.ts +24 -10
  133. package/src/commands/whatsapp/register-webhook.ts +16 -10
  134. package/src/commands/whatsapp/send-template.ts +33 -21
  135. package/src/commands/whatsapp/send.ts +23 -15
  136. package/src/commands/whatsapp/widget.ts +25 -17
  137. package/src/commands/workers/deploy.ts +34 -22
  138. package/src/commands/workers/index.ts +21 -7
  139. package/src/commands/workers/list.ts +31 -19
  140. package/src/commands/workers/logs.ts +30 -20
  141. package/src/commands/workers/remove.ts +30 -22
  142. package/src/commands/workers/secret.ts +46 -34
  143. package/src/commands/workers/test.ts +34 -22
  144. package/src/schemas/agent.config.schema.json +569 -0
  145. package/src/studio/api/sseClient.ts +91 -0
  146. package/src/studio/api/studioApi.ts +27 -0
  147. package/src/studio/api/types.ts +96 -0
  148. package/src/studio/components/App.tsx +266 -0
  149. package/src/studio/components/ChatLog.tsx +95 -0
  150. package/src/studio/components/Footer.tsx +38 -0
  151. package/src/studio/components/Header.tsx +39 -0
  152. package/src/studio/components/Input.tsx +32 -0
  153. package/src/studio/components/Message.tsx +87 -0
  154. package/src/studio/components/Suggestions.tsx +26 -0
  155. package/src/studio/components/ToolCall.tsx +58 -0
  156. package/src/studio/components/WhatsappConnectCard.tsx +139 -0
  157. package/src/studio/index.ts +58 -0
  158. package/src/studio/render/markdown.ts +32 -0
  159. package/src/studio/render/steps.ts +57 -0
  160. package/src/studio/runOneShot.ts +114 -0
  161. package/src/studio/runRepl.tsx +76 -0
  162. package/src/studio/slash/handlers.ts +226 -0
  163. package/src/studio/slash/parser.ts +41 -0
  164. package/src/studio/slash/registry.ts +54 -0
  165. package/src/studio/state/store.ts +273 -0
  166. package/src/studio/whatsapp/api.ts +96 -0
  167. package/src/studio/whatsapp/polling.ts +93 -0
  168. package/src/studio/whatsapp/types.ts +80 -0
  169. package/src/types/agent.ts +1 -1
  170. package/src/types/auth.ts +4 -3
  171. package/src/types/portal.ts +1 -1
  172. package/src/types/workers.ts +1 -1
  173. package/src/utils/agent-errors.ts +67 -0
  174. package/src/utils/api.ts +6 -0
  175. package/src/utils/banner.ts +14 -9
  176. package/src/utils/credentials.ts +6 -5
  177. package/src/utils/help.ts +51 -0
  178. package/tsconfig.json +9 -6
@@ -0,0 +1,63 @@
1
+ import { getBaseUrl } from '../api/studioApi.js';
2
+ function headers(opts) {
3
+ const h = {
4
+ 'Content-Type': 'application/json',
5
+ Authorization: `Bearer ${opts.apiKey}`,
6
+ 'x-workspace-id': opts.workspaceId,
7
+ };
8
+ if (opts.userId)
9
+ h['x-user-id'] = opts.userId;
10
+ return h;
11
+ }
12
+ /**
13
+ * GET /api/workspace/{workspaceId} — the API returns an array of workspaces
14
+ * (the front uses `[0]`). Returns the first element or null.
15
+ */
16
+ export async function getWorkspaceById(opts, signal) {
17
+ const url = `${getBaseUrl(opts.zone, opts.dev)}/api/workspace/${encodeURIComponent(opts.workspaceId)}`;
18
+ const res = await fetch(url, { method: 'GET', headers: headers(opts), signal });
19
+ if (!res.ok) {
20
+ throw new Error(`GET workspace ${res.status} ${res.statusText}`);
21
+ }
22
+ const json = (await res.json());
23
+ if (!json)
24
+ return null;
25
+ if (Array.isArray(json))
26
+ return json[0] ?? null;
27
+ return json;
28
+ }
29
+ /**
30
+ * POST /api/workspace/{workspaceId}/integrations/{integrationId}/activate
31
+ * Body: { isActive: true, platformCode: "whatsapp" }
32
+ */
33
+ export async function activateIntegration(opts, integrationId, signal) {
34
+ const url = `${getBaseUrl(opts.zone, opts.dev)}/api/workspace/${encodeURIComponent(opts.workspaceId)}/integrations/${encodeURIComponent(integrationId)}/activate`;
35
+ const res = await fetch(url, {
36
+ method: 'POST',
37
+ headers: headers(opts),
38
+ body: JSON.stringify({ isActive: true, platformCode: 'whatsapp' }),
39
+ signal,
40
+ });
41
+ const text = await res.text();
42
+ let parsed = {};
43
+ if (text) {
44
+ try {
45
+ parsed = JSON.parse(text);
46
+ }
47
+ catch { /* not json */ }
48
+ }
49
+ if (!res.ok) {
50
+ return { success: false, message: parsed.message || `HTTP ${res.status} ${res.statusText}` };
51
+ }
52
+ return parsed.success === false ? parsed : { success: true, ...parsed };
53
+ }
54
+ /** Adapter: derives the workspace fetch options from a StudioStreamOptions. */
55
+ export function workspaceOptsFromStream(stream) {
56
+ return {
57
+ apiKey: stream.apiKey,
58
+ workspaceId: stream.workspaceId,
59
+ zone: stream.zone,
60
+ dev: stream.dev,
61
+ userId: stream.userId,
62
+ };
63
+ }
@@ -0,0 +1,77 @@
1
+ import { activateIntegration, getWorkspaceById } from './api.js';
2
+ import { findNewWhatsappIntegration, WA_POLL_INTERVAL_MS, WA_POLL_MAX_ATTEMPTS, } from './types.js';
3
+ /**
4
+ * Starts the polling loop. Returns a handle to cancel it. The loop:
5
+ * 1. GETs the workspace every WA_POLL_INTERVAL_MS up to WA_POLL_MAX_ATTEMPTS.
6
+ * 2. Looks for a whatsapp integration whose id isn't in `existingIntegrationIds`.
7
+ * 3. When found, calls POST .../activate and reports the result.
8
+ */
9
+ export function startWhatsappPolling(opts, linkData, cb) {
10
+ const knownIds = new Set(linkData.existingIntegrationIds ?? []);
11
+ const controller = new AbortController();
12
+ let attempts = 0;
13
+ let busy = false;
14
+ let stopped = false;
15
+ let timer = null;
16
+ const stop = () => {
17
+ stopped = true;
18
+ if (timer) {
19
+ clearInterval(timer);
20
+ timer = null;
21
+ }
22
+ controller.abort();
23
+ };
24
+ const tick = async () => {
25
+ if (busy || stopped)
26
+ return;
27
+ busy = true;
28
+ attempts++;
29
+ cb.onAttempt(attempts);
30
+ try {
31
+ const ws = await getWorkspaceById(opts, controller.signal);
32
+ const newIntegration = findNewWhatsappIntegration(ws?.integrations, knownIds);
33
+ if (newIntegration?.id) {
34
+ const number = newIntegration.cellphoneNumberFormat ||
35
+ newIntegration.cellphoneNumber ||
36
+ '';
37
+ cb.onActivating(newIntegration.id, number);
38
+ if (timer) {
39
+ clearInterval(timer);
40
+ timer = null;
41
+ }
42
+ const res = await activateIntegration(opts, newIntegration.id, controller.signal);
43
+ if (res.success !== false) {
44
+ cb.onConnected(number);
45
+ }
46
+ else {
47
+ cb.onError(res.message || 'Could not activate the integration.');
48
+ }
49
+ stopped = true;
50
+ return;
51
+ }
52
+ }
53
+ catch (err) {
54
+ if (err.name === 'AbortError')
55
+ return;
56
+ // Transient network errors: swallow and keep polling.
57
+ }
58
+ finally {
59
+ busy = false;
60
+ }
61
+ if (attempts >= WA_POLL_MAX_ATTEMPTS) {
62
+ if (timer) {
63
+ clearInterval(timer);
64
+ timer = null;
65
+ }
66
+ stopped = true;
67
+ cb.onTimeout();
68
+ }
69
+ };
70
+ timer = setInterval(() => { void tick(); }, WA_POLL_INTERVAL_MS);
71
+ // Trigger the first attempt immediately so the user sees activity right away.
72
+ void tick();
73
+ return {
74
+ cancel() { stop(); },
75
+ get stopped() { return stopped; },
76
+ };
77
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Types and helpers for the "connect WhatsApp from Agent Studio" flow.
3
+ *
4
+ * The backend tool `connect_whatsapp` emits a `tool_result` chunk with
5
+ * `type: "whatsapp_link"`. When `data.shortUrl` is present we render an
6
+ * inline card with the onboarding link and start polling the workspace
7
+ * until the new integration appears. Baseline of "known" ids comes from
8
+ * the server (`existingIntegrationIds`) to avoid race conditions.
9
+ *
10
+ * Mirror of /Plazbot-Front-v2.0/src/modules/agentStudio/whatsappConnect.ts
11
+ */
12
+ export const WA_POLL_INTERVAL_MS = 5000;
13
+ export const WA_POLL_MAX_ATTEMPTS = 60; // 5 minutes
14
+ /**
15
+ * Returns a new whatsapp integration whose id is NOT in the baseline.
16
+ * If multiple are new, picks the most recently created one.
17
+ */
18
+ export function findNewWhatsappIntegration(integrations, knownIds) {
19
+ if (!integrations?.length)
20
+ return null;
21
+ const candidates = integrations.filter((i) => (i.type === 'whatsapp' || i.type === 'whatsapp_business') &&
22
+ !!i.id &&
23
+ !knownIds.has(i.id));
24
+ if (!candidates.length)
25
+ return null;
26
+ return candidates.reduce((latest, current) => {
27
+ const a = latest.creationDate ? new Date(latest.creationDate).getTime() : 0;
28
+ const b = current.creationDate ? new Date(current.creationDate).getTime() : 0;
29
+ return b > a ? current : latest;
30
+ });
31
+ }
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -0,0 +1,46 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Resuelve un error proveniente del SDK/axios al cargar un agente y devuelve
4
+ * un mensaje legible que oriente al usuario sobre la causa real (404 = ID o
5
+ * workspace/zona incorrectos, 401 = token expirado, etc.).
6
+ */
7
+ export function describeAgentLoadError(error, agentId, credentials, context = {}) {
8
+ const err = error;
9
+ const status = err?.response?.status;
10
+ const workspace = context.workspaceOverride || credentials.workspace;
11
+ const zone = context.zoneOverride || credentials.zone;
12
+ const envHint = context.dev ? ' (env: --dev / localhost:5090)' : '';
13
+ if (status === 404) {
14
+ return [
15
+ `Agent "${agentId}" was not found in workspace ${workspace} (zone ${zone})${envHint}.`,
16
+ chalk.gray(' Verify the ID and active workspace:'),
17
+ chalk.gray(' plazbot status'),
18
+ chalk.gray(' plazbot agent list'),
19
+ chalk.gray(' If the agent lives in a different zone, re-init with the right one:'),
20
+ chalk.gray(' plazbot init -z LA # or EU'),
21
+ ].join('\n');
22
+ }
23
+ if (status === 401) {
24
+ return [
25
+ 'Authentication token rejected (401).',
26
+ chalk.gray(' Re-run: plazbot init -k <jwt> -w <workspace> -z LA|EU'),
27
+ ].join('\n');
28
+ }
29
+ if (status === 403) {
30
+ return [
31
+ `No permissions to access agent "${agentId}" in workspace ${workspace}.`,
32
+ chalk.gray(' Confirm your user has access to that workspace.'),
33
+ ].join('\n');
34
+ }
35
+ if (status === 429) {
36
+ return 'Rate limit reached. Try again in a few seconds.';
37
+ }
38
+ if (typeof status === 'number' && status >= 500) {
39
+ return [
40
+ `Backend error (HTTP ${status})${envHint}.`,
41
+ chalk.gray(` ${err.response?.data?.message || err.message || ''}`).trimEnd(),
42
+ ].join('\n');
43
+ }
44
+ const fallback = err?.response?.data?.message || err?.message || 'Unknown error';
45
+ return fallback;
46
+ }
package/dist/utils/api.js CHANGED
@@ -1,25 +1,24 @@
1
- "use strict";
2
1
  // Utilidades para llamadas directas al API de Plazbot
3
2
  // Usado por comandos que no tienen clase SDK (ej: workers)
4
- var __importDefault = (this && this.__importDefault) || function (mod) {
5
- return (mod && mod.__esModule) ? mod : { "default": mod };
6
- };
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.createApiClient = createApiClient;
9
- const axios_1 = __importDefault(require("axios"));
3
+ import axios from 'axios';
10
4
  function getBaseUrl(zone, dev) {
11
5
  if (dev)
12
6
  return 'http://localhost:5090';
13
7
  return zone === 'EU' ? 'https://apieu.plazbot.com' : 'https://api.plazbot.com';
14
8
  }
15
- function createApiClient(options) {
9
+ export function createApiClient(options) {
16
10
  const baseURL = getBaseUrl(options.zone, options.dev);
17
- return axios_1.default.create({
11
+ return axios.create({
18
12
  baseURL,
19
13
  headers: {
20
14
  'Content-Type': 'application/json',
15
+ // El apiKey almacenado en el CLI ya es un JWT válido. El backend espera
16
+ // Authorization: Bearer en endpoints nuevos (ej. /api/agent/studio).
17
+ // x-api-key se mantiene transitorio para no romper endpoints legacy.
18
+ 'Authorization': `Bearer ${options.apiKey}`,
21
19
  'x-api-key': options.apiKey,
22
20
  'x-workspace-id': options.workspace,
23
21
  },
24
22
  });
25
23
  }
24
+ export { getBaseUrl };
@@ -1,13 +1,11 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.showBanner = showBanner;
7
- exports.showMiniHeader = showMiniHeader;
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const credentials_1 = require("./credentials");
10
- const { version: VERSION } = require('../../package.json');
1
+ import chalk from 'chalk';
2
+ import { readFileSync } from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { dirname, join } from 'node:path';
5
+ import { getStoredCredentials } from './credentials.js';
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const pkgPath = join(__dirname, '..', '..', 'package.json');
8
+ const { version: VERSION } = JSON.parse(readFileSync(pkgPath, 'utf-8'));
11
9
  // ASCII art del logo Plazbot (burbujas de chat)
12
10
  const logo = [
13
11
  ' ╭──────────╮ ',
@@ -19,51 +17,52 @@ const logo = [
19
17
  ' │ ╰────╯ │ ',
20
18
  ' ╰───────────────╯ ',
21
19
  ];
22
- const coloredLogo = logo.map(line => chalk_1.default.hex('#2E8B57')(line));
23
- async function showBanner() {
20
+ const coloredLogo = logo.map(line => chalk.hex('#2E8B57')(line));
21
+ export async function showBanner() {
24
22
  const width = 70;
25
23
  // Intentar cargar credenciales
26
24
  let credentials = null;
27
25
  try {
28
- credentials = await (0, credentials_1.getStoredCredentials)();
26
+ credentials = await getStoredCredentials();
29
27
  }
30
28
  catch {
31
29
  // No hay credenciales guardadas
32
30
  }
33
31
  console.log();
34
- console.log(chalk_1.default.hex('#4CAF50')('─'.repeat(width)));
32
+ console.log(chalk.hex('#4CAF50')('─'.repeat(width)));
35
33
  console.log();
36
34
  // Layout de 2 columnas
37
35
  const leftWidth = 30;
38
36
  const rightStart = leftWidth + 4;
39
37
  // Línea del título
40
- const title = chalk_1.default.bold.hex('#4CAF50')(` Plazbot CLI v${VERSION}`);
38
+ const title = chalk.bold.hex('#4CAF50')(` Plazbot CLI v${VERSION}`);
41
39
  // Info columna derecha
42
40
  const rightColumn = [];
43
41
  if (credentials) {
44
- rightColumn.push(chalk_1.default.bold.hex('#4CAF50')('Workspace conectado'));
45
- rightColumn.push(chalk_1.default.gray(` ${credentials.workspace || 'N/A'}`));
46
- rightColumn.push(chalk_1.default.gray(` ${credentials.email || ''}`));
47
- rightColumn.push(chalk_1.default.gray(` Zona: ${credentials.zone || 'N/A'}`));
42
+ rightColumn.push(chalk.bold.hex('#4CAF50')('Connected workspace'));
43
+ rightColumn.push(chalk.gray(` ${credentials.workspace || 'N/A'}`));
44
+ if (credentials.email)
45
+ rightColumn.push(chalk.gray(` ${credentials.email}`));
46
+ rightColumn.push(chalk.gray(` Zone: ${credentials.zone || 'N/A'}`));
48
47
  rightColumn.push('');
49
- rightColumn.push(chalk_1.default.hex('#4CAF50')('─'.repeat(35)));
48
+ rightColumn.push(chalk.hex('#4CAF50')('─'.repeat(35)));
50
49
  rightColumn.push('');
51
- rightColumn.push(chalk_1.default.bold.hex('#4CAF50')('Comandos rapidos'));
52
- rightColumn.push(chalk_1.default.white(' plazbot agent list'));
53
- rightColumn.push(chalk_1.default.white(' plazbot agent create'));
54
- rightColumn.push(chalk_1.default.white(' plazbot agent chat -a <id>'));
55
- rightColumn.push(chalk_1.default.white(' plazbot whatsapp send-message'));
50
+ rightColumn.push(chalk.bold.hex('#4CAF50')('Quick commands'));
51
+ rightColumn.push(chalk.white(' plazbot agent list'));
52
+ rightColumn.push(chalk.white(' plazbot agent create'));
53
+ rightColumn.push(chalk.white(' plazbot agent chat -a <id>'));
54
+ rightColumn.push(chalk.white(' plazbot whatsapp send-message'));
56
55
  }
57
56
  else {
58
- rightColumn.push(chalk_1.default.bold.hex('#FFA726')('No conectado'));
57
+ rightColumn.push(chalk.bold.hex('#FFA726')('Not connected'));
59
58
  rightColumn.push('');
60
- rightColumn.push(chalk_1.default.bold.hex('#4CAF50')('Para comenzar'));
61
- rightColumn.push(chalk_1.default.white(' plazbot init -e <email> -k <key> -w <workspace> -z <zone>'));
59
+ rightColumn.push(chalk.bold.hex('#4CAF50')('To get started'));
60
+ rightColumn.push(chalk.white(' plazbot init -e <email> -k <key> -w <workspace> -z <zone>'));
62
61
  rightColumn.push('');
63
- rightColumn.push(chalk_1.default.hex('#4CAF50')('─'.repeat(35)));
62
+ rightColumn.push(chalk.hex('#4CAF50')('─'.repeat(35)));
64
63
  rightColumn.push('');
65
- rightColumn.push(chalk_1.default.bold.hex('#4CAF50')('Documentacion'));
66
- rightColumn.push(chalk_1.default.gray(' https://docs.plazbot.com'));
64
+ rightColumn.push(chalk.bold.hex('#4CAF50')('Documentation'));
65
+ rightColumn.push(chalk.gray(' https://docs.plazbot.com'));
67
66
  }
68
67
  // Imprimir título
69
68
  console.log(title);
@@ -79,9 +78,9 @@ async function showBanner() {
79
78
  console.log(`${left}${padding} ${right}`);
80
79
  }
81
80
  console.log();
82
- console.log(chalk_1.default.hex('#4CAF50')('─'.repeat(width)));
81
+ console.log(chalk.hex('#4CAF50')('─'.repeat(width)));
83
82
  console.log();
84
83
  }
85
- function showMiniHeader(command) {
86
- console.log(chalk_1.default.hex('#4CAF50')(`\n Plazbot`) + chalk_1.default.gray(` > ${command}\n`));
84
+ export function showMiniHeader(command) {
85
+ console.log(chalk.hex('#4CAF50')(`\n Plazbot`) + chalk.gray(` > ${command}\n`));
87
86
  }
@@ -1,19 +1,11 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getStoredCredentials = getStoredCredentials;
7
- exports.saveCredentials = saveCredentials;
8
- exports.removeCredentials = removeCredentials;
9
- const promises_1 = __importDefault(require("fs/promises"));
10
- const path_1 = __importDefault(require("path"));
11
- const os_1 = __importDefault(require("os"));
12
- const configDir = path_1.default.join(os_1.default.homedir(), '.plazbot');
13
- const configPath = path_1.default.join(configDir, 'config.json');
14
- async function getStoredCredentials() {
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ const configDir = path.join(os.homedir(), '.plazbot');
5
+ const configPath = path.join(configDir, 'config.json');
6
+ export async function getStoredCredentials() {
15
7
  try {
16
- const configRaw = await promises_1.default.readFile(configPath, 'utf-8');
8
+ const configRaw = await fs.readFile(configPath, 'utf-8');
17
9
  const config = JSON.parse(configRaw);
18
10
  if (!config.apiKey || !config.workspace || !config.zone) {
19
11
  throw new Error('Credenciales incompletas');
@@ -24,10 +16,10 @@ async function getStoredCredentials() {
24
16
  throw new Error("No se encontró una sesión activa. Ejecuta 'plazbot init' primero.");
25
17
  }
26
18
  }
27
- async function saveCredentials(credentials) {
28
- await promises_1.default.mkdir(configDir, { recursive: true });
29
- await promises_1.default.writeFile(configPath, JSON.stringify(credentials, null, 2));
19
+ export async function saveCredentials(credentials) {
20
+ await fs.mkdir(configDir, { recursive: true });
21
+ await fs.writeFile(configPath, JSON.stringify(credentials, null, 2));
30
22
  }
31
- async function removeCredentials() {
32
- await promises_1.default.rm(configPath, { force: true });
23
+ export async function removeCredentials() {
24
+ await fs.rm(configPath, { force: true });
33
25
  }
@@ -0,0 +1,44 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Appends a colored "Examples" section to a Commander command's --help output.
4
+ *
5
+ * Usage:
6
+ * addExamples(myCommand, [
7
+ * { description: 'List all agents in the current workspace', command: 'plazbot agent list' },
8
+ * { description: 'List as JSON for scripting', command: 'plazbot agent list --json' },
9
+ * ]);
10
+ *
11
+ * Renders as:
12
+ * Examples:
13
+ * # List all agents in the current workspace
14
+ * $ plazbot agent list
15
+ *
16
+ * # List as JSON for scripting
17
+ * $ plazbot agent list --json
18
+ */
19
+ export function addExamples(cmd, examples) {
20
+ if (!examples.length)
21
+ return cmd;
22
+ const lines = ['', chalk.bold('Examples:')];
23
+ for (const ex of examples) {
24
+ lines.push(' ' + chalk.gray('# ' + ex.description));
25
+ lines.push(' ' + chalk.cyan('$ ') + ex.command);
26
+ lines.push('');
27
+ }
28
+ cmd.addHelpText('after', lines.join('\n'));
29
+ return cmd;
30
+ }
31
+ /**
32
+ * Appends a "Notes" section after Examples. Use for caveats, links, or
33
+ * prerequisites the user should know before running the command.
34
+ */
35
+ export function addNotes(cmd, notes) {
36
+ if (!notes.length)
37
+ return cmd;
38
+ const lines = ['', chalk.bold('Notes:')];
39
+ for (const n of notes)
40
+ lines.push(' ' + chalk.gray('• ') + n);
41
+ lines.push('');
42
+ cmd.addHelpText('after', lines.join('\n'));
43
+ return cmd;
44
+ }
@@ -1,45 +1,39 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.logger = void 0;
7
- const chalk_1 = __importDefault(require("chalk"));
8
- exports.logger = {
1
+ import chalk from 'chalk';
2
+ export const logger = {
9
3
  info: (message) => {
10
- console.log(chalk_1.default.white(message));
4
+ console.log(chalk.white(message));
11
5
  },
12
6
  success: (message) => {
13
- console.log(chalk_1.default.hex('#66BB6A')(`\n ${message}`));
7
+ console.log(chalk.hex('#66BB6A')(`\n ${message}`));
14
8
  },
15
9
  warning: (message) => {
16
- console.log(chalk_1.default.hex('#FFA726')(`\n ${message}`));
10
+ console.log(chalk.hex('#FFA726')(`\n ${message}`));
17
11
  },
18
12
  error: (error) => {
19
13
  const message = error instanceof Error ? error.message : error;
20
- console.error(chalk_1.default.hex('#EF5350')(`\n Error: ${message}`));
14
+ console.error(chalk.hex('#EF5350')(`\n Error: ${message}`));
21
15
  },
22
16
  divider: (length = 50) => {
23
- console.log(chalk_1.default.gray('─'.repeat(length)));
17
+ console.log(chalk.gray('─'.repeat(length)));
24
18
  },
25
19
  doubleDivider: (length = 50) => {
26
- console.log(chalk_1.default.gray('═'.repeat(length)));
20
+ console.log(chalk.gray('═'.repeat(length)));
27
21
  },
28
22
  label: (key, value) => {
29
- console.log(` ${chalk_1.default.gray(key + ':')} ${chalk_1.default.white(value)}`);
23
+ console.log(` ${chalk.gray(key + ':')} ${chalk.white(value)}`);
30
24
  },
31
25
  title: (text) => {
32
- console.log(chalk_1.default.bold.hex('#4CAF50')(`\n ${text}`));
33
- console.log(chalk_1.default.gray(' ' + '─'.repeat(40)));
26
+ console.log(chalk.bold.hex('#4CAF50')(`\n ${text}`));
27
+ console.log(chalk.gray(' ' + '─'.repeat(40)));
34
28
  },
35
29
  dim: (message) => {
36
- console.log(chalk_1.default.gray(` ${message}`));
30
+ console.log(chalk.gray(` ${message}`));
37
31
  },
38
32
  json: (data) => {
39
33
  const formatted = JSON.stringify(data, null, 2)
40
34
  .split('\n')
41
35
  .map(line => ' ' + line)
42
36
  .join('\n');
43
- console.log(chalk_1.default.gray(formatted));
37
+ console.log(chalk.gray(formatted));
44
38
  }
45
39
  };