plazbot-cli 0.3.7 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +38 -2
  2. package/dist/commands/auth/browser-login.js +121 -0
  3. package/dist/commands/auth/index.js +5 -1
  4. package/dist/commands/auth/login.js +1 -3
  5. package/dist/commands/auth/logout.js +4 -3
  6. package/dist/commands/auth/status.js +8 -5
  7. package/dist/commands/auth/workspace.js +73 -0
  8. package/dist/commands/whatsapp/connect-flow.js +137 -0
  9. package/dist/commands/whatsapp/connect.js +26 -160
  10. package/dist/commands/whatsapp/index.js +4 -0
  11. package/dist/commands/whatsapp/setup.js +242 -0
  12. package/dist/studio/components/App.js +1 -1
  13. package/dist/studio/runOneShot.js +2 -2
  14. package/dist/studio/runRepl.js +1 -1
  15. package/dist/utils/agent-errors.js +2 -2
  16. package/dist/utils/banner.js +10 -9
  17. package/dist/utils/credentials.js +31 -3
  18. package/dist/utils/open-browser.js +17 -0
  19. package/package.json +14 -6
  20. package/.claude/settings.local.json +0 -19
  21. package/CLAUDE.md +0 -121
  22. package/agent.config.json +0 -21
  23. package/dist/studio/components/AgentPanel.js +0 -35
  24. package/dist/studio/render/json.js +0 -16
  25. package/dist/studio/whatsapp/api.js +0 -63
  26. package/dist/studio/whatsapp/polling.js +0 -77
  27. package/dist/studio/whatsapp/types.js +0 -31
  28. package/src/cli.ts +0 -57
  29. package/src/commands/agent/ai-config.ts +0 -164
  30. package/src/commands/agent/chat.ts +0 -225
  31. package/src/commands/agent/copy.ts +0 -46
  32. package/src/commands/agent/create.ts +0 -103
  33. package/src/commands/agent/delete.ts +0 -71
  34. package/src/commands/agent/enable-widget.ts +0 -67
  35. package/src/commands/agent/export.ts +0 -430
  36. package/src/commands/agent/files.ts +0 -171
  37. package/src/commands/agent/get.ts +0 -233
  38. package/src/commands/agent/index.ts +0 -55
  39. package/src/commands/agent/list.ts +0 -58
  40. package/src/commands/agent/monitor.ts +0 -375
  41. package/src/commands/agent/on-message.ts +0 -82
  42. package/src/commands/agent/set.ts +0 -149
  43. package/src/commands/agent/templates.ts +0 -892
  44. package/src/commands/agent/tools.ts +0 -168
  45. package/src/commands/agent/update.ts +0 -61
  46. package/src/commands/agent/validate.ts +0 -135
  47. package/src/commands/agent/wizard.ts +0 -756
  48. package/src/commands/auth/index.ts +0 -10
  49. package/src/commands/auth/login.ts +0 -72
  50. package/src/commands/auth/logout.ts +0 -28
  51. package/src/commands/auth/status.ts +0 -28
  52. package/src/commands/portal/add-agent.ts +0 -66
  53. package/src/commands/portal/add-link.ts +0 -47
  54. package/src/commands/portal/clear-links.ts +0 -33
  55. package/src/commands/portal/create.ts +0 -58
  56. package/src/commands/portal/delete.ts +0 -70
  57. package/src/commands/portal/get.ts +0 -77
  58. package/src/commands/portal/index.ts +0 -32
  59. package/src/commands/portal/list.ts +0 -79
  60. package/src/commands/portal/update.ts +0 -93
  61. package/src/commands/whatsapp/broadcast.ts +0 -110
  62. package/src/commands/whatsapp/channels.ts +0 -109
  63. package/src/commands/whatsapp/chat.ts +0 -85
  64. package/src/commands/whatsapp/connect.ts +0 -220
  65. package/src/commands/whatsapp/delete-webhook.ts +0 -43
  66. package/src/commands/whatsapp/index.ts +0 -37
  67. package/src/commands/whatsapp/register-webhook.ts +0 -47
  68. package/src/commands/whatsapp/send-template.ts +0 -94
  69. package/src/commands/whatsapp/send.ts +0 -55
  70. package/src/commands/whatsapp/widget.ts +0 -75
  71. package/src/commands/workers/deploy.ts +0 -156
  72. package/src/commands/workers/index.ts +0 -30
  73. package/src/commands/workers/list.ts +0 -105
  74. package/src/commands/workers/logs.ts +0 -99
  75. package/src/commands/workers/remove.ts +0 -103
  76. package/src/commands/workers/secret.ts +0 -191
  77. package/src/commands/workers/test.ts +0 -145
  78. package/src/schemas/agent.config.schema.json +0 -569
  79. package/src/studio/api/sseClient.ts +0 -91
  80. package/src/studio/api/studioApi.ts +0 -27
  81. package/src/studio/api/types.ts +0 -96
  82. package/src/studio/components/App.tsx +0 -274
  83. package/src/studio/components/ChatLog.tsx +0 -121
  84. package/src/studio/components/ConnectCard.tsx +0 -171
  85. package/src/studio/components/Footer.tsx +0 -38
  86. package/src/studio/components/Header.tsx +0 -39
  87. package/src/studio/components/Input.tsx +0 -176
  88. package/src/studio/components/Message.tsx +0 -87
  89. package/src/studio/components/Suggestions.tsx +0 -26
  90. package/src/studio/components/ToolCall.tsx +0 -58
  91. package/src/studio/connect/api.ts +0 -98
  92. package/src/studio/connect/polling.ts +0 -94
  93. package/src/studio/connect/types.ts +0 -141
  94. package/src/studio/index.ts +0 -58
  95. package/src/studio/render/markdown.ts +0 -93
  96. package/src/studio/render/steps.ts +0 -57
  97. package/src/studio/runOneShot.ts +0 -114
  98. package/src/studio/runRepl.tsx +0 -82
  99. package/src/studio/slash/handlers.ts +0 -226
  100. package/src/studio/slash/parser.ts +0 -41
  101. package/src/studio/slash/registry.ts +0 -54
  102. package/src/studio/state/store.ts +0 -279
  103. package/src/types/agent.ts +0 -63
  104. package/src/types/auth.ts +0 -9
  105. package/src/types/common.ts +0 -10
  106. package/src/types/message.ts +0 -34
  107. package/src/types/portal.ts +0 -56
  108. package/src/types/workers.ts +0 -86
  109. package/src/utils/agent-errors.ts +0 -67
  110. package/src/utils/api.ts +0 -35
  111. package/src/utils/banner.ts +0 -99
  112. package/src/utils/credentials.ts +0 -38
  113. package/src/utils/help.ts +0 -51
  114. package/src/utils/logger.ts +0 -40
  115. package/src/utils/ui.ts +0 -109
  116. package/tsconfig.json +0 -18
@@ -1,34 +0,0 @@
1
- export interface MessageCommandOptions {
2
- dev?: boolean;
3
- to?: string;
4
- message?: string;
5
- phone?: string;
6
- template?: string;
7
- }
8
-
9
- export interface DirectMessageCommandOptions {
10
- dev?: boolean;
11
- to: string;
12
- message: string;
13
- }
14
-
15
- export interface TemplateCommandOptions {
16
- dev?: boolean;
17
- phone: string;
18
- template: string;
19
- }
20
-
21
- export interface WhatsappMessageParams {
22
- message: string;
23
- to: string;
24
- }
25
-
26
- export interface ConversationTemplateParams {
27
- to: string;
28
- template: string;
29
- }
30
-
31
- export interface WebhookParams {
32
- number: string;
33
- webhookUrl: string;
34
- }
@@ -1,56 +0,0 @@
1
- import { BaseCommandOptions } from './common.js';
2
-
3
- export interface PortalCommandOptions extends BaseCommandOptions {
4
- portalId?: string;
5
- name?: string;
6
- title?: string;
7
- subtitle?: string;
8
- logo?: string;
9
- logoDark?: string;
10
- access?: "direct" | "form";
11
- disabled?: string;
12
- brandOff?: string;
13
- zone?: "LA" | "EU";
14
- dev?: boolean;
15
- force?: boolean;
16
- }
17
-
18
- export interface AddAgentToPortalOptions extends BaseCommandOptions {
19
- portalId: string;
20
- agentId: string;
21
- }
22
-
23
- export interface AddLinkToPortalOptions extends BaseCommandOptions {
24
- portalId: string;
25
- text: string;
26
- url: string;
27
- }
28
-
29
- export interface PortalLink {
30
- value: string;
31
- url: string;
32
- }
33
-
34
- export interface PortalAgent {
35
- id: string;
36
- name: string;
37
- }
38
-
39
- export interface Portal {
40
- id: string;
41
- name: string;
42
- url: string;
43
- access: string;
44
- disabled: boolean;
45
- title?: string;
46
- subtitle?: string;
47
- logo?: string;
48
- logodark?: string;
49
- links?: PortalLink[];
50
- agents?: PortalAgent[];
51
- }
52
-
53
- export interface PortalResponse {
54
- success: boolean;
55
- portal: Portal;
56
- }
@@ -1,86 +0,0 @@
1
- import { BaseCommandOptions } from './common.js';
2
-
3
- // ── Opciones de comandos ────────────────────────────────────────────────────
4
-
5
- export interface WorkerDeployOptions extends BaseCommandOptions {
6
- file?: string;
7
- name?: string;
8
- description?: string;
9
- }
10
-
11
- export interface WorkerListOptions extends BaseCommandOptions {
12
- type?: string;
13
- status?: string;
14
- }
15
-
16
- export interface WorkerLogsOptions extends BaseCommandOptions {
17
- name: string;
18
- limit?: number;
19
- status?: string;
20
- }
21
-
22
- export interface WorkerRemoveOptions extends BaseCommandOptions {
23
- force?: boolean;
24
- }
25
-
26
- export interface WorkerSecretSetOptions extends BaseCommandOptions {
27
- key: string;
28
- value: string;
29
- }
30
-
31
- export interface WorkerSecretListOptions extends BaseCommandOptions {}
32
-
33
- export interface WorkerSecretRemoveOptions extends BaseCommandOptions {
34
- force?: boolean;
35
- }
36
-
37
- export interface WorkerTestOptions extends BaseCommandOptions {
38
- file: string;
39
- event?: string;
40
- input?: string;
41
- }
42
-
43
- // ── Respuestas del API ──────────────────────────────────────────────────────
44
-
45
- export interface WorkerListItem {
46
- id: string;
47
- name: string;
48
- type: 'tool' | 'worker' | 'sync' | 'schedule' | 'webhook';
49
- status: 'active' | 'inactive' | 'error';
50
- description?: string;
51
- cronExpression?: string;
52
- webhookUrl?: string;
53
- executionCount: number;
54
- errorCount: number;
55
- avgDurationMs: number;
56
- lastExecutedAt?: string;
57
- lastError?: string;
58
- createdAt: string;
59
- updatedAt: string;
60
- }
61
-
62
- export interface WorkerLogItem {
63
- id: string;
64
- workerName: string;
65
- workerType: string;
66
- status: 'success' | 'error' | 'timeout';
67
- durationMs: number;
68
- error?: string;
69
- triggerSource?: string;
70
- createdAt: string;
71
- }
72
-
73
- export interface WorkerSecretItem {
74
- key: string;
75
- createdAt: string;
76
- updatedAt: string;
77
- }
78
-
79
- export interface WorkerDeployResult {
80
- id: string;
81
- name: string;
82
- type: string;
83
- status: string;
84
- webhookUrl?: string;
85
- cronExpression?: string;
86
- }
@@ -1,67 +0,0 @@
1
- import chalk from 'chalk';
2
- import type { StoredCredentials } from './credentials.js';
3
-
4
- interface AxiosLikeError {
5
- response?: {
6
- status?: number;
7
- data?: { message?: string };
8
- };
9
- message?: string;
10
- }
11
-
12
- /**
13
- * Resuelve un error proveniente del SDK/axios al cargar un agente y devuelve
14
- * un mensaje legible que oriente al usuario sobre la causa real (404 = ID o
15
- * workspace/zona incorrectos, 401 = token expirado, etc.).
16
- */
17
- export function describeAgentLoadError(
18
- error: unknown,
19
- agentId: string,
20
- credentials: Pick<StoredCredentials, 'workspace' | 'zone'>,
21
- context: { dev?: boolean; workspaceOverride?: string; zoneOverride?: string } = {}
22
- ): string {
23
- const err = error as AxiosLikeError;
24
- const status = err?.response?.status;
25
- const workspace = context.workspaceOverride || credentials.workspace;
26
- const zone = context.zoneOverride || credentials.zone;
27
- const envHint = context.dev ? ' (env: --dev / localhost:5090)' : '';
28
-
29
- if (status === 404) {
30
- return [
31
- `Agent "${agentId}" was not found in workspace ${workspace} (zone ${zone})${envHint}.`,
32
- chalk.gray(' Verify the ID and active workspace:'),
33
- chalk.gray(' plazbot status'),
34
- chalk.gray(' plazbot agent list'),
35
- chalk.gray(' If the agent lives in a different zone, re-init with the right one:'),
36
- chalk.gray(' plazbot init -z LA # or EU'),
37
- ].join('\n');
38
- }
39
-
40
- if (status === 401) {
41
- return [
42
- 'Authentication token rejected (401).',
43
- chalk.gray(' Re-run: plazbot init -k <jwt> -w <workspace> -z LA|EU'),
44
- ].join('\n');
45
- }
46
-
47
- if (status === 403) {
48
- return [
49
- `No permissions to access agent "${agentId}" in workspace ${workspace}.`,
50
- chalk.gray(' Confirm your user has access to that workspace.'),
51
- ].join('\n');
52
- }
53
-
54
- if (status === 429) {
55
- return 'Rate limit reached. Try again in a few seconds.';
56
- }
57
-
58
- if (typeof status === 'number' && status >= 500) {
59
- return [
60
- `Backend error (HTTP ${status})${envHint}.`,
61
- chalk.gray(` ${err.response?.data?.message || err.message || ''}`).trimEnd(),
62
- ].join('\n');
63
- }
64
-
65
- const fallback = err?.response?.data?.message || err?.message || 'Unknown error';
66
- return fallback;
67
- }
package/src/utils/api.ts DELETED
@@ -1,35 +0,0 @@
1
- // Utilidades para llamadas directas al API de Plazbot
2
- // Usado por comandos que no tienen clase SDK (ej: workers)
3
-
4
- import axios, { AxiosInstance } from 'axios';
5
-
6
- interface ApiClientOptions {
7
- apiKey: string;
8
- workspace: string;
9
- zone: 'LA' | 'EU';
10
- dev?: boolean;
11
- }
12
-
13
- function getBaseUrl(zone: string, dev?: boolean): string {
14
- if (dev) return 'http://localhost:5090';
15
- return zone === 'EU' ? 'https://apieu.plazbot.com' : 'https://api.plazbot.com';
16
- }
17
-
18
- export function createApiClient(options: ApiClientOptions): AxiosInstance {
19
- const baseURL = getBaseUrl(options.zone, options.dev);
20
-
21
- return axios.create({
22
- baseURL,
23
- headers: {
24
- 'Content-Type': 'application/json',
25
- // El apiKey almacenado en el CLI ya es un JWT válido. El backend espera
26
- // Authorization: Bearer en endpoints nuevos (ej. /api/agent/studio).
27
- // x-api-key se mantiene transitorio para no romper endpoints legacy.
28
- 'Authorization': `Bearer ${options.apiKey}`,
29
- 'x-api-key': options.apiKey,
30
- 'x-workspace-id': options.workspace,
31
- },
32
- });
33
- }
34
-
35
- export { getBaseUrl };
@@ -1,99 +0,0 @@
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
-
7
- const __dirname = dirname(fileURLToPath(import.meta.url));
8
- const pkgPath = join(__dirname, '..', '..', 'package.json');
9
- const { version: VERSION } = JSON.parse(readFileSync(pkgPath, 'utf-8'));
10
-
11
- // ASCII art del logo Plazbot (burbujas de chat)
12
- const logo = [
13
- ' ╭──────────╮ ',
14
- ' │ ● ● ● │ ',
15
- ' ╰────┬─────╯ ',
16
- ' ╭─────┴────────╮ ',
17
- ' │ ╭─╮ ╭─╮ │ ',
18
- ' │ ╰─╯ ╰─╯ │ ',
19
- ' │ ╰────╯ │ ',
20
- ' ╰───────────────╯ ',
21
- ];
22
-
23
- const coloredLogo = logo.map(line =>
24
- chalk.hex('#2E8B57')(line)
25
- );
26
-
27
- export async function showBanner(): Promise<void> {
28
- const width = 70;
29
-
30
- // Intentar cargar credenciales
31
- let credentials: { email?: string; workspace?: string; zone?: string } | null = null;
32
- try {
33
- credentials = await getStoredCredentials();
34
- } catch {
35
- // No hay credenciales guardadas
36
- }
37
-
38
- console.log();
39
- console.log(chalk.hex('#4CAF50')('─'.repeat(width)));
40
- console.log();
41
-
42
- // Layout de 2 columnas
43
- const leftWidth = 30;
44
- const rightStart = leftWidth + 4;
45
-
46
- // Línea del título
47
- const title = chalk.bold.hex('#4CAF50')(` Plazbot CLI v${VERSION}`);
48
-
49
- // Info columna derecha
50
- const rightColumn: string[] = [];
51
-
52
- if (credentials) {
53
- rightColumn.push(chalk.bold.hex('#4CAF50')('Connected workspace'));
54
- rightColumn.push(chalk.gray(` ${credentials.workspace || 'N/A'}`));
55
- if (credentials.email) rightColumn.push(chalk.gray(` ${credentials.email}`));
56
- rightColumn.push(chalk.gray(` Zone: ${credentials.zone || 'N/A'}`));
57
- rightColumn.push('');
58
- rightColumn.push(chalk.hex('#4CAF50')('─'.repeat(35)));
59
- rightColumn.push('');
60
- rightColumn.push(chalk.bold.hex('#4CAF50')('Quick commands'));
61
- rightColumn.push(chalk.white(' plazbot agent list'));
62
- rightColumn.push(chalk.white(' plazbot agent create'));
63
- rightColumn.push(chalk.white(' plazbot agent chat -a <id>'));
64
- rightColumn.push(chalk.white(' plazbot whatsapp send-message'));
65
- } else {
66
- rightColumn.push(chalk.bold.hex('#FFA726')('Not connected'));
67
- rightColumn.push('');
68
- rightColumn.push(chalk.bold.hex('#4CAF50')('To get started'));
69
- rightColumn.push(chalk.white(' plazbot init -e <email> -k <key> -w <workspace> -z <zone>'));
70
- rightColumn.push('');
71
- rightColumn.push(chalk.hex('#4CAF50')('─'.repeat(35)));
72
- rightColumn.push('');
73
- rightColumn.push(chalk.bold.hex('#4CAF50')('Documentation'));
74
- rightColumn.push(chalk.gray(' https://docs.plazbot.com'));
75
- }
76
-
77
- // Imprimir título
78
- console.log(title);
79
- console.log();
80
-
81
- // Imprimir logo + info lado a lado
82
- const maxLines = Math.max(coloredLogo.length, rightColumn.length);
83
- for (let i = 0; i < maxLines; i++) {
84
- const left = i < coloredLogo.length ? coloredLogo[i] : ' '.repeat(leftWidth);
85
- const right = i < rightColumn.length ? rightColumn[i] : '';
86
- // Pad left column
87
- const paddedLeft = left.replace(/\x1b\[[0-9;]*m/g, '');
88
- const padding = ' '.repeat(Math.max(0, leftWidth - paddedLeft.length));
89
- console.log(`${left}${padding} ${right}`);
90
- }
91
-
92
- console.log();
93
- console.log(chalk.hex('#4CAF50')('─'.repeat(width)));
94
- console.log();
95
- }
96
-
97
- export function showMiniHeader(command: string): void {
98
- console.log(chalk.hex('#4CAF50')(`\n Plazbot`) + chalk.gray(` > ${command}\n`));
99
- }
@@ -1,38 +0,0 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
- import os from 'os';
4
-
5
- const configDir = path.join(os.homedir(), '.plazbot');
6
- const configPath = path.join(configDir, 'config.json');
7
-
8
- export interface StoredCredentials {
9
- email?: string;
10
- apiKey: string;
11
- workspace: string;
12
- zone: "LA" | "EU";
13
- userId?: string;
14
- }
15
-
16
- export async function getStoredCredentials(): Promise<StoredCredentials> {
17
- try {
18
- const configRaw = await fs.readFile(configPath, 'utf-8');
19
- const config = JSON.parse(configRaw);
20
-
21
- if (!config.apiKey || !config.workspace || !config.zone) {
22
- throw new Error('Credenciales incompletas');
23
- }
24
-
25
- return config;
26
- } catch (error) {
27
- throw new Error("No se encontró una sesión activa. Ejecuta 'plazbot init' primero.");
28
- }
29
- }
30
-
31
- export async function saveCredentials(credentials: StoredCredentials): Promise<void> {
32
- await fs.mkdir(configDir, { recursive: true });
33
- await fs.writeFile(configPath, JSON.stringify(credentials, null, 2));
34
- }
35
-
36
- export async function removeCredentials(): Promise<void> {
37
- await fs.rm(configPath, { force: true });
38
- }
package/src/utils/help.ts DELETED
@@ -1,51 +0,0 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
-
4
- export interface HelpExample {
5
- /** Brief description of what the example does. */
6
- description: string;
7
- /** The command line to run (without the `$ ` prefix). */
8
- command: string;
9
- }
10
-
11
- /**
12
- * Appends a colored "Examples" section to a Commander command's --help output.
13
- *
14
- * Usage:
15
- * addExamples(myCommand, [
16
- * { description: 'List all agents in the current workspace', command: 'plazbot agent list' },
17
- * { description: 'List as JSON for scripting', command: 'plazbot agent list --json' },
18
- * ]);
19
- *
20
- * Renders as:
21
- * Examples:
22
- * # List all agents in the current workspace
23
- * $ plazbot agent list
24
- *
25
- * # List as JSON for scripting
26
- * $ plazbot agent list --json
27
- */
28
- export function addExamples(cmd: Command, examples: HelpExample[]): Command {
29
- if (!examples.length) return cmd;
30
- const lines: string[] = ['', chalk.bold('Examples:')];
31
- for (const ex of examples) {
32
- lines.push(' ' + chalk.gray('# ' + ex.description));
33
- lines.push(' ' + chalk.cyan('$ ') + ex.command);
34
- lines.push('');
35
- }
36
- cmd.addHelpText('after', lines.join('\n'));
37
- return cmd;
38
- }
39
-
40
- /**
41
- * Appends a "Notes" section after Examples. Use for caveats, links, or
42
- * prerequisites the user should know before running the command.
43
- */
44
- export function addNotes(cmd: Command, notes: string[]): Command {
45
- if (!notes.length) return cmd;
46
- const lines: string[] = ['', chalk.bold('Notes:')];
47
- for (const n of notes) lines.push(' ' + chalk.gray('• ') + n);
48
- lines.push('');
49
- cmd.addHelpText('after', lines.join('\n'));
50
- return cmd;
51
- }
@@ -1,40 +0,0 @@
1
- import chalk from 'chalk';
2
-
3
- export const logger = {
4
- info: (message: string) => {
5
- console.log(chalk.white(message));
6
- },
7
- success: (message: string) => {
8
- console.log(chalk.hex('#66BB6A')(`\n ${message}`));
9
- },
10
- warning: (message: string) => {
11
- console.log(chalk.hex('#FFA726')(`\n ${message}`));
12
- },
13
- error: (error: Error | string) => {
14
- const message = error instanceof Error ? error.message : error;
15
- console.error(chalk.hex('#EF5350')(`\n Error: ${message}`));
16
- },
17
- divider: (length: number = 50) => {
18
- console.log(chalk.gray('─'.repeat(length)));
19
- },
20
- doubleDivider: (length: number = 50) => {
21
- console.log(chalk.gray('═'.repeat(length)));
22
- },
23
- label: (key: string, value: string) => {
24
- console.log(` ${chalk.gray(key + ':')} ${chalk.white(value)}`);
25
- },
26
- title: (text: string) => {
27
- console.log(chalk.bold.hex('#4CAF50')(`\n ${text}`));
28
- console.log(chalk.gray(' ' + '─'.repeat(40)));
29
- },
30
- dim: (message: string) => {
31
- console.log(chalk.gray(` ${message}`));
32
- },
33
- json: (data: any) => {
34
- const formatted = JSON.stringify(data, null, 2)
35
- .split('\n')
36
- .map(line => ' ' + line)
37
- .join('\n');
38
- console.log(chalk.gray(formatted));
39
- }
40
- };
package/src/utils/ui.ts DELETED
@@ -1,109 +0,0 @@
1
- import chalk from 'chalk';
2
- import ora, { Ora } from 'ora';
3
- import Table from 'cli-table3';
4
-
5
- // Colores del tema Plazbot
6
- export const theme = {
7
- primary: chalk.hex('#4CAF50'),
8
- secondary: chalk.hex('#2196F3'),
9
- accent: chalk.hex('#FFA726'),
10
- success: chalk.hex('#66BB6A'),
11
- error: chalk.hex('#EF5350'),
12
- warning: chalk.hex('#FFA726'),
13
- muted: chalk.gray,
14
- bold: chalk.bold,
15
- dim: chalk.dim,
16
- };
17
-
18
- // Spinner
19
- export function createSpinner(text: string): Ora {
20
- return ora({
21
- text: theme.muted(text),
22
- spinner: 'dots',
23
- color: 'green',
24
- });
25
- }
26
-
27
- // Tabla formateada
28
- export function createTable(headers: string[], rows: string[][]): string {
29
- const table = new Table({
30
- head: headers.map(h => theme.bold.hex('#4CAF50')(h)),
31
- style: {
32
- head: [],
33
- border: ['gray'],
34
- },
35
- chars: {
36
- 'top': '─', 'top-mid': '┬', 'top-left': '┌', 'top-right': '┐',
37
- 'bottom': '─', 'bottom-mid': '┴', 'bottom-left': '└', 'bottom-right': '┘',
38
- 'left': '│', 'left-mid': '├', 'mid': '─', 'mid-mid': '┼',
39
- 'right': '│', 'right-mid': '┤', 'middle': '│'
40
- }
41
- });
42
- rows.forEach(row => table.push(row));
43
- return table.toString();
44
- }
45
-
46
- // Box simple
47
- export function box(content: string, title?: string): string {
48
- const lines = content.split('\n');
49
- const maxLen = Math.max(...lines.map(l => stripAnsi(l).length), title ? stripAnsi(title).length + 4 : 0);
50
- const width = maxLen + 4;
51
-
52
- let result = '';
53
- if (title) {
54
- result += theme.muted(' ┌─ ') + theme.primary(title) + theme.muted(' ' + '─'.repeat(Math.max(0, width - stripAnsi(title).length - 5))) + theme.muted('┐') + '\n';
55
- } else {
56
- result += theme.muted(' ┌' + '─'.repeat(width) + '┐') + '\n';
57
- }
58
-
59
- for (const line of lines) {
60
- const pad = ' '.repeat(Math.max(0, maxLen - stripAnsi(line).length));
61
- result += theme.muted(' │') + ' ' + line + pad + ' ' + theme.muted('│') + '\n';
62
- }
63
-
64
- result += theme.muted(' └' + '─'.repeat(width) + '┘');
65
- return result;
66
- }
67
-
68
- // Strip ANSI codes para calcular longitud real
69
- function stripAnsi(str: string): string {
70
- return str.replace(/\x1b\[[0-9;]*m/g, '');
71
- }
72
-
73
- // Formato de fecha legible
74
- export function formatDate(date: string | Date): string {
75
- const d = new Date(date);
76
- return d.toLocaleDateString('es-ES', {
77
- year: 'numeric',
78
- month: 'short',
79
- day: 'numeric',
80
- hour: '2-digit',
81
- minute: '2-digit'
82
- });
83
- }
84
-
85
- // Status badge
86
- export function statusBadge(enabled: boolean): string {
87
- return enabled
88
- ? theme.success('● activo')
89
- : theme.error('○ inactivo');
90
- }
91
-
92
- // Key-value pair formateado
93
- export function kvPair(key: string, value: string): string {
94
- return ` ${theme.muted(key + ':')} ${value}`;
95
- }
96
-
97
- // Sección con título
98
- export function section(title: string): string {
99
- return '\n' + theme.bold.hex('#4CAF50')(` ${title}`) + '\n' + theme.muted(' ' + '─'.repeat(40));
100
- }
101
-
102
- // Progress bar simple
103
- export function progressBar(current: number, total: number, width: number = 30): string {
104
- const percent = Math.round((current / total) * 100);
105
- const filled = Math.round((current / total) * width);
106
- const empty = width - filled;
107
- const bar = theme.success('█'.repeat(filled)) + theme.muted('░'.repeat(empty));
108
- return `${bar} ${theme.bold(percent + '%')} (${current}/${total})`;
109
- }
package/tsconfig.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "jsx": "react-jsx",
7
- "outDir": "./dist",
8
- "rootDir": "./src",
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "resolveJsonModule": true,
13
- "isolatedModules": true,
14
- "forceConsistentCasingInFileNames": true
15
- },
16
- "include": ["src/**/*"],
17
- "exclude": ["node_modules", "**/*.spec.ts", "dist"]
18
- }