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.
- package/CLAUDE.md +34 -5
- package/README.md +21 -0
- package/dist/cli.js +32 -20
- package/dist/commands/agent/ai-config.js +98 -50
- package/dist/commands/agent/chat.js +80 -74
- package/dist/commands/agent/copy.js +23 -21
- package/dist/commands/agent/create.js +42 -72
- package/dist/commands/agent/delete.js +29 -30
- package/dist/commands/agent/enable-widget.js +30 -26
- package/dist/commands/agent/export.js +90 -77
- package/dist/commands/agent/files.js +68 -60
- package/dist/commands/agent/get.js +101 -87
- package/dist/commands/agent/index.js +53 -39
- package/dist/commands/agent/list.js +26 -24
- package/dist/commands/agent/monitor.js +91 -86
- package/dist/commands/agent/on-message.js +40 -37
- package/dist/commands/agent/set.js +62 -59
- package/dist/commands/agent/templates.js +109 -108
- package/dist/commands/agent/tools.js +64 -65
- package/dist/commands/agent/update.js +28 -27
- package/dist/commands/agent/validate.js +127 -0
- package/dist/commands/agent/wizard.js +152 -159
- package/dist/commands/auth/index.js +7 -10
- package/dist/commands/auth/login.js +50 -37
- package/dist/commands/auth/logout.js +16 -14
- package/dist/commands/auth/status.js +19 -16
- package/dist/commands/portal/add-agent.js +26 -24
- package/dist/commands/portal/add-link.js +21 -17
- package/dist/commands/portal/clear-links.js +17 -15
- package/dist/commands/portal/create.js +25 -21
- package/dist/commands/portal/delete.js +31 -30
- package/dist/commands/portal/get.js +33 -31
- package/dist/commands/portal/index.js +30 -22
- package/dist/commands/portal/list.js +34 -30
- package/dist/commands/portal/update.js +41 -33
- package/dist/commands/whatsapp/broadcast.js +40 -37
- package/dist/commands/whatsapp/channels.js +40 -34
- package/dist/commands/whatsapp/chat.js +33 -32
- package/dist/commands/whatsapp/connect.js +53 -52
- package/dist/commands/whatsapp/delete-webhook.js +19 -17
- package/dist/commands/whatsapp/index.js +35 -25
- package/dist/commands/whatsapp/register-webhook.js +21 -19
- package/dist/commands/whatsapp/send-template.js +39 -31
- package/dist/commands/whatsapp/send.js +27 -23
- package/dist/commands/whatsapp/widget.js +35 -31
- package/dist/commands/workers/deploy.js +49 -44
- package/dist/commands/workers/index.js +28 -18
- package/dist/commands/workers/list.js +43 -35
- package/dist/commands/workers/logs.js +38 -32
- package/dist/commands/workers/remove.js +38 -37
- package/dist/commands/workers/secret.js +63 -58
- package/dist/commands/workers/test.js +44 -36
- package/dist/schemas/agent.config.schema.json +569 -0
- package/dist/studio/api/sseClient.js +97 -0
- package/dist/studio/api/studioApi.js +25 -0
- package/dist/studio/api/types.js +16 -0
- package/dist/studio/components/AgentPanel.js +35 -0
- package/dist/studio/components/App.js +214 -0
- package/dist/studio/components/ChatLog.js +59 -0
- package/dist/studio/components/Footer.js +11 -0
- package/dist/studio/components/Header.js +8 -0
- package/dist/studio/components/Input.js +15 -0
- package/dist/studio/components/Message.js +56 -0
- package/dist/studio/components/Suggestions.js +11 -0
- package/dist/studio/components/ToolCall.js +33 -0
- package/dist/studio/components/WhatsappConnectCard.js +57 -0
- package/dist/studio/index.js +42 -0
- package/dist/studio/render/json.js +16 -0
- package/dist/studio/render/markdown.js +32 -0
- package/dist/studio/render/steps.js +58 -0
- package/dist/studio/runOneShot.js +96 -0
- package/dist/studio/runRepl.js +52 -0
- package/dist/studio/slash/handlers.js +199 -0
- package/dist/studio/slash/parser.js +46 -0
- package/dist/studio/slash/registry.js +16 -0
- package/dist/studio/state/store.js +181 -0
- package/dist/studio/whatsapp/api.js +63 -0
- package/dist/studio/whatsapp/polling.js +77 -0
- package/dist/studio/whatsapp/types.js +31 -0
- package/dist/types/agent.js +1 -2
- package/dist/types/auth.js +1 -2
- package/dist/types/common.js +1 -2
- package/dist/types/message.js +1 -2
- package/dist/types/portal.js +1 -2
- package/dist/types/workers.js +1 -2
- package/dist/utils/agent-errors.js +46 -0
- package/dist/utils/api.js +8 -9
- package/dist/utils/banner.js +33 -34
- package/dist/utils/credentials.js +12 -20
- package/dist/utils/help.js +44 -0
- package/dist/utils/logger.js +13 -19
- package/dist/utils/ui.js +35 -49
- package/package.json +21 -10
- package/src/cli.ts +24 -8
- package/src/commands/agent/ai-config.ts +89 -34
- package/src/commands/agent/chat.ts +49 -37
- package/src/commands/agent/copy.ts +19 -13
- package/src/commands/agent/create.ts +32 -22
- package/src/commands/agent/delete.ts +24 -18
- package/src/commands/agent/enable-widget.ts +31 -23
- package/src/commands/agent/export.ts +72 -51
- package/src/commands/agent/files.ts +51 -39
- package/src/commands/agent/get.ts +86 -66
- package/src/commands/agent/index.ts +36 -18
- package/src/commands/agent/list.ts +22 -16
- package/src/commands/agent/monitor.ts +67 -56
- package/src/commands/agent/on-message.ts +36 -27
- package/src/commands/agent/set.ts +47 -37
- package/src/commands/agent/templates.ts +90 -82
- package/src/commands/agent/tools.ts +53 -47
- package/src/commands/agent/update.ts +28 -20
- package/src/commands/agent/validate.ts +135 -0
- package/src/commands/agent/wizard.ts +114 -114
- package/src/commands/auth/index.ts +3 -3
- package/src/commands/auth/login.ts +44 -29
- package/src/commands/auth/logout.ts +16 -10
- package/src/commands/auth/status.ts +14 -8
- package/src/commands/portal/add-agent.ts +23 -17
- package/src/commands/portal/add-link.ts +17 -9
- package/src/commands/portal/clear-links.ts +13 -7
- package/src/commands/portal/create.ts +20 -12
- package/src/commands/portal/delete.ts +28 -20
- package/src/commands/portal/get.ts +25 -19
- package/src/commands/portal/index.ts +22 -10
- package/src/commands/portal/list.ts +27 -19
- package/src/commands/portal/update.ts +38 -26
- package/src/commands/whatsapp/broadcast.ts +28 -18
- package/src/commands/whatsapp/channels.ts +31 -20
- package/src/commands/whatsapp/chat.ts +20 -12
- package/src/commands/whatsapp/connect.ts +39 -31
- package/src/commands/whatsapp/delete-webhook.ts +15 -9
- package/src/commands/whatsapp/index.ts +24 -10
- package/src/commands/whatsapp/register-webhook.ts +16 -10
- package/src/commands/whatsapp/send-template.ts +33 -21
- package/src/commands/whatsapp/send.ts +23 -15
- package/src/commands/whatsapp/widget.ts +25 -17
- package/src/commands/workers/deploy.ts +34 -22
- package/src/commands/workers/index.ts +21 -7
- package/src/commands/workers/list.ts +31 -19
- package/src/commands/workers/logs.ts +30 -20
- package/src/commands/workers/remove.ts +30 -22
- package/src/commands/workers/secret.ts +46 -34
- package/src/commands/workers/test.ts +34 -22
- package/src/schemas/agent.config.schema.json +569 -0
- package/src/studio/api/sseClient.ts +91 -0
- package/src/studio/api/studioApi.ts +27 -0
- package/src/studio/api/types.ts +96 -0
- package/src/studio/components/App.tsx +266 -0
- package/src/studio/components/ChatLog.tsx +95 -0
- package/src/studio/components/Footer.tsx +38 -0
- package/src/studio/components/Header.tsx +39 -0
- package/src/studio/components/Input.tsx +32 -0
- package/src/studio/components/Message.tsx +87 -0
- package/src/studio/components/Suggestions.tsx +26 -0
- package/src/studio/components/ToolCall.tsx +58 -0
- package/src/studio/components/WhatsappConnectCard.tsx +139 -0
- package/src/studio/index.ts +58 -0
- package/src/studio/render/markdown.ts +32 -0
- package/src/studio/render/steps.ts +57 -0
- package/src/studio/runOneShot.ts +114 -0
- package/src/studio/runRepl.tsx +76 -0
- package/src/studio/slash/handlers.ts +226 -0
- package/src/studio/slash/parser.ts +41 -0
- package/src/studio/slash/registry.ts +54 -0
- package/src/studio/state/store.ts +273 -0
- package/src/studio/whatsapp/api.ts +96 -0
- package/src/studio/whatsapp/polling.ts +93 -0
- package/src/studio/whatsapp/types.ts +80 -0
- package/src/types/agent.ts +1 -1
- package/src/types/auth.ts +4 -3
- package/src/types/portal.ts +1 -1
- package/src/types/workers.ts +1 -1
- package/src/utils/agent-errors.ts +67 -0
- package/src/utils/api.ts +6 -0
- package/src/utils/banner.ts +14 -9
- package/src/utils/credentials.ts +6 -5
- package/src/utils/help.ts +51 -0
- package/tsconfig.json +9 -6
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 >=
|
|
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
|
-
│
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
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
|
-
|
|
24
|
+
program
|
|
15
25
|
.name('plazbot')
|
|
16
|
-
.description('
|
|
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
|
-
|
|
29
|
+
authCommands.forEach(cmd => program.addCommand(cmd));
|
|
20
30
|
// Registrar todos los comandos de agente
|
|
21
|
-
|
|
31
|
+
program.addCommand(agentCommands);
|
|
22
32
|
// Registrar todos los comandos de portal
|
|
23
|
-
|
|
33
|
+
program.addCommand(portalCommands);
|
|
24
34
|
// Registrar todos los comandos de WhatsApp
|
|
25
|
-
|
|
35
|
+
program.addCommand(whatsappCommands);
|
|
26
36
|
// Registrar todos los comandos de Workers
|
|
27
|
-
|
|
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
|
-
|
|
31
|
-
|
|
42
|
+
showBanner().then(() => {
|
|
43
|
+
program.outputHelp();
|
|
32
44
|
});
|
|
33
45
|
}
|
|
34
46
|
else {
|
|
35
|
-
|
|
47
|
+
program.parse(process.argv);
|
|
36
48
|
}
|
|
@@ -1,82 +1,126 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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: [
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
19
|
-
.description('
|
|
20
|
-
.argument('<agentId>', 'ID
|
|
21
|
-
.option('--dev', '
|
|
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
|
|
25
|
-
const agent = new
|
|
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 =
|
|
67
|
+
const spinner = createSpinner('Loading agent...');
|
|
32
68
|
spinner.start();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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(
|
|
83
|
+
console.log(theme.bold('\n Current configuration:'));
|
|
40
84
|
currentProviders.forEach((p) => {
|
|
41
|
-
console.log(
|
|
42
|
-
console.log(
|
|
43
|
-
console.log(
|
|
44
|
-
console.log(
|
|
45
|
-
console.log(
|
|
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(
|
|
93
|
+
console.log(theme.muted('\n Using default AI configuration (Plazbot)'));
|
|
50
94
|
}
|
|
51
|
-
const { action } = await
|
|
95
|
+
const { action } = await inquirer.prompt([{
|
|
52
96
|
type: 'list',
|
|
53
97
|
name: 'action',
|
|
54
|
-
message: '
|
|
98
|
+
message: 'What would you like to do?',
|
|
55
99
|
choices: [
|
|
56
|
-
{ name: '
|
|
57
|
-
{ name: '
|
|
58
|
-
{ name: '
|
|
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 =
|
|
109
|
+
const resetSpinner = createSpinner('Resetting configuration...');
|
|
66
110
|
resetSpinner.start();
|
|
67
111
|
await agent.updateAgent(agentId, resetConfig);
|
|
68
|
-
resetSpinner.succeed('
|
|
112
|
+
resetSpinner.succeed('Using default configuration');
|
|
69
113
|
return;
|
|
70
114
|
}
|
|
71
115
|
// Configurar nuevo proveedor
|
|
72
|
-
const ai = await
|
|
73
|
-
{ type: 'list', name: 'provider', message: '
|
|
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
|
|
77
|
-
{ type: 'list', name: 'model', message: '
|
|
78
|
-
{ type: 'password', name: 'apiToken', message: 'API Token:', mask: '*', validate: (v) => v.length > 0 || '
|
|
79
|
-
{ type: 'number', name: 'temperature', message: '
|
|
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 =
|
|
138
|
+
const updateSpinner = createSpinner('Saving configuration...');
|
|
95
139
|
updateSpinner.start();
|
|
96
140
|
await agent.updateAgent(agentId, updatedConfig);
|
|
97
|
-
updateSpinner.succeed(`
|
|
141
|
+
updateSpinner.succeed(`Provider configured: ${ai.provider} / ${config.model}`);
|
|
98
142
|
}
|
|
99
143
|
catch (error) {
|
|
100
|
-
const message = error instanceof Error ? error.message : '
|
|
101
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
${
|
|
17
|
-
${
|
|
18
|
-
${
|
|
19
|
-
${
|
|
20
|
-
${
|
|
21
|
-
${
|
|
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
|
-
|
|
24
|
-
.description('
|
|
25
|
-
.
|
|
26
|
-
.option('-s, --session-id <id>', 'ID
|
|
27
|
-
.option('-m, --multiple-answers', '
|
|
28
|
-
.option('--dev', '
|
|
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
|
|
32
|
-
const agent = new
|
|
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 ||
|
|
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(
|
|
44
|
-
const _res = await agent.getAgentById({ id:
|
|
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 =
|
|
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 || '
|
|
58
|
-
const toolCalling = agentInfo?.useToolCalling ?
|
|
55
|
+
const agentName = agentInfo?.name || 'Agent';
|
|
56
|
+
const toolCalling = agentInfo?.useToolCalling ? chalk.hex('#4CAF50')(' [Tool Calling]') : '';
|
|
59
57
|
console.log();
|
|
60
|
-
console.log(
|
|
61
|
-
console.log(
|
|
62
|
-
console.log(
|
|
63
|
-
console.log(
|
|
64
|
-
console.log(
|
|
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('
|
|
69
|
-
console.log(
|
|
70
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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(
|
|
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(
|
|
112
|
+
process.stdout.write(chalk.gray(' ...thinking\n'));
|
|
115
113
|
const response = await agent.onMessage({
|
|
116
|
-
agentId:
|
|
114
|
+
agentId: agentId,
|
|
117
115
|
question,
|
|
118
116
|
sessionId,
|
|
119
117
|
multipleAnswers: options.multipleAnswers
|
|
120
118
|
});
|
|
121
|
-
const timestamp = new Date().toLocaleTimeString('
|
|
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(
|
|
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(
|
|
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(
|
|
135
|
+
console.log(chalk.gray(' Sources:'));
|
|
138
136
|
response.sources.forEach((source) => {
|
|
139
|
-
console.log(
|
|
137
|
+
console.log(chalk.gray(` - ${source.title || 'Untitled'}`));
|
|
140
138
|
if (source.url)
|
|
141
|
-
console.log(
|
|
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 : '
|
|
149
|
-
console.log(
|
|
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 : '
|
|
158
|
-
|
|
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
|
|
174
|
+
return chalk.bold.hex('#4CAF50')(' ' + line.substring(4));
|
|
169
175
|
if (line.startsWith('## '))
|
|
170
|
-
return
|
|
176
|
+
return chalk.bold.hex('#4CAF50')(' ' + line.substring(3));
|
|
171
177
|
if (line.startsWith('# '))
|
|
172
|
-
return
|
|
178
|
+
return chalk.bold.hex('#4CAF50')(' ' + line.substring(2));
|
|
173
179
|
// Bold
|
|
174
|
-
line = line.replace(/\*\*(.*?)\*\*/g, (_, text) =>
|
|
180
|
+
line = line.replace(/\*\*(.*?)\*\*/g, (_, text) => chalk.bold(text));
|
|
175
181
|
// Italic
|
|
176
|
-
line = line.replace(/\*(.*?)\*/g, (_, text) =>
|
|
182
|
+
line = line.replace(/\*(.*?)\*/g, (_, text) => chalk.italic(text));
|
|
177
183
|
// Code inline
|
|
178
|
-
line = line.replace(/`(.*?)`/g, (_, text) =>
|
|
184
|
+
line = line.replace(/`(.*?)`/g, (_, text) => chalk.hex('#FFA726')(text));
|
|
179
185
|
// List items
|
|
180
186
|
if (line.match(/^\s*[-*]\s/)) {
|
|
181
|
-
return
|
|
187
|
+
return chalk.white(' ' + line.replace(/^\s*[-*]\s/, ' • '));
|
|
182
188
|
}
|
|
183
189
|
// Numbered lists
|
|
184
190
|
if (line.match(/^\s*\d+\.\s/)) {
|
|
185
|
-
return
|
|
191
|
+
return chalk.white(' ' + line);
|
|
186
192
|
}
|
|
187
|
-
return
|
|
193
|
+
return chalk.white(' ' + line);
|
|
188
194
|
}).join('\n');
|
|
189
195
|
}
|