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.
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 +86 -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 +22 -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 +93 -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
package/CLAUDE.md CHANGED
@@ -7,8 +7,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
7
7
  Plazbot CLI v2.0 es una interfaz de línea de comandos oficial para la plataforma Plazbot. Permite gestionar agentes de IA, portales web y comunicaciones vía WhatsApp desde la terminal.
8
8
 
9
9
  - **Lenguaje**: TypeScript 5.0+
10
- - **Runtime**: Node.js >=16.0.0
10
+ - **Runtime**: Node.js >=18.17.0 (ESM)
11
11
  - **Framework CLI**: Commander.js
12
+ - **TUI**: Ink v5 + React 18 + zustand (solo para `plazbot studio`)
12
13
 
13
14
  ## Comandos de Desarrollo
14
15
 
@@ -47,13 +48,37 @@ src/
47
48
  │ ├── agent/ # CRUD + chat interactivo de agentes
48
49
  │ ├── auth/ # init (login) y logout
49
50
  │ ├── portal/ # CRUD + gestión de enlaces
50
- └── whatsapp/ # Mensajes y webhooks
51
+ ├── whatsapp/ # Mensajes y webhooks
52
+ │ └── workers/ # Tools, syncs, schedules, webhooks
53
+ ├── studio/ # REPL interactivo (Ink + SSE)
54
+ │ ├── index.ts # studioCommand + subcomando ask
55
+ │ ├── runRepl.tsx # Bootstrap Ink render(<App/>)
56
+ │ ├── runOneShot.ts # Modo no interactivo (stdout)
57
+ │ ├── api/ # types, studioApi, sseClient (fetch + ReadableStream)
58
+ │ ├── state/store.ts # zustand: messages, steps, agentConfig, usage
59
+ │ ├── slash/ # parser, registry, handlers (/help, /clear, /agents…)
60
+ │ ├── render/ # markdown (marked-terminal), steps, json
61
+ │ └── components/ # App, Header, ChatLog, Message, ToolCall, Input…
51
62
  ├── types/ # Interfaces TypeScript
52
63
  └── utils/
53
64
  ├── logger.ts # Logging formateado (info, success, warning, error)
65
+ ├── api.ts # axios con Authorization Bearer + x-workspace-id
54
66
  └── credentials.ts # Persistencia en ~/.plazbot/config.json
55
67
  ```
56
68
 
69
+ ### Studio (REPL interactivo)
70
+
71
+ `plazbot studio` abre una TUI estilo Claude Code que consume el endpoint SSE
72
+ `POST /api/agent/studio`. Permite crear, cargar, diagnosticar y guardar agentes
73
+ en conversación natural. Las tool_calls se renderizan como cards con spinner;
74
+ el `agentConfig` aparece en un panel lateral con tabs preview/json/diagnose.
75
+
76
+ - `plazbot studio` → REPL completo (Ink)
77
+ - `plazbot studio -m "..."` o `plazbot studio ask "..."` → one-shot a stdout
78
+ - `plazbot studio ask "..." --json` → NDJSON crudo de los chunks SSE
79
+
80
+ Atajos: `Tab` panel · `Esc` cancelar stream · `Ctrl+C` salir.
81
+
57
82
  ### Flujo de Comandos
58
83
 
59
84
  1. `cli.ts` usa Commander.js para registrar grupos de comandos
@@ -74,13 +99,17 @@ El CLI depende del paquete `plazbot` que expone tres clases principales:
74
99
  Se almacenan en `~/.plazbot/config.json`:
75
100
  ```json
76
101
  {
77
- "email": "string",
78
- "apiKey": "string",
102
+ "email": "string (opcional)",
103
+ "apiKey": "string (JWT)",
79
104
  "workspace": "string",
80
- "zone": "LA | EU"
105
+ "zone": "LA | EU",
106
+ "userId": "string (opcional, usado por studio como x-user-id)"
81
107
  }
82
108
  ```
83
109
 
110
+ El `apiKey` es un JWT válido. El CLI lo envía como `Authorization: Bearer <jwt>`
111
+ y mantiene transitoriamente `x-api-key` para endpoints legacy.
112
+
84
113
  ### Flag --dev
85
114
 
86
115
  Todos los comandos soportan `--dev` para apuntar al backend local (`http://localhost:5090`).
package/README.md CHANGED
@@ -4,6 +4,27 @@ Official Command Line Interface for Plazbot - Manage your AI agents and portals
4
4
 
5
5
  ## Features
6
6
 
7
+ 🧠 **Agent Studio (REPL interactivo, estilo Claude Code)**
8
+ ```bash
9
+ # Modo REPL completo (TUI con Ink)
10
+ plazbot studio
11
+
12
+ # One-shot (resultado a stdout, sin TUI)
13
+ plazbot studio ask "lista mis agentes"
14
+ plazbot studio -m "crea un agente de ventas para WhatsApp"
15
+
16
+ # NDJSON crudo de los chunks SSE
17
+ plazbot studio ask "diagnostica el agente xyz" --json
18
+
19
+ # Backend local
20
+ plazbot studio --dev
21
+ ```
22
+
23
+ Slash commands: `/help`, `/clear`, `/quit`, `/agents`, `/load <id>`, `/save`,
24
+ `/diagnose`, `/panel`, `/json`, `/preview`.
25
+
26
+ Atajos: `Tab` panel · `Esc` cancelar stream · `Ctrl+C` salir.
27
+
7
28
  🤖 **Agent Management**
8
29
  ```bash
9
30
  # Create a new agent
package/dist/cli.js CHANGED
@@ -1,36 +1,48 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- const commander_1 = require("commander");
5
- const portal_1 = require("./commands/portal");
6
- const auth_1 = require("./commands/auth");
7
- const agent_1 = require("./commands/agent");
8
- const whatsapp_1 = require("./commands/whatsapp");
9
- const workers_1 = require("./commands/workers");
10
- const banner_1 = require("./utils/banner");
2
+ import { program } from 'commander';
3
+ import { readFileSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { dirname, join } from 'node:path';
6
+ import { portalCommands } from './commands/portal/index.js';
7
+ import { authCommands } from './commands/auth/index.js';
8
+ import { agentCommands } from './commands/agent/index.js';
9
+ import { whatsappCommands } from './commands/whatsapp/index.js';
10
+ import { workersCommands } from './commands/workers/index.js';
11
+ import { studioCommand } from './studio/index.js';
12
+ import { showBanner } from './utils/banner.js';
13
+ // Guard de runtime: Plazbot CLI v0.3+ requiere Node 18.17+
14
+ const [major, minor] = process.versions.node.split('.').map(Number);
15
+ if (major < 18 || (major === 18 && minor < 17)) {
16
+ console.error(`Plazbot CLI v0.3+ requires Node.js >=18.17.0. Current version: ${process.versions.node}`);
17
+ process.exit(1);
18
+ }
11
19
  // Leer version desde package.json
12
- const { version } = require('../package.json');
20
+ const __dirname = dirname(fileURLToPath(import.meta.url));
21
+ const pkgPath = join(__dirname, '..', 'package.json');
22
+ const { version } = JSON.parse(readFileSync(pkgPath, 'utf-8'));
13
23
  // Configuracion basica del CLI
14
- commander_1.program
24
+ program
15
25
  .name('plazbot')
16
- .description('CLI oficial de Plazbot - Agentes de IA para WhatsApp, portales y desarrolladores')
26
+ .description('Official Plazbot CLI - AI agents for WhatsApp, portals and developers')
17
27
  .version(version);
18
28
  // Registrar todos los comandos de autenticacion
19
- auth_1.authCommands.forEach(cmd => commander_1.program.addCommand(cmd));
29
+ authCommands.forEach(cmd => program.addCommand(cmd));
20
30
  // Registrar todos los comandos de agente
21
- commander_1.program.addCommand(agent_1.agentCommands);
31
+ program.addCommand(agentCommands);
22
32
  // Registrar todos los comandos de portal
23
- commander_1.program.addCommand(portal_1.portalCommands);
33
+ program.addCommand(portalCommands);
24
34
  // Registrar todos los comandos de WhatsApp
25
- commander_1.program.addCommand(whatsapp_1.whatsappCommands);
35
+ program.addCommand(whatsappCommands);
26
36
  // Registrar todos los comandos de Workers
27
- commander_1.program.addCommand(workers_1.workersCommands);
37
+ program.addCommand(workersCommands);
38
+ // Registrar el comando Studio (REPL interactivo)
39
+ program.addCommand(studioCommand);
28
40
  // Si no se pasan argumentos, mostrar banner
29
41
  if (process.argv.length <= 2) {
30
- (0, banner_1.showBanner)().then(() => {
31
- commander_1.program.outputHelp();
42
+ showBanner().then(() => {
43
+ program.outputHelp();
32
44
  });
33
45
  }
34
46
  else {
35
- commander_1.program.parse(process.argv);
47
+ program.parse(process.argv);
36
48
  }
@@ -1,82 +1,126 @@
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.aiConfigCommand = void 0;
7
- const commander_1 = require("commander");
8
- const plazbot_1 = require("plazbot");
9
- const inquirer_1 = __importDefault(require("inquirer"));
10
- const credentials_1 = require("../../utils/credentials");
11
- const logger_1 = require("../../utils/logger");
12
- const ui_1 = require("../../utils/ui");
1
+ import { Command } from 'commander';
2
+ import { Agent } from 'plazbot';
3
+ import inquirer from 'inquirer';
4
+ import { getStoredCredentials } from '../../utils/credentials.js';
5
+ import { logger } from '../../utils/logger.js';
6
+ import { addExamples } from '../../utils/help.js';
7
+ import { describeAgentLoadError } from '../../utils/agent-errors.js';
8
+ import { createSpinner, theme, section, kvPair } from '../../utils/ui.js';
9
+ // Catalogo de modelos sincronizado con el front (AIModelSection.tsx).
10
+ // Si se actualiza el dropdown del front, actualizar aqui tambien.
13
11
  const MODELS = {
14
- openai: ['gpt-4o', 'gpt-4', 'gpt-3.5-turbo', 'o1-preview', 'o1-mini'],
15
- claude: ['claude-3-5-sonnet-20241022', 'claude-3-opus-20240229', 'claude-3-haiku-20240307'],
16
- gemini: ['gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash'],
12
+ openai: [
13
+ // GPT-5.4 (flagship actual)
14
+ 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.4-nano',
15
+ // GPT-5.2
16
+ 'gpt-5.2',
17
+ // GPT-5.1
18
+ 'gpt-5.1', 'gpt-5.1-codex', 'gpt-5.1-codex-mini',
19
+ // GPT-5
20
+ 'gpt-5', 'gpt-5-mini', 'gpt-5-nano',
21
+ // GPT-4.1
22
+ 'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano',
23
+ // GPT-4o
24
+ 'gpt-4o', 'gpt-4o-mini',
25
+ // Razonamiento (o-series)
26
+ 'o4-mini', 'o3', 'o3-mini', 'o1-2024-12-17',
27
+ // Legacy
28
+ 'gpt-4-turbo', 'gpt-3.5-turbo',
29
+ ],
30
+ claude: [
31
+ // Mythos-class (flagship)
32
+ 'claude-fable-5',
33
+ // Claude 4.6
34
+ 'claude-opus-4-6', 'claude-sonnet-4-6',
35
+ // Claude 4.5
36
+ 'claude-opus-4-5-20251101', 'claude-sonnet-4-5-20250929', 'claude-haiku-4-5-20251001',
37
+ // Claude 4.x
38
+ 'claude-opus-4-1-20250805', 'claude-opus-4-20250514', 'claude-sonnet-4-20250514',
39
+ ],
40
+ gemini: [
41
+ // Gemini 3.1 (flagship actual)
42
+ 'gemini-3.1-pro-preview', 'gemini-3.1-flash-lite-preview',
43
+ // Gemini 2.5
44
+ 'gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.5-flash-lite',
45
+ // Gemini 2.0
46
+ 'gemini-2.0-flash',
47
+ ],
48
+ };
49
+ const DEFAULT_MODEL = {
50
+ openai: 'gpt-4o',
51
+ claude: 'claude-sonnet-4-6',
52
+ gemini: 'gemini-2.5-pro',
17
53
  };
18
- exports.aiConfigCommand = new commander_1.Command('ai-config')
19
- .description('Configurar proveedor de IA del agente')
20
- .argument('<agentId>', 'ID del agente')
21
- .option('--dev', 'Usar ambiente de desarrollo', false)
54
+ export const aiConfigCommand = new Command('ai-config')
55
+ .description('Configure the agent AI provider')
56
+ .argument('<agentId>', 'Agent ID')
57
+ .option('--dev', 'Use development environment', false)
22
58
  .action(async (agentId, options) => {
23
59
  try {
24
- const credentials = await (0, credentials_1.getStoredCredentials)();
25
- const agent = new plazbot_1.Agent({
60
+ const credentials = await getStoredCredentials();
61
+ const agent = new Agent({
26
62
  workspaceId: credentials.workspace,
27
63
  apiKey: credentials.apiKey,
28
64
  zone: credentials.zone,
29
65
  ...(options.dev && { customUrl: "http://localhost:5090" })
30
66
  });
31
- const spinner = (0, ui_1.createSpinner)('Cargando agente...');
67
+ const spinner = createSpinner('Loading agent...');
32
68
  spinner.start();
33
- const _res = await agent.getAgentById({ id: agentId });
34
- const agentData = _res.agent || _res.data || _res;
35
- spinner.stop();
36
- console.log((0, ui_1.section)('Configuracion de IA - ' + (agentData.name || agentId)));
69
+ let agentData;
70
+ try {
71
+ const _res = await agent.getAgentById({ id: agentId });
72
+ agentData = _res.agent || _res.data || _res;
73
+ spinner.stop();
74
+ }
75
+ catch (loadErr) {
76
+ spinner.stop();
77
+ logger.error(describeAgentLoadError(loadErr, agentId, credentials, { dev: options.dev }));
78
+ process.exit(1);
79
+ }
80
+ console.log(section('AI Configuration - ' + (agentData.name || agentId)));
37
81
  const currentProviders = agentData.aiProviders || [];
38
82
  if (currentProviders.length > 0 && agentData.customAIConfig) {
39
- console.log(ui_1.theme.bold('\n Configuracion actual:'));
83
+ console.log(theme.bold('\n Current configuration:'));
40
84
  currentProviders.forEach((p) => {
41
- console.log((0, ui_1.kvPair)(' Proveedor', p.provider));
42
- console.log((0, ui_1.kvPair)(' Modelo', p.model));
43
- console.log((0, ui_1.kvPair)(' Temperatura', String(p.temperature)));
44
- console.log((0, ui_1.kvPair)(' Max Tokens', String(p.maxTokens)));
45
- console.log((0, ui_1.kvPair)(' Default', p.isDefault ? 'Si' : 'No'));
85
+ console.log(kvPair(' Provider', p.provider));
86
+ console.log(kvPair(' Model', p.model));
87
+ console.log(kvPair(' Temperature', String(p.temperature)));
88
+ console.log(kvPair(' Max Tokens', String(p.maxTokens)));
89
+ console.log(kvPair(' Default', p.isDefault ? 'Yes' : 'No'));
46
90
  });
47
91
  }
48
92
  else {
49
- console.log(ui_1.theme.muted('\n Usando configuracion de IA por defecto (Plazbot)'));
93
+ console.log(theme.muted('\n Using default AI configuration (Plazbot)'));
50
94
  }
51
- const { action } = await inquirer_1.default.prompt([{
95
+ const { action } = await inquirer.prompt([{
52
96
  type: 'list',
53
97
  name: 'action',
54
- message: 'Que deseas hacer?',
98
+ message: 'What would you like to do?',
55
99
  choices: [
56
- { name: 'Configurar nuevo proveedor', value: 'set' },
57
- { name: 'Usar configuracion por defecto', value: 'reset' },
58
- { name: 'Salir', value: 'exit' },
100
+ { name: 'Configure new provider', value: 'set' },
101
+ { name: 'Use default configuration', value: 'reset' },
102
+ { name: 'Exit', value: 'exit' },
59
103
  ],
60
104
  }]);
61
105
  if (action === 'exit')
62
106
  return;
63
107
  if (action === 'reset') {
64
108
  const { id, _id, ...resetConfig } = { ...agentData, customAIConfig: false, aiProviders: [] };
65
- const resetSpinner = (0, ui_1.createSpinner)('Reseteando configuracion...');
109
+ const resetSpinner = createSpinner('Resetting configuration...');
66
110
  resetSpinner.start();
67
111
  await agent.updateAgent(agentId, resetConfig);
68
- resetSpinner.succeed('Usando configuracion por defecto');
112
+ resetSpinner.succeed('Using default configuration');
69
113
  return;
70
114
  }
71
115
  // Configurar nuevo proveedor
72
- const ai = await inquirer_1.default.prompt([
73
- { type: 'list', name: 'provider', message: 'Proveedor:', choices: ['openai', 'claude', 'gemini'] },
116
+ const ai = await inquirer.prompt([
117
+ { type: 'list', name: 'provider', message: 'Provider:', choices: ['openai', 'claude', 'gemini'] },
74
118
  ]);
75
119
  const models = MODELS[ai.provider] || MODELS.openai;
76
- const config = await inquirer_1.default.prompt([
77
- { type: 'list', name: 'model', message: 'Modelo:', choices: models },
78
- { type: 'password', name: 'apiToken', message: 'API Token:', mask: '*', validate: (v) => v.length > 0 || 'Requerido' },
79
- { type: 'number', name: 'temperature', message: 'Temperatura (0-2):', default: 0.7 },
120
+ const config = await inquirer.prompt([
121
+ { type: 'list', name: 'model', message: 'Model:', choices: models, default: DEFAULT_MODEL[ai.provider] },
122
+ { type: 'password', name: 'apiToken', message: 'API Token:', mask: '*', validate: (v) => v.length > 0 || 'Required' },
123
+ { type: 'number', name: 'temperature', message: 'Temperature (0-2):', default: 0.7 },
80
124
  { type: 'number', name: 'maxTokens', message: 'Max tokens (1024-16384):', default: 4096 },
81
125
  ]);
82
126
  const { id: _uid, _id: _oid, ...updatedConfig } = {
@@ -91,14 +135,18 @@ exports.aiConfigCommand = new commander_1.Command('ai-config')
91
135
  isDefault: true,
92
136
  }],
93
137
  };
94
- const updateSpinner = (0, ui_1.createSpinner)('Guardando configuracion...');
138
+ const updateSpinner = createSpinner('Saving configuration...');
95
139
  updateSpinner.start();
96
140
  await agent.updateAgent(agentId, updatedConfig);
97
- updateSpinner.succeed(`Proveedor configurado: ${ai.provider} / ${config.model}`);
141
+ updateSpinner.succeed(`Provider configured: ${ai.provider} / ${config.model}`);
98
142
  }
99
143
  catch (error) {
100
- const message = error instanceof Error ? error.message : 'Error desconocido';
101
- logger_1.logger.error(message);
144
+ const message = error instanceof Error ? error.message : 'Unknown error';
145
+ logger.error(message);
102
146
  process.exit(1);
103
147
  }
104
148
  });
149
+ addExamples(aiConfigCommand, [
150
+ { description: 'Pick provider/model/API key for the agent interactively',
151
+ command: 'plazbot agent ai-config agt_AbcDef123' },
152
+ ]);
@@ -1,84 +1,82 @@
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.chatCommand = void 0;
7
- const commander_1 = require("commander");
8
- const plazbot_1 = require("plazbot");
9
- const credentials_1 = require("../../utils/credentials");
10
- const logger_1 = require("../../utils/logger");
11
- const ui_1 = require("../../utils/ui");
12
- const crypto_1 = __importDefault(require("crypto"));
13
- const readline_1 = __importDefault(require("readline"));
14
- const chalk_1 = __importDefault(require("chalk"));
1
+ import { Command } from 'commander';
2
+ import { Agent } from 'plazbot';
3
+ import { getStoredCredentials } from '../../utils/credentials.js';
4
+ import { logger } from '../../utils/logger.js';
5
+ import { addExamples } from '../../utils/help.js';
6
+ import { describeAgentLoadError } from '../../utils/agent-errors.js';
7
+ import { section } from '../../utils/ui.js';
8
+ import crypto from 'crypto';
9
+ import readline from 'readline';
10
+ import chalk from 'chalk';
15
11
  const COMMANDS_HELP = `
16
- ${chalk_1.default.bold('Comandos disponibles:')}
17
- ${chalk_1.default.hex('#4CAF50')('/exit')} Terminar conversacion
18
- ${chalk_1.default.hex('#4CAF50')('/clear')} Limpiar pantalla
19
- ${chalk_1.default.hex('#4CAF50')('/info')} Informacion de la sesion
20
- ${chalk_1.default.hex('#4CAF50')('/sources')} Mostrar/ocultar fuentes
21
- ${chalk_1.default.hex('#4CAF50')('/help')} Mostrar estos comandos
12
+ ${chalk.bold('Available commands:')}
13
+ ${chalk.hex('#4CAF50')('/exit')} End conversation
14
+ ${chalk.hex('#4CAF50')('/clear')} Clear screen
15
+ ${chalk.hex('#4CAF50')('/info')} Session information
16
+ ${chalk.hex('#4CAF50')('/sources')} Toggle sources
17
+ ${chalk.hex('#4CAF50')('/help')} Show these commands
22
18
  `;
23
- exports.chatCommand = new commander_1.Command('chat')
24
- .description('Inicia una sesion de chat interactiva con un agente')
25
- .requiredOption('-a, --agent-id <id>', 'ID del agente')
26
- .option('-s, --session-id <id>', 'ID de sesion (opcional)')
27
- .option('-m, --multiple-answers', 'Permitir multiples respuestas', false)
28
- .option('--dev', 'Usar ambiente de desarrollo', false)
29
- .action(async (options) => {
19
+ export const chatCommand = new Command('chat')
20
+ .description('Start an interactive chat session with an agent')
21
+ .argument('<agentId>', 'Agent ID')
22
+ .option('-s, --session-id <id>', 'Session ID (optional)')
23
+ .option('-m, --multiple-answers', 'Allow multiple answers', false)
24
+ .option('--dev', 'Use development environment', false)
25
+ .action(async (agentId, options) => {
30
26
  try {
31
- const credentials = await (0, credentials_1.getStoredCredentials)();
32
- const agent = new plazbot_1.Agent({
27
+ const credentials = await getStoredCredentials();
28
+ const agent = new Agent({
33
29
  workspaceId: credentials.workspace,
34
30
  apiKey: credentials.apiKey,
35
31
  zone: credentials.zone,
36
32
  ...(options.dev && { customUrl: "http://localhost:5090" })
37
33
  });
38
- const sessionId = options.sessionId || crypto_1.default.randomUUID();
34
+ const sessionId = options.sessionId || crypto.randomUUID();
39
35
  let showSources = true;
40
36
  // Cargar info del agente
41
37
  let agentInfo = null;
42
38
  try {
43
- process.stdout.write(chalk_1.default.gray(' Conectando con agente...'));
44
- const _res = await agent.getAgentById({ id: options.agentId });
39
+ process.stdout.write(chalk.gray(' Connecting to agent...'));
40
+ const _res = await agent.getAgentById({ id: agentId });
45
41
  agentInfo = _res.agent || _res.data || _res;
46
42
  process.stdout.write('\r' + ' '.repeat(40) + '\r');
47
43
  }
48
- catch {
44
+ catch (loadErr) {
49
45
  process.stdout.write('\r' + ' '.repeat(40) + '\r');
46
+ logger.error(describeAgentLoadError(loadErr, agentId, credentials, { dev: options.dev }));
47
+ process.exit(1);
50
48
  }
51
- const rl = readline_1.default.createInterface({
49
+ const rl = readline.createInterface({
52
50
  input: process.stdin,
53
51
  output: process.stdout
54
52
  });
55
53
  // Pantalla de chat
56
54
  console.clear();
57
- const agentName = agentInfo?.name || 'Agente';
58
- const toolCalling = agentInfo?.useToolCalling ? chalk_1.default.hex('#4CAF50')(' [Tool Calling]') : '';
55
+ const agentName = agentInfo?.name || 'Agent';
56
+ const toolCalling = agentInfo?.useToolCalling ? chalk.hex('#4CAF50')(' [Tool Calling]') : '';
59
57
  console.log();
60
- console.log(chalk_1.default.hex('#4CAF50')(' ┌' + '─'.repeat(58) + '┐'));
61
- console.log(chalk_1.default.hex('#4CAF50')(' │') + chalk_1.default.bold(` ${agentName}${toolCalling}`).padEnd(68) + chalk_1.default.hex('#4CAF50')('│'));
62
- console.log(chalk_1.default.hex('#4CAF50')(' │') + chalk_1.default.gray(` Session: ${sessionId.substring(0, 8)}...`).padEnd(68) + chalk_1.default.hex('#4CAF50')('│'));
63
- console.log(chalk_1.default.hex('#4CAF50')(' │') + chalk_1.default.gray(' /help para ver comandos').padEnd(68) + chalk_1.default.hex('#4CAF50')('│'));
64
- console.log(chalk_1.default.hex('#4CAF50')(' └' + '─'.repeat(58) + '┘'));
58
+ console.log(chalk.hex('#4CAF50')(' ┌' + '─'.repeat(58) + '┐'));
59
+ console.log(chalk.hex('#4CAF50')(' │') + chalk.bold(` ${agentName}${toolCalling}`).padEnd(68) + chalk.hex('#4CAF50')('│'));
60
+ console.log(chalk.hex('#4CAF50')(' │') + chalk.gray(` Session: ${sessionId.substring(0, 8)}...`).padEnd(68) + chalk.hex('#4CAF50')('│'));
61
+ console.log(chalk.hex('#4CAF50')(' │') + chalk.gray(' /help to see commands').padEnd(68) + chalk.hex('#4CAF50')('│'));
62
+ console.log(chalk.hex('#4CAF50')(' └' + '─'.repeat(58) + '┘'));
65
63
  console.log();
66
64
  // Saludo del agente
67
65
  if (agentInfo?.instructions?.greeting) {
68
- const timestamp = new Date().toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit' });
69
- console.log(chalk_1.default.hex('#4CAF50')(` ${agentName}`) + chalk_1.default.gray(` ${timestamp}`));
70
- console.log(chalk_1.default.white(` ${agentInfo.instructions.greeting}`));
66
+ const timestamp = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
67
+ console.log(chalk.hex('#4CAF50')(` ${agentName}`) + chalk.gray(` ${timestamp}`));
68
+ console.log(chalk.white(` ${agentInfo.instructions.greeting}`));
71
69
  console.log();
72
70
  }
73
71
  const askQuestion = () => {
74
- rl.question(chalk_1.default.hex('#2196F3')(' Tu > '), async (question) => {
72
+ rl.question(chalk.hex('#2196F3')(' You > '), async (question) => {
75
73
  if (!question.trim()) {
76
74
  askQuestion();
77
75
  return;
78
76
  }
79
77
  // Comandos especiales
80
78
  if (question.toLowerCase() === '/exit') {
81
- console.log(chalk_1.default.gray('\n Sesion terminada.\n'));
79
+ console.log(chalk.gray('\n Session ended.\n'));
82
80
  rl.close();
83
81
  return;
84
82
  }
@@ -93,60 +91,60 @@ exports.chatCommand = new commander_1.Command('chat')
93
91
  return;
94
92
  }
95
93
  if (question.toLowerCase() === '/info') {
96
- console.log((0, ui_1.section)('Informacion de sesion'));
97
- logger_1.logger.label('Agent ID', options.agentId);
98
- logger_1.logger.label('Session ID', sessionId);
99
- logger_1.logger.label('Agente', agentName);
100
- logger_1.logger.label('Tool Calling', agentInfo?.useToolCalling ? 'Activado' : 'Desactivado');
101
- logger_1.logger.label('AI Provider', agentInfo?.customAIConfig ? (agentInfo.aiProviders?.[0]?.provider || 'Custom') : 'Default');
94
+ console.log(section('Session information'));
95
+ logger.label('Agent ID', agentId);
96
+ logger.label('Session ID', sessionId);
97
+ logger.label('Agent', agentName);
98
+ logger.label('Tool Calling', agentInfo?.useToolCalling ? 'Enabled' : 'Disabled');
99
+ logger.label('AI Provider', agentInfo?.customAIConfig ? (agentInfo.aiProviders?.[0]?.provider || 'Custom') : 'Default');
102
100
  console.log();
103
101
  askQuestion();
104
102
  return;
105
103
  }
106
104
  if (question.toLowerCase() === '/sources') {
107
105
  showSources = !showSources;
108
- console.log(chalk_1.default.gray(` Fuentes: ${showSources ? 'activadas' : 'desactivadas'}`));
106
+ console.log(chalk.gray(` Sources: ${showSources ? 'on' : 'off'}`));
109
107
  console.log();
110
108
  askQuestion();
111
109
  return;
112
110
  }
113
111
  try {
114
- process.stdout.write(chalk_1.default.gray(' ...pensando\n'));
112
+ process.stdout.write(chalk.gray(' ...thinking\n'));
115
113
  const response = await agent.onMessage({
116
- agentId: options.agentId,
114
+ agentId: agentId,
117
115
  question,
118
116
  sessionId,
119
117
  multipleAnswers: options.multipleAnswers
120
118
  });
121
- const timestamp = new Date().toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit' });
119
+ const timestamp = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
122
120
  // Mostrar tool calls si hay
123
121
  if (response.actionsExecuted && response.actionsExecuted.length > 0) {
124
122
  response.actionsExecuted.forEach((action) => {
125
- console.log(chalk_1.default.hex('#FFA726')(` Tool: ${action.name || action.intent || 'action'}`));
123
+ console.log(chalk.hex('#FFA726')(` Tool: ${action.name || action.intent || 'action'}`));
126
124
  });
127
125
  }
128
126
  // Respuesta del agente
129
127
  console.log();
130
- console.log(chalk_1.default.hex('#4CAF50')(` ${agentName}`) + chalk_1.default.gray(` ${timestamp}`));
128
+ console.log(chalk.hex('#4CAF50')(` ${agentName}`) + chalk.gray(` ${timestamp}`));
131
129
  // Formatear respuesta (soporte basico de markdown)
132
130
  const formattedAnswer = formatResponse(response.answer);
133
131
  console.log(formattedAnswer);
134
132
  console.log();
135
133
  // Fuentes
136
134
  if (showSources && response.sources && response.sources.length > 0) {
137
- console.log(chalk_1.default.gray(' Fuentes:'));
135
+ console.log(chalk.gray(' Sources:'));
138
136
  response.sources.forEach((source) => {
139
- console.log(chalk_1.default.gray(` - ${source.title || 'Sin titulo'}`));
137
+ console.log(chalk.gray(` - ${source.title || 'Untitled'}`));
140
138
  if (source.url)
141
- console.log(chalk_1.default.gray(` ${source.url}`));
139
+ console.log(chalk.gray(` ${source.url}`));
142
140
  });
143
141
  console.log();
144
142
  }
145
143
  askQuestion();
146
144
  }
147
145
  catch (error) {
148
- const message = error instanceof Error ? error.message : 'Error desconocido';
149
- console.log(chalk_1.default.hex('#EF5350')(`\n ✖ Error: ${message}\n`));
146
+ const message = error instanceof Error ? error.message : 'Unknown error';
147
+ console.log(chalk.hex('#EF5350')(`\n ✖ Error: ${message}\n`));
150
148
  askQuestion();
151
149
  }
152
150
  });
@@ -154,36 +152,44 @@ exports.chatCommand = new commander_1.Command('chat')
154
152
  askQuestion();
155
153
  }
156
154
  catch (error) {
157
- const message = error instanceof Error ? error.message : 'Error desconocido';
158
- logger_1.logger.error(message);
155
+ const message = error instanceof Error ? error.message : 'Unknown error';
156
+ logger.error(message);
159
157
  process.exit(1);
160
158
  }
161
159
  });
160
+ addExamples(chatCommand, [
161
+ { description: 'Open an interactive chat with the agent',
162
+ command: 'plazbot agent chat agt_AbcDef123' },
163
+ { description: 'Reuse a previous session ID to continue the conversation',
164
+ command: 'plazbot agent chat agt_AbcDef123 -s sess_AbcDef123' },
165
+ { description: 'Allow the agent to send multiple answers per turn',
166
+ command: 'plazbot agent chat agt_AbcDef123 -m' },
167
+ ]);
162
168
  function formatResponse(text) {
163
169
  if (!text)
164
170
  return '';
165
171
  return text.split('\n').map(line => {
166
172
  // Headers
167
173
  if (line.startsWith('### '))
168
- return chalk_1.default.bold.hex('#4CAF50')(' ' + line.substring(4));
174
+ return chalk.bold.hex('#4CAF50')(' ' + line.substring(4));
169
175
  if (line.startsWith('## '))
170
- return chalk_1.default.bold.hex('#4CAF50')(' ' + line.substring(3));
176
+ return chalk.bold.hex('#4CAF50')(' ' + line.substring(3));
171
177
  if (line.startsWith('# '))
172
- return chalk_1.default.bold.hex('#4CAF50')(' ' + line.substring(2));
178
+ return chalk.bold.hex('#4CAF50')(' ' + line.substring(2));
173
179
  // Bold
174
- line = line.replace(/\*\*(.*?)\*\*/g, (_, text) => chalk_1.default.bold(text));
180
+ line = line.replace(/\*\*(.*?)\*\*/g, (_, text) => chalk.bold(text));
175
181
  // Italic
176
- line = line.replace(/\*(.*?)\*/g, (_, text) => chalk_1.default.italic(text));
182
+ line = line.replace(/\*(.*?)\*/g, (_, text) => chalk.italic(text));
177
183
  // Code inline
178
- line = line.replace(/`(.*?)`/g, (_, text) => chalk_1.default.hex('#FFA726')(text));
184
+ line = line.replace(/`(.*?)`/g, (_, text) => chalk.hex('#FFA726')(text));
179
185
  // List items
180
186
  if (line.match(/^\s*[-*]\s/)) {
181
- return chalk_1.default.white(' ' + line.replace(/^\s*[-*]\s/, ' • '));
187
+ return chalk.white(' ' + line.replace(/^\s*[-*]\s/, ' • '));
182
188
  }
183
189
  // Numbered lists
184
190
  if (line.match(/^\s*\d+\.\s/)) {
185
- return chalk_1.default.white(' ' + line);
191
+ return chalk.white(' ' + line);
186
192
  }
187
- return chalk_1.default.white(' ' + line);
193
+ return chalk.white(' ' + line);
188
194
  }).join('\n');
189
195
  }