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.
- 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 +86 -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 +22 -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 +93 -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
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "AgentConfig",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": ["name", "prompt", "zone", "buffer"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": { "type": "string" },
|
|
8
|
+
"description": { "type": "string" },
|
|
9
|
+
"prompt": { "type": "string" },
|
|
10
|
+
"zone": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"enum": ["LA", "EU"]
|
|
13
|
+
},
|
|
14
|
+
"timezone": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "IANA timezone string, e.g., 'America/Lima', 'Europe/Madrid'"
|
|
17
|
+
},
|
|
18
|
+
"buffer": {
|
|
19
|
+
"type": "integer",
|
|
20
|
+
"minimum": 3,
|
|
21
|
+
"maximum": 20
|
|
22
|
+
},
|
|
23
|
+
"version": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"pattern": "^v\\d+\\.\\d+$",
|
|
26
|
+
"description": "Version del agente (auto-incrementado). Formato: v2.0, v2.1, etc."
|
|
27
|
+
},
|
|
28
|
+
"color": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"enum": ["orange", "blue", "green", "gray", "white"]
|
|
31
|
+
},
|
|
32
|
+
"question": { "type": "string" },
|
|
33
|
+
"enable": { "type": "boolean" },
|
|
34
|
+
"tags": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"items": { "type": "string" }
|
|
37
|
+
},
|
|
38
|
+
"instructions": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"properties": {
|
|
41
|
+
"tone": { "type": "string" },
|
|
42
|
+
"style": { "type": "string" },
|
|
43
|
+
"personality": { "type": "string" },
|
|
44
|
+
"objective": { "type": "string" },
|
|
45
|
+
"language": { "type": "string" },
|
|
46
|
+
"emojis": { "type": "boolean" },
|
|
47
|
+
"preferredFormat": { "type": "string" },
|
|
48
|
+
"maxWords": { "type": "integer" },
|
|
49
|
+
"avoidTopics": {
|
|
50
|
+
"type": "array",
|
|
51
|
+
"items": { "type": "string" }
|
|
52
|
+
},
|
|
53
|
+
"respondOnlyIfKnows": { "type": "boolean" },
|
|
54
|
+
"maintainToneBetweenMessages": { "type": "boolean" },
|
|
55
|
+
"greeting": { "type": "string" }
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"person": {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"properties": {
|
|
61
|
+
"name": { "type": "string" },
|
|
62
|
+
"role": { "type": "string" },
|
|
63
|
+
"speaksInFirstPerson": { "type": "boolean" },
|
|
64
|
+
"isHuman": { "type": "boolean" }
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"fallbacks": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"properties": {
|
|
70
|
+
"noAnswer": { "type": "string" },
|
|
71
|
+
"serviceError": { "type": "string" },
|
|
72
|
+
"doNotUnderstand": { "type": "string" }
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"rules": {
|
|
76
|
+
"type": "object",
|
|
77
|
+
"properties": {
|
|
78
|
+
"doNotMentionPrices": { "type": "boolean" },
|
|
79
|
+
"doNotDiagnose": { "type": "boolean" },
|
|
80
|
+
"doNotRespondOutsideHours": { "type": "string" }
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"examples": {
|
|
84
|
+
"type": "array",
|
|
85
|
+
"items": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"required": ["value", "color"],
|
|
88
|
+
"properties": {
|
|
89
|
+
"value": { "type": "string" },
|
|
90
|
+
"color": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"enum": ["orange", "blue", "green", "gray", "white"]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"showInChat": { "type": "boolean" },
|
|
98
|
+
"enableWidget": { "type": "boolean" },
|
|
99
|
+
"enableWhatsappWidget": { "type": "boolean" },
|
|
100
|
+
"urlWhatsappWidget": { "type": "string" },
|
|
101
|
+
"formWidget": { "type": "boolean" },
|
|
102
|
+
"darkWidget": { "type": "boolean" },
|
|
103
|
+
"colorWidget": {
|
|
104
|
+
"type": ["string", "null"],
|
|
105
|
+
"enum": ["white", "dark", "green", "blue", "gray", null],
|
|
106
|
+
"description": "Tema visual del widget. Tiene prioridad sobre darkWidget cuando esta definido."
|
|
107
|
+
},
|
|
108
|
+
"nameWidget": { "type": "string" },
|
|
109
|
+
"initialShowWidget": { "type": "boolean" },
|
|
110
|
+
"initialViewWidget": {
|
|
111
|
+
"type": ["string", "null"],
|
|
112
|
+
"enum": ["home", "chat", "avatar", null],
|
|
113
|
+
"description": "Vista inicial al abrir el widget manualmente: home | chat | avatar. Null = home (legacy)."
|
|
114
|
+
},
|
|
115
|
+
"fUseAutomationFlowWidget": { "type": "boolean" },
|
|
116
|
+
"iconWidget": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"enum": ["robot", "message", "support", "qa", "chat", "smile", "voice", "uservoice"],
|
|
119
|
+
"default": "robot"
|
|
120
|
+
},
|
|
121
|
+
"typeWidget": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"enum": ["widget", "search"],
|
|
124
|
+
"default": "widget",
|
|
125
|
+
"description": "Tipo de widget: widget (chat lateral clasico) o search (buscador centrado tipo Spotlight)"
|
|
126
|
+
},
|
|
127
|
+
"positionWidget": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"enum": ["down", "center"],
|
|
130
|
+
"default": "down",
|
|
131
|
+
"description": "Posicion del widget al abrirse: down (abajo-derecha clasico) o center (centrado en pantalla). Solo aplica en desktop (>=768px). En mobile siempre es fullscreen."
|
|
132
|
+
},
|
|
133
|
+
"enablePoweredBy": {
|
|
134
|
+
"type": "boolean",
|
|
135
|
+
"default": false,
|
|
136
|
+
"description": "Mostrar 'Powered by Plazbot' en el footer del widget. Solo editable desde AgentTraining para companies plazbot/plazbot-eu/plazbot-developer/plazbot-sandbox."
|
|
137
|
+
},
|
|
138
|
+
"multianswerWidget": {
|
|
139
|
+
"type": "boolean",
|
|
140
|
+
"default": false,
|
|
141
|
+
"description": "Si true, divide la respuesta del agente IA en varios mensajes (split por doble salto de linea)."
|
|
142
|
+
},
|
|
143
|
+
"enableAvatarWidget": { "type": "boolean" },
|
|
144
|
+
"avatarGender": {
|
|
145
|
+
"type": "string",
|
|
146
|
+
"enum": ["male", "female"],
|
|
147
|
+
"description": "DEPRECATED: legacy Simli. HeyGen no lo usa (el genero es inherente al avatarFaceId). Se mantiene por retrocompatibilidad."
|
|
148
|
+
},
|
|
149
|
+
"avatarVoiceId": {
|
|
150
|
+
"type": "string",
|
|
151
|
+
"description": "HeyGen voice_id (Multilingual). Usa 'default' o vacio para que HeyGen aplique la voz nativa del avatar."
|
|
152
|
+
},
|
|
153
|
+
"avatarLanguage": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"description": "Codigo ISO corto HeyGen: es | en | pt | fr | it | de"
|
|
156
|
+
},
|
|
157
|
+
"avatarFaceId": {
|
|
158
|
+
"type": "string",
|
|
159
|
+
"description": "HeyGen avatar_id (ej: 'Annie_expressive12_public'). Nombre legacy heredado de Simli."
|
|
160
|
+
},
|
|
161
|
+
"avatarApiKey": {
|
|
162
|
+
"type": "string",
|
|
163
|
+
"description": "API Key personal de HeyGen del cliente (BYOK). Texto plano en CosmosDB."
|
|
164
|
+
},
|
|
165
|
+
"avatarQuality": {
|
|
166
|
+
"type": "string",
|
|
167
|
+
"enum": ["low", "medium", "high"],
|
|
168
|
+
"default": "medium",
|
|
169
|
+
"description": "Calidad del streaming HeyGen. A mayor calidad mayor consumo de creditos."
|
|
170
|
+
},
|
|
171
|
+
"avatarBackground": {
|
|
172
|
+
"type": ["string", "null"],
|
|
173
|
+
"description": "URL de imagen de fondo personalizada para el avatar (S3). Si tiene valor, el backend usa el avatar con fondo verde y el widget aplica chroma key."
|
|
174
|
+
},
|
|
175
|
+
"voiceConfig": {
|
|
176
|
+
"type": "object",
|
|
177
|
+
"description": "Voice agent configuration for phone calls",
|
|
178
|
+
"properties": {
|
|
179
|
+
"enabled": { "type": "boolean" },
|
|
180
|
+
"phoneNumber": { "type": "string", "description": "DID phone number, e.g., +573151234567" },
|
|
181
|
+
"ttsProvider": { "type": "string", "enum": ["google", "openai"] },
|
|
182
|
+
"ttsVoiceId": { "type": "string", "description": "TTS voice ID, e.g., nova, es-US-Journey-D" },
|
|
183
|
+
"ttsLanguage": { "type": "string", "description": "Language code, e.g., es-CO, es-MX" },
|
|
184
|
+
"greeting": { "type": "string", "description": "Initial greeting message for TTS" },
|
|
185
|
+
"maxCallDurationSeconds": { "type": "integer", "minimum": 60, "maximum": 1800, "default": 300 },
|
|
186
|
+
"silenceTimeoutMs": { "type": "integer", "minimum": 2000, "maximum": 15000, "default": 5000 },
|
|
187
|
+
"transferExtension": { "type": "string", "description": "SIP extension for human transfer" },
|
|
188
|
+
"voiceType": { "type": "string", "enum": ["compact", "complete"], "description": "compact=fast no tools, complete=full toolcalling+RAG" }
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"useToolCalling": {
|
|
192
|
+
"type": "boolean",
|
|
193
|
+
"default": false,
|
|
194
|
+
"description": "If true, uses the Tool Calling orchestrator for more natural conversations. If false, uses the classic orchestrator."
|
|
195
|
+
},
|
|
196
|
+
"enableWebSearch": {
|
|
197
|
+
"type": "boolean",
|
|
198
|
+
"default": false,
|
|
199
|
+
"description": "If true, the agent can search the web using the provider's native tool (OpenAI web_search_preview, Claude web_search_20250305, Gemini google_search). No extra API key required."
|
|
200
|
+
},
|
|
201
|
+
"responseMode": {
|
|
202
|
+
"type": "string",
|
|
203
|
+
"enum": ["direct", "batched"],
|
|
204
|
+
"default": "direct",
|
|
205
|
+
"description": "Modo de respuesta: direct (inmediato) o batched (espera mensajes consecutivos)"
|
|
206
|
+
},
|
|
207
|
+
"batchWaitSeconds": {
|
|
208
|
+
"type": "integer",
|
|
209
|
+
"minimum": 2,
|
|
210
|
+
"maximum": 10,
|
|
211
|
+
"default": 3,
|
|
212
|
+
"description": "Segundos de espera para acumular mensajes consecutivos (solo si responseMode=batched)"
|
|
213
|
+
},
|
|
214
|
+
"customAIConfig": {
|
|
215
|
+
"type": "boolean",
|
|
216
|
+
"default": false,
|
|
217
|
+
"description": "If true, uses aiProviders from agent config. If false, uses company.openaiData.openaiToken"
|
|
218
|
+
},
|
|
219
|
+
"aiProviders": {
|
|
220
|
+
"type": "array",
|
|
221
|
+
"description": "Custom AI provider configurations. Only used when customAIConfig is true",
|
|
222
|
+
"items": {
|
|
223
|
+
"type": "object",
|
|
224
|
+
"required": ["provider", "model", "apiToken"],
|
|
225
|
+
"properties": {
|
|
226
|
+
"provider": {
|
|
227
|
+
"type": "string",
|
|
228
|
+
"enum": ["openai", "claude", "gemini"],
|
|
229
|
+
"description": "AI provider: openai, claude (Anthropic), or gemini (Google)"
|
|
230
|
+
},
|
|
231
|
+
"model": {
|
|
232
|
+
"type": "string",
|
|
233
|
+
"description": "Specific model name: 'gpt-5.4', 'gpt-4o', 'claude-sonnet-4-6', 'claude-opus-4-6', 'gemini-2.5-pro', 'gemini-2.5-flash'"
|
|
234
|
+
},
|
|
235
|
+
"apiToken": {
|
|
236
|
+
"type": "string",
|
|
237
|
+
"description": "API token for the provider"
|
|
238
|
+
},
|
|
239
|
+
"temperature": {
|
|
240
|
+
"type": "number",
|
|
241
|
+
"minimum": 0,
|
|
242
|
+
"maximum": 2,
|
|
243
|
+
"default": 0.7,
|
|
244
|
+
"description": "Controls randomness in responses (0-2)"
|
|
245
|
+
},
|
|
246
|
+
"maxTokens": {
|
|
247
|
+
"type": "integer",
|
|
248
|
+
"minimum": 1,
|
|
249
|
+
"description": "Maximum tokens in response"
|
|
250
|
+
},
|
|
251
|
+
"isDefault": {
|
|
252
|
+
"type": "boolean",
|
|
253
|
+
"default": false,
|
|
254
|
+
"description": "If multiple providers exist, which one to use by default"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
"channels": {
|
|
260
|
+
"type": "array",
|
|
261
|
+
"items": {
|
|
262
|
+
"type": "object",
|
|
263
|
+
"required": ["channel", "key"],
|
|
264
|
+
"properties": {
|
|
265
|
+
"channel": { "type": "string" },
|
|
266
|
+
"key": { "type": "string" },
|
|
267
|
+
"multianswer": { "type": "boolean", "default": false }
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
"services": {
|
|
272
|
+
"type": "array",
|
|
273
|
+
"items": {
|
|
274
|
+
"type": "object",
|
|
275
|
+
"required": ["intent", "reference", "method", "endpoint", "requiredFields"],
|
|
276
|
+
"properties": {
|
|
277
|
+
"intent": { "type": "string" },
|
|
278
|
+
"reference": { "type": "string" },
|
|
279
|
+
"enabled": { "type": "boolean", "default": true },
|
|
280
|
+
"method": { "type": "string", "enum": ["GET", "POST"] },
|
|
281
|
+
"tags": {
|
|
282
|
+
"type": "array",
|
|
283
|
+
"items": { "type": "string" }
|
|
284
|
+
},
|
|
285
|
+
"endpoint": { "type": "string", "format": "uri" },
|
|
286
|
+
"requiredFields": {
|
|
287
|
+
"type": "array",
|
|
288
|
+
"items": {
|
|
289
|
+
"type": "object",
|
|
290
|
+
"properties": {
|
|
291
|
+
"name": {
|
|
292
|
+
"type": "string"
|
|
293
|
+
},
|
|
294
|
+
"description": {
|
|
295
|
+
"type": "string"
|
|
296
|
+
},
|
|
297
|
+
"promptHint": {
|
|
298
|
+
"type": "string"
|
|
299
|
+
},
|
|
300
|
+
"type": {
|
|
301
|
+
"type": "string",
|
|
302
|
+
"enum": ["string", "number", "integer", "boolean", "date", "datetime", "email", "phone", "array", "arrayObject"]
|
|
303
|
+
},
|
|
304
|
+
"properties": {
|
|
305
|
+
"type": "array",
|
|
306
|
+
"items": {
|
|
307
|
+
"type": "object",
|
|
308
|
+
"properties": {
|
|
309
|
+
"name": { "type": "string" },
|
|
310
|
+
"type": { "type": "string" }
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
"headers": {
|
|
318
|
+
"type": "object",
|
|
319
|
+
"additionalProperties": { "type": "string" }
|
|
320
|
+
},
|
|
321
|
+
"bodyTemplate": {
|
|
322
|
+
"type": "object",
|
|
323
|
+
"additionalProperties": { "type": "string" }
|
|
324
|
+
},
|
|
325
|
+
"bodySchema": {
|
|
326
|
+
"type": "object",
|
|
327
|
+
"additionalProperties": {
|
|
328
|
+
"type": "string",
|
|
329
|
+
"enum": ["string", "date", "boolean", "numeric"]
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
"responseMapping": {
|
|
333
|
+
"type": "object",
|
|
334
|
+
"additionalProperties": { "type": "string" }
|
|
335
|
+
},
|
|
336
|
+
"responseMessage": {
|
|
337
|
+
"type": "string"
|
|
338
|
+
},
|
|
339
|
+
"responseConditions": {
|
|
340
|
+
"type": "array",
|
|
341
|
+
"items": {
|
|
342
|
+
"type": "object",
|
|
343
|
+
"properties": {
|
|
344
|
+
"condition": {
|
|
345
|
+
"type": "string",
|
|
346
|
+
"description": "Condicion simple legacy (retrocompatible). Usar 'conditions' para AND/OR."
|
|
347
|
+
},
|
|
348
|
+
"conditions": {
|
|
349
|
+
"type": "array",
|
|
350
|
+
"description": "Sub-condiciones para combinar con AND/OR",
|
|
351
|
+
"items": {
|
|
352
|
+
"type": "object",
|
|
353
|
+
"required": ["condition"],
|
|
354
|
+
"properties": {
|
|
355
|
+
"condition": {
|
|
356
|
+
"type": "string",
|
|
357
|
+
"description": "Expresion condicional usando JSONPath y operadores (==, !=, <, >, <=, >=, in, nin)"
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
"logicalOperator": {
|
|
363
|
+
"type": "string",
|
|
364
|
+
"enum": ["AND", "OR"],
|
|
365
|
+
"default": "AND",
|
|
366
|
+
"description": "Operador logico para combinar sub-condiciones. Default: AND"
|
|
367
|
+
},
|
|
368
|
+
"message": {
|
|
369
|
+
"type": "string",
|
|
370
|
+
"description": "Mensaje a mostrar si la condicion se cumple"
|
|
371
|
+
},
|
|
372
|
+
"nextService": {
|
|
373
|
+
"type": "string",
|
|
374
|
+
"description": "Intent del siguiente servicio a activar automaticamente si se cumple la condicion"
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
"action": { "type": "string" }
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
"variables": {
|
|
384
|
+
"type": "array",
|
|
385
|
+
"description": "Variables personalizadas del agente con valores por defecto",
|
|
386
|
+
"items": {
|
|
387
|
+
"type": "object",
|
|
388
|
+
"required": ["code", "name", "type"],
|
|
389
|
+
"properties": {
|
|
390
|
+
"code": { "type": "string", "description": "Codigo unico de la variable (alfanumerico + underscore)" },
|
|
391
|
+
"name": { "type": "string", "description": "Nombre legible de la variable" },
|
|
392
|
+
"type": { "type": "string", "enum": ["string", "number", "boolean"], "description": "Tipo de dato" },
|
|
393
|
+
"defaultValue": { "type": "string", "description": "Valor por defecto si no se envia en on-message" },
|
|
394
|
+
"description": { "type": "string", "description": "Descripcion de para que se usa la variable" }
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
"source": {
|
|
399
|
+
"type": ["object", "null"],
|
|
400
|
+
"description": "Configuracion de Fuente de Datos del agente (Plazbot nativo o Google Sheets). El LLM consulta esta fuente cuando necesita responder con catalogos/stock/etc.",
|
|
401
|
+
"properties": {
|
|
402
|
+
"enabled": { "type": "boolean", "default": false },
|
|
403
|
+
"reference": {
|
|
404
|
+
"type": "string",
|
|
405
|
+
"description": "Descripcion que lee el LLM para decidir cuando consultar la fuente"
|
|
406
|
+
},
|
|
407
|
+
"sourceType": {
|
|
408
|
+
"type": ["string", "null"],
|
|
409
|
+
"enum": ["plazbot", "googlesheets", null],
|
|
410
|
+
"description": "Tipo de fuente: plazbot (nativa Supabase) o googlesheets"
|
|
411
|
+
},
|
|
412
|
+
"businessType": {
|
|
413
|
+
"type": ["string", "null"],
|
|
414
|
+
"enum": [
|
|
415
|
+
"products", "services", "menu", "real_estate", "courses",
|
|
416
|
+
"vehicles", "hospitality", "healthcare", "events", "parts",
|
|
417
|
+
"custom", null
|
|
418
|
+
],
|
|
419
|
+
"description": "Tipo de negocio para sugerir mapeo semantico"
|
|
420
|
+
},
|
|
421
|
+
"columnMapping": {
|
|
422
|
+
"type": ["object", "null"],
|
|
423
|
+
"additionalProperties": { "type": "string" },
|
|
424
|
+
"description": "Mapeo clave=nombre semantico -> valor=key real de la columna"
|
|
425
|
+
},
|
|
426
|
+
"plazbotSource": {
|
|
427
|
+
"type": ["object", "null"],
|
|
428
|
+
"properties": {
|
|
429
|
+
"sourceId": { "type": ["string", "null"] }
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
"googleSheets": {
|
|
433
|
+
"type": ["object", "null"],
|
|
434
|
+
"properties": {
|
|
435
|
+
"integrationId": { "type": ["string", "null"] },
|
|
436
|
+
"spreadsheetId": { "type": ["string", "null"] },
|
|
437
|
+
"sheetName": { "type": ["string", "null"] },
|
|
438
|
+
"sheetId": { "type": ["integer", "null"] },
|
|
439
|
+
"detectedColumns": {
|
|
440
|
+
"type": ["array", "null"],
|
|
441
|
+
"items": { "type": "string" }
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
},
|
|
447
|
+
"actions": {
|
|
448
|
+
"type": "array",
|
|
449
|
+
"items": {
|
|
450
|
+
"type": "object",
|
|
451
|
+
"required": ["intent", "reference", "enabled", "action"],
|
|
452
|
+
"properties": {
|
|
453
|
+
"intent": { "type": "string" },
|
|
454
|
+
"reference": { "type": "string" },
|
|
455
|
+
"tags": {
|
|
456
|
+
"type": "array",
|
|
457
|
+
"items": { "type": "string" }
|
|
458
|
+
},
|
|
459
|
+
"enabled": { "type": "boolean" },
|
|
460
|
+
"requiredFields": {
|
|
461
|
+
"type": "array",
|
|
462
|
+
"items": {
|
|
463
|
+
"type": "object",
|
|
464
|
+
"properties": {
|
|
465
|
+
"name": {
|
|
466
|
+
"type": "string"
|
|
467
|
+
},
|
|
468
|
+
"description": {
|
|
469
|
+
"type": "string"
|
|
470
|
+
},
|
|
471
|
+
"promptHint": {
|
|
472
|
+
"type": "string"
|
|
473
|
+
},
|
|
474
|
+
"type": {
|
|
475
|
+
"type": "string",
|
|
476
|
+
"enum": ["string", "number", "integer", "boolean", "date", "datetime", "email", "phone", "array", "arrayObject"]
|
|
477
|
+
},
|
|
478
|
+
"properties": {
|
|
479
|
+
"type": "array",
|
|
480
|
+
"items": {
|
|
481
|
+
"type": "object",
|
|
482
|
+
"properties": {
|
|
483
|
+
"name": { "type": "string" },
|
|
484
|
+
"type": { "type": "string" }
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
"responseMessage": { "type": "string" },
|
|
492
|
+
"responseJson": { "type": "boolean" },
|
|
493
|
+
"responseExact": { "type": "boolean" },
|
|
494
|
+
"action": {
|
|
495
|
+
"type": "array",
|
|
496
|
+
"items": {
|
|
497
|
+
"type": "object",
|
|
498
|
+
"required": ["type", "value"],
|
|
499
|
+
"properties": {
|
|
500
|
+
"type": {
|
|
501
|
+
"type": "string",
|
|
502
|
+
"enum": [
|
|
503
|
+
"action.asign",
|
|
504
|
+
"action.stage",
|
|
505
|
+
"action.agentShutDown",
|
|
506
|
+
"action.segmentation",
|
|
507
|
+
"action.tag",
|
|
508
|
+
"action.solved",
|
|
509
|
+
"action.event.add",
|
|
510
|
+
"action.event.update",
|
|
511
|
+
"action.event.delete",
|
|
512
|
+
"action.event.list",
|
|
513
|
+
"action.event.confirm",
|
|
514
|
+
"action.event.cancel",
|
|
515
|
+
"action.secuence",
|
|
516
|
+
"action.unassign",
|
|
517
|
+
"action.stage.remove",
|
|
518
|
+
"action.tag.remove",
|
|
519
|
+
"action.segmentation.remove",
|
|
520
|
+
"action.worker"
|
|
521
|
+
]
|
|
522
|
+
},
|
|
523
|
+
"value": { "type": "string" },
|
|
524
|
+
"durationMinutes": {
|
|
525
|
+
"type": "integer",
|
|
526
|
+
"minimum": 5,
|
|
527
|
+
"maximum": 480,
|
|
528
|
+
"default": 30,
|
|
529
|
+
"description": "Duracion del evento en minutos (solo para action.event.add/update). Default: 30"
|
|
530
|
+
},
|
|
531
|
+
"availabilitySchedule": {
|
|
532
|
+
"type": "object",
|
|
533
|
+
"description": "Horario personalizado para disponibilidad de citas (solo action.event.add). Si no se configura o useWorkspaceSchedule=true, usa el horario del workspace.",
|
|
534
|
+
"properties": {
|
|
535
|
+
"useWorkspaceSchedule": { "type": "boolean", "default": true },
|
|
536
|
+
"days": {
|
|
537
|
+
"type": "array",
|
|
538
|
+
"maxItems": 7,
|
|
539
|
+
"items": {
|
|
540
|
+
"type": "object",
|
|
541
|
+
"properties": {
|
|
542
|
+
"enabled": { "type": "boolean" },
|
|
543
|
+
"allDay": { "type": "boolean" },
|
|
544
|
+
"from": { "type": "string" },
|
|
545
|
+
"to": { "type": "string" },
|
|
546
|
+
"ranges": {
|
|
547
|
+
"type": "array",
|
|
548
|
+
"items": {
|
|
549
|
+
"type": "object",
|
|
550
|
+
"properties": {
|
|
551
|
+
"from": { "type": "string" },
|
|
552
|
+
"to": { "type": "string" }
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
"additionalProperties": false
|
|
569
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { buildStudioUrl, buildStudioHeaders } from './studioApi.js';
|
|
2
|
+
import { StudioHttpError } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Cliente SSE para POST /api/agent/studio.
|
|
5
|
+
* - Usa fetch() global (Node >=18) y lee `res.body` como ReadableStream.
|
|
6
|
+
* - Parsea líneas con prefijo `data:` y emite cada JSON como un StudioChunk.
|
|
7
|
+
* - Soporta cancelación via AbortSignal (tecla Esc en el REPL).
|
|
8
|
+
*/
|
|
9
|
+
export async function streamStudio(opts, request, onChunk, signal) {
|
|
10
|
+
const url = buildStudioUrl(opts.zone, opts.dev);
|
|
11
|
+
const headers = buildStudioHeaders(opts);
|
|
12
|
+
const body = {
|
|
13
|
+
...request,
|
|
14
|
+
workspaceId: request.workspaceId ?? opts.workspaceId,
|
|
15
|
+
userId: request.userId ?? opts.userId,
|
|
16
|
+
};
|
|
17
|
+
let res;
|
|
18
|
+
try {
|
|
19
|
+
res = await fetch(url, {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
headers,
|
|
22
|
+
body: JSON.stringify(body),
|
|
23
|
+
signal,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
if (err.name === 'AbortError')
|
|
28
|
+
return;
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
if (!res.ok) {
|
|
32
|
+
const text = await safeReadText(res);
|
|
33
|
+
throw new StudioHttpError(res.status, res.statusText, text);
|
|
34
|
+
}
|
|
35
|
+
if (!res.body) {
|
|
36
|
+
throw new Error('Respuesta sin body en POST /api/agent/studio');
|
|
37
|
+
}
|
|
38
|
+
const reader = res.body.getReader();
|
|
39
|
+
const decoder = new TextDecoder();
|
|
40
|
+
let buffer = '';
|
|
41
|
+
try {
|
|
42
|
+
while (true) {
|
|
43
|
+
const { done, value } = await reader.read();
|
|
44
|
+
if (done)
|
|
45
|
+
break;
|
|
46
|
+
buffer += decoder.decode(value, { stream: true });
|
|
47
|
+
// SSE: eventos separados por \n\n; cada evento puede tener varias líneas.
|
|
48
|
+
let idx;
|
|
49
|
+
while ((idx = buffer.indexOf('\n')) >= 0) {
|
|
50
|
+
const line = buffer.slice(0, idx).replace(/\r$/, '');
|
|
51
|
+
buffer = buffer.slice(idx + 1);
|
|
52
|
+
if (!line.startsWith('data:'))
|
|
53
|
+
continue;
|
|
54
|
+
const payload = line.slice(5).trim();
|
|
55
|
+
if (!payload)
|
|
56
|
+
continue;
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(payload);
|
|
59
|
+
onChunk(parsed);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Línea malformada: la ignoramos silenciosamente.
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Flush final
|
|
67
|
+
const tail = buffer.trim();
|
|
68
|
+
if (tail.startsWith('data:')) {
|
|
69
|
+
const payload = tail.slice(5).trim();
|
|
70
|
+
if (payload) {
|
|
71
|
+
try {
|
|
72
|
+
onChunk(JSON.parse(payload));
|
|
73
|
+
}
|
|
74
|
+
catch { /* ignore */ }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (err.name === 'AbortError')
|
|
80
|
+
return;
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
try {
|
|
85
|
+
reader.releaseLock();
|
|
86
|
+
}
|
|
87
|
+
catch { /* noop */ }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function safeReadText(res) {
|
|
91
|
+
try {
|
|
92
|
+
return await res.text();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return '';
|
|
96
|
+
}
|
|
97
|
+
}
|