novapsis 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -53
- package/dist/index.cjs +138 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +282 -22
- package/dist/index.d.ts +282 -22
- package/dist/index.mjs +138 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,6 +82,8 @@ await novapsis.whatsapp.sendLocation({
|
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
### Plantillas Oficiales de Meta (Templates)
|
|
85
|
+
|
|
86
|
+
#### Envío de Plantillas Aprobadas
|
|
85
87
|
```typescript
|
|
86
88
|
await novapsis.whatsapp.sendTemplate({
|
|
87
89
|
to: '34600112233',
|
|
@@ -99,86 +101,126 @@ await novapsis.whatsapp.sendTemplate({
|
|
|
99
101
|
});
|
|
100
102
|
```
|
|
101
103
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
## 🏢 2. Multi-Tenant y Sedes (B2B Tech Provider)
|
|
105
|
-
|
|
106
|
-
Si tienes un CRM o plataforma multi-tenant y quieres que tus clientes o sedes conecten su propio número de WhatsApp con su cuenta de Meta:
|
|
107
|
-
|
|
104
|
+
#### Listar Plantillas en Meta
|
|
108
105
|
```typescript
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
redirectUrl: 'https://tu-crm.com/sedes/12/whatsapp-callback',
|
|
113
|
-
logoUrl: 'https://tu-crm.com/logo.png', // Marca blanca (Plan PRO)
|
|
114
|
-
brandColor: '#0ea5e9', // Marca blanca (Plan PRO)
|
|
115
|
-
metadata: { sede_id: 'sede_12' },
|
|
106
|
+
const templates = await novapsis.whatsapp.listTemplates({
|
|
107
|
+
status: 'APPROVED', // Opcional: 'APPROVED', 'PENDING', 'REJECTED'
|
|
108
|
+
category: 'UTILITY', // Opcional: 'MARKETING', 'UTILITY', 'AUTHENTICATION'
|
|
116
109
|
});
|
|
117
|
-
|
|
118
|
-
// 2. Abre session.session_url en un modal o ventana popup en tu frontend
|
|
119
|
-
console.log(session.session_url);
|
|
110
|
+
console.log(templates);
|
|
120
111
|
```
|
|
121
112
|
|
|
122
|
-
|
|
113
|
+
#### Crear Plantilla en Meta Graph API
|
|
123
114
|
```typescript
|
|
124
|
-
await novapsis.whatsapp.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
115
|
+
const newTemplate = await novapsis.whatsapp.createTemplate({
|
|
116
|
+
name: 'confirmacion_entrega_v1',
|
|
117
|
+
displayName: 'Confirmación de Entrega',
|
|
118
|
+
category: 'UTILITY',
|
|
119
|
+
language: 'es',
|
|
120
|
+
components: [
|
|
121
|
+
{
|
|
122
|
+
type: 'HEADER',
|
|
123
|
+
format: 'TEXT',
|
|
124
|
+
text: 'Tu pedido está en camino 🚚',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: 'BODY',
|
|
128
|
+
text: 'Hola {{1}}, tu pedido #{{2}} ha salido de almacén y llegará hoy.',
|
|
129
|
+
example: {
|
|
130
|
+
body_text: [['Carlos', '94821']],
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
],
|
|
128
134
|
});
|
|
135
|
+
console.log('Plantilla enviada a Meta:', newTemplate.template.status);
|
|
129
136
|
```
|
|
130
137
|
|
|
131
138
|
---
|
|
132
139
|
|
|
133
|
-
##
|
|
140
|
+
## ⚙️ 2. Ajustes de la Aplicación y Organización (Settings & Renombrado)
|
|
134
141
|
|
|
135
|
-
|
|
142
|
+
Permite consultar los datos de la cuenta u organización y actualizar el nombre visible (para plataformas que ofrecen marca blanca o renombrado de la app) y su zona horaria IANA:
|
|
136
143
|
|
|
137
|
-
### En Next.js (App Router: `app/api/webhooks/novapsis/route.ts`)
|
|
138
144
|
```typescript
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
// 1. Obtener ajustes actuales
|
|
146
|
+
const org = await novapsis.organization.get();
|
|
147
|
+
console.log(`Organización actual: ${org.name}, Zona Horaria: ${org.timezone}`);
|
|
148
|
+
|
|
149
|
+
// 2. Cambiar nombre de la aplicación y zona horaria
|
|
150
|
+
const updated = await novapsis.organization.update({
|
|
151
|
+
name: 'Sistemas Médicos Nova ERP', // Renombrado de la app / empresa
|
|
152
|
+
timezone: 'Europe/Madrid',
|
|
144
153
|
});
|
|
154
|
+
console.log('Organización actualizada:', updated.name);
|
|
155
|
+
```
|
|
145
156
|
|
|
146
|
-
|
|
147
|
-
const rawBody = await req.text();
|
|
148
|
-
const signature = req.headers.get('x-novapsis-signature');
|
|
157
|
+
---
|
|
149
158
|
|
|
150
|
-
|
|
151
|
-
const isValid = novapsis.webhooks.verifySignature(
|
|
152
|
-
rawBody,
|
|
153
|
-
signature,
|
|
154
|
-
process.env.NOVAPSIS_WEBHOOK_SECRET!
|
|
155
|
-
);
|
|
159
|
+
## 🤖 3. Agentes de IA Headless: Prompts, Horarios y RAG
|
|
156
160
|
|
|
157
|
-
|
|
158
|
-
return NextResponse.json({ error: 'Firma inválida' }, { status: 401 });
|
|
159
|
-
}
|
|
161
|
+
Si construyes un panel de administración personalizado o un CRM propio, puedes gobernar los agentes de inteligencia artificial de Novapsis SM de forma 100% programática:
|
|
160
162
|
|
|
161
|
-
|
|
163
|
+
### Crear o Modificar Agente (Prompt de Sistema y Modelo)
|
|
164
|
+
```typescript
|
|
165
|
+
// 1. Crear un nuevo agente
|
|
166
|
+
const agent = await novapsis.ai.createAgent({
|
|
167
|
+
name: 'Asistente de Reservas y Urgencias',
|
|
168
|
+
systemPrompt: 'Eres el recepcionista virtual de Clínica Nova. Atiende con tono empático y solicita nombre y hora deseada.',
|
|
169
|
+
model: 'gemini-2.5-flash',
|
|
170
|
+
mode: 'both', // 'agent' | 'rag' | 'both'
|
|
171
|
+
temperature: 0.2,
|
|
172
|
+
isActive: true,
|
|
173
|
+
groupingTimeoutSeconds: 5, // Agrupa ráfagas de mensajes de WhatsApp
|
|
174
|
+
});
|
|
162
175
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
176
|
+
// 2. Modificar el nombre o el prompt dinámicamente
|
|
177
|
+
await novapsis.ai.updateAgent(agent.id, {
|
|
178
|
+
name: 'Asistente Principal Nova Dental',
|
|
179
|
+
systemPrompt: 'Actualización de protocolo: Preguntar primero si es asegurado privado.',
|
|
180
|
+
});
|
|
181
|
+
```
|
|
167
182
|
|
|
168
|
-
|
|
169
|
-
|
|
183
|
+
### Horarios de Atención del Agente
|
|
184
|
+
```typescript
|
|
185
|
+
// Configurar horario comercial (Lunes a Viernes de 09:00 a 19:00)
|
|
186
|
+
await novapsis.ai.setSchedule(agent.id, {
|
|
187
|
+
days: [1, 2, 3, 4, 5], // 1=Lunes ... 7=Domingo
|
|
188
|
+
activeFrom: '09:00',
|
|
189
|
+
activeUntil: '19:00',
|
|
190
|
+
name: 'Horario Comercial Sede Central',
|
|
191
|
+
isActive: true,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Consultar horario activo
|
|
195
|
+
const scheduleInfo = await novapsis.ai.getSchedule(agent.id);
|
|
196
|
+
console.log('Horario activo:', scheduleInfo.schedule, 'Timezone:', scheduleInfo.timezone);
|
|
170
197
|
```
|
|
171
198
|
|
|
172
|
-
|
|
199
|
+
### Ingesta de Base de Conocimiento (RAG Vectorial Instantáneo)
|
|
200
|
+
```typescript
|
|
201
|
+
// Sube texto plano que se procesa, fragmenta y vectoriza automáticamente (Vertex AI 1536d pgvector)
|
|
202
|
+
const doc = await novapsis.ai.addKnowledge(agent.id, {
|
|
203
|
+
title: 'Tarifario y Tratamientos 2026',
|
|
204
|
+
description: 'Precios actualizados de implantes y ortodoncia invisible',
|
|
205
|
+
content: `
|
|
206
|
+
- Limpieza dental ultrasónica: 45 EUR.
|
|
207
|
+
- Implante de titanio biocompatible: 650 EUR.
|
|
208
|
+
- Financiación disponible hasta en 24 meses sin intereses.
|
|
209
|
+
`,
|
|
210
|
+
});
|
|
211
|
+
console.log(`Documento RAG indexado con ID: ${doc.id}`);
|
|
173
212
|
|
|
174
|
-
|
|
213
|
+
// Consultar documentos activos del agente
|
|
214
|
+
const docs = await novapsis.ai.listKnowledge(agent.id);
|
|
215
|
+
console.log('Documentos RAG disponibles:', docs.length);
|
|
216
|
+
```
|
|
175
217
|
|
|
218
|
+
### Ejecutar Consulta Conversacional
|
|
176
219
|
```typescript
|
|
177
220
|
const result = await novapsis.ai.execute({
|
|
178
|
-
agentId:
|
|
179
|
-
message: '¿
|
|
221
|
+
agentId: agent.id,
|
|
222
|
+
message: '¿Cuánto cuesta la limpieza dental y qué horarios tenéis?',
|
|
180
223
|
});
|
|
181
|
-
|
|
182
224
|
console.log(result.response);
|
|
183
225
|
```
|
|
184
226
|
|
package/dist/index.cjs
CHANGED
|
@@ -48,7 +48,7 @@ var HttpClient = class {
|
|
|
48
48
|
headers: {
|
|
49
49
|
"Authorization": `Bearer ${this.apiKey}`,
|
|
50
50
|
"Content-Type": "application/json",
|
|
51
|
-
"User-Agent": "Novapsis-SDK-Node/1.
|
|
51
|
+
"User-Agent": "Novapsis-SDK-Node/1.1.0"
|
|
52
52
|
},
|
|
53
53
|
body: body ? JSON.stringify(body) : void 0,
|
|
54
54
|
signal: controller.signal
|
|
@@ -183,17 +183,33 @@ var WhatsAppService = class {
|
|
|
183
183
|
const res = await this.http.request("GET", "/whatsapp/connections");
|
|
184
184
|
return res.connections;
|
|
185
185
|
}
|
|
186
|
-
/**
|
|
187
|
-
async
|
|
188
|
-
const
|
|
186
|
+
/** Lista las plantillas oficiales de Meta con filtros opcionales de estado y categoría */
|
|
187
|
+
async listTemplates(options = {}) {
|
|
188
|
+
const query = {};
|
|
189
|
+
if (options.status) query.status = options.status;
|
|
190
|
+
if (options.category) query.category = options.category;
|
|
191
|
+
const res = await this.http.request("GET", "/whatsapp/templates", void 0, query);
|
|
189
192
|
return res.templates;
|
|
190
193
|
}
|
|
191
|
-
/**
|
|
194
|
+
/** Obtiene las plantillas oficiales de Meta aprobadas (alias directo de listTemplates) */
|
|
195
|
+
async getTemplates() {
|
|
196
|
+
return this.listTemplates();
|
|
197
|
+
}
|
|
198
|
+
/** Crea una nueva plantilla oficial de WhatsApp para someter a revisión y aprobación en Meta */
|
|
192
199
|
async createTemplate(options) {
|
|
200
|
+
const templateName = options.template_name || options.name;
|
|
201
|
+
if (!templateName) {
|
|
202
|
+
throw new NovapsisAPIError("Se requiere `name` o `template_name` para crear una plantilla.", "VALIDATION_ERROR", 400);
|
|
203
|
+
}
|
|
204
|
+
const components = options.components || (options.bodyText ? [{ type: "BODY", text: options.bodyText }] : []);
|
|
193
205
|
return this.http.request("POST", "/whatsapp/templates", {
|
|
194
|
-
|
|
206
|
+
template_name: templateName,
|
|
207
|
+
display_name: options.displayName || options.display_name,
|
|
195
208
|
category: options.category,
|
|
196
|
-
|
|
209
|
+
language: options.language || "es",
|
|
210
|
+
components,
|
|
211
|
+
connection_id: options.connectionId || options.connection_id,
|
|
212
|
+
message_send_ttl_seconds: options.messageSendTtlSeconds
|
|
197
213
|
});
|
|
198
214
|
}
|
|
199
215
|
/** Lista las campañas masivas de WhatsApp configuradas */
|
|
@@ -218,9 +234,31 @@ var OnboardingService = class {
|
|
|
218
234
|
async createSession(options = {}) {
|
|
219
235
|
return this.http.request("POST", "/onboarding/sessions", {
|
|
220
236
|
client_name: options.clientName,
|
|
237
|
+
company_name: options.companyName,
|
|
221
238
|
redirect_url: options.redirectUrl,
|
|
222
239
|
logo_url: options.logoUrl,
|
|
223
240
|
brand_color: options.brandColor,
|
|
241
|
+
background_color: options.backgroundColor,
|
|
242
|
+
card_background_color: options.cardBackgroundColor,
|
|
243
|
+
card_border_color: options.cardBorderColor,
|
|
244
|
+
text_color: options.textColor,
|
|
245
|
+
text_secondary_color: options.textSecondaryColor,
|
|
246
|
+
button_color: options.buttonColor,
|
|
247
|
+
button_text_color: options.buttonTextColor,
|
|
248
|
+
badge_color: options.badgeColor,
|
|
249
|
+
badge_text_color: options.badgeTextColor,
|
|
250
|
+
title: options.title,
|
|
251
|
+
description: options.description,
|
|
252
|
+
button_text: options.buttonText,
|
|
253
|
+
badge_text: options.badgeText,
|
|
254
|
+
footer_text: options.footerText,
|
|
255
|
+
features: options.features,
|
|
256
|
+
success_title: options.successTitle,
|
|
257
|
+
success_description: options.successDescription,
|
|
258
|
+
success_button_text: options.successButtonText,
|
|
259
|
+
hide_meta_badge: options.hideMetaBadge,
|
|
260
|
+
hide_footer: options.hideFooter,
|
|
261
|
+
expires_in_hours: options.expiresInHours,
|
|
224
262
|
metadata: options.metadata
|
|
225
263
|
});
|
|
226
264
|
}
|
|
@@ -265,8 +303,12 @@ var WebhookService = class {
|
|
|
265
303
|
verifySignature(rawBody, signatureHeader, secret) {
|
|
266
304
|
if (!signatureHeader || !secret || !rawBody) return false;
|
|
267
305
|
try {
|
|
306
|
+
const cleanSig = signatureHeader.startsWith("sha256=") ? signatureHeader.slice(7) : signatureHeader;
|
|
268
307
|
const computed = crypto__default.default.createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
|
|
269
|
-
|
|
308
|
+
const bufA = Buffer.from(computed, "hex");
|
|
309
|
+
const bufB = Buffer.from(cleanSig, "hex");
|
|
310
|
+
if (bufA.length !== bufB.length) return false;
|
|
311
|
+
return crypto__default.default.timingSafeEqual(bufA, bufB);
|
|
270
312
|
} catch {
|
|
271
313
|
return false;
|
|
272
314
|
}
|
|
@@ -287,17 +329,97 @@ var ContactsService = class {
|
|
|
287
329
|
return this.http.request("POST", "/contacts", options);
|
|
288
330
|
}
|
|
289
331
|
};
|
|
332
|
+
var OrganizationService = class {
|
|
333
|
+
constructor(http) {
|
|
334
|
+
this.http = http;
|
|
335
|
+
}
|
|
336
|
+
http;
|
|
337
|
+
/** Obtiene la información y configuración de la organización actual */
|
|
338
|
+
async get() {
|
|
339
|
+
const res = await this.http.request("GET", "/organization");
|
|
340
|
+
return res.organization;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Actualiza la configuración de la organización (cambio de nombre de la app/empresa, zona horaria)
|
|
344
|
+
*/
|
|
345
|
+
async update(options) {
|
|
346
|
+
const res = await this.http.request("PATCH", "/organization", {
|
|
347
|
+
name: options.name,
|
|
348
|
+
timezone: options.timezone
|
|
349
|
+
});
|
|
350
|
+
return res.organization;
|
|
351
|
+
}
|
|
352
|
+
};
|
|
290
353
|
var AIService = class {
|
|
291
354
|
constructor(http) {
|
|
292
355
|
this.http = http;
|
|
293
356
|
}
|
|
294
357
|
http;
|
|
295
|
-
/** Lista los agentes de IA configurados
|
|
358
|
+
/** Lista los agentes de IA configurados en la organización */
|
|
296
359
|
async listAgents() {
|
|
297
360
|
const res = await this.http.request("GET", "/ai/agents");
|
|
298
361
|
return res.agents;
|
|
299
362
|
}
|
|
300
|
-
/**
|
|
363
|
+
/** Obtiene la configuración completa de un agente por su ID */
|
|
364
|
+
async getAgent(agentId) {
|
|
365
|
+
const res = await this.http.request("GET", `/ai/agents/${agentId}`);
|
|
366
|
+
return res.agent;
|
|
367
|
+
}
|
|
368
|
+
/** Crea un nuevo agente de IA para la organización */
|
|
369
|
+
async createAgent(options) {
|
|
370
|
+
const res = await this.http.request("POST", "/ai/agents", {
|
|
371
|
+
name: options.name,
|
|
372
|
+
system_prompt: options.systemPrompt,
|
|
373
|
+
model: options.model,
|
|
374
|
+
mode: options.mode,
|
|
375
|
+
temperature: options.temperature,
|
|
376
|
+
is_active: options.isActive,
|
|
377
|
+
grouping_timeout_seconds: options.groupingTimeoutSeconds
|
|
378
|
+
});
|
|
379
|
+
return res.agent;
|
|
380
|
+
}
|
|
381
|
+
/** Actualiza nombre, prompt de sistema, modelo o configuración de un agente */
|
|
382
|
+
async updateAgent(agentId, options) {
|
|
383
|
+
const res = await this.http.request("PATCH", `/ai/agents/${agentId}`, {
|
|
384
|
+
name: options.name,
|
|
385
|
+
system_prompt: options.systemPrompt,
|
|
386
|
+
model: options.model,
|
|
387
|
+
mode: options.mode,
|
|
388
|
+
temperature: options.temperature,
|
|
389
|
+
is_active: options.isActive,
|
|
390
|
+
grouping_timeout_seconds: options.groupingTimeoutSeconds
|
|
391
|
+
});
|
|
392
|
+
return res.agent;
|
|
393
|
+
}
|
|
394
|
+
/** Consulta el horario de atención configurado para el agente y la zona horaria */
|
|
395
|
+
async getSchedule(agentId) {
|
|
396
|
+
return this.http.request("GET", `/ai/agents/${agentId}/schedule`);
|
|
397
|
+
}
|
|
398
|
+
/** Configura o reemplaza el horario de atención activa del agente */
|
|
399
|
+
async setSchedule(agentId, options) {
|
|
400
|
+
return this.http.request("PUT", `/ai/agents/${agentId}/schedule`, {
|
|
401
|
+
days: options.days,
|
|
402
|
+
active_from: options.activeFrom,
|
|
403
|
+
active_until: options.activeUntil,
|
|
404
|
+
name: options.name,
|
|
405
|
+
is_active: options.isActive
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
/** Lista los documentos de la base de conocimiento RAG asociados al agente */
|
|
409
|
+
async listKnowledge(agentId) {
|
|
410
|
+
const res = await this.http.request("GET", `/ai/agents/${agentId}/knowledge`);
|
|
411
|
+
return res.documents;
|
|
412
|
+
}
|
|
413
|
+
/** Ingesta y vectoriza nuevo conocimiento en texto plano directamente al agente */
|
|
414
|
+
async addKnowledge(agentId, options) {
|
|
415
|
+
const res = await this.http.request("POST", `/ai/agents/${agentId}/knowledge`, {
|
|
416
|
+
title: options.title,
|
|
417
|
+
content: options.content,
|
|
418
|
+
description: options.description
|
|
419
|
+
});
|
|
420
|
+
return res.document;
|
|
421
|
+
}
|
|
422
|
+
/** Ejecuta una consulta conversacional contra el agente y su base de conocimiento RAG */
|
|
301
423
|
async execute(options) {
|
|
302
424
|
return this.http.request("POST", `/ai/agents/${options.agentId}/execute`, {
|
|
303
425
|
message: options.message
|
|
@@ -306,6 +428,8 @@ var AIService = class {
|
|
|
306
428
|
};
|
|
307
429
|
var Novapsis = class {
|
|
308
430
|
http;
|
|
431
|
+
/** Métodos para ajustes de la organización y cambio de nombre de la app */
|
|
432
|
+
organization;
|
|
309
433
|
/** Métodos para envíos y operaciones de WhatsApp */
|
|
310
434
|
whatsapp;
|
|
311
435
|
/** Métodos para onboarding hosted y vinculación B2B */
|
|
@@ -314,13 +438,14 @@ var Novapsis = class {
|
|
|
314
438
|
webhooks;
|
|
315
439
|
/** Métodos para contactos del CRM */
|
|
316
440
|
contacts;
|
|
317
|
-
/** Métodos para Agentes de Inteligencia Artificial */
|
|
441
|
+
/** Métodos para Agentes de Inteligencia Artificial (prompts, RAG, horarios) */
|
|
318
442
|
ai;
|
|
319
443
|
constructor(options) {
|
|
320
444
|
if (!options.apiKey) {
|
|
321
445
|
throw new NovapsisAPIError("Se requiere una apiKey v\xE1lida para inicializar el cliente de Novapsis.", "CONFIG_ERROR", 400);
|
|
322
446
|
}
|
|
323
447
|
this.http = new HttpClient(options);
|
|
448
|
+
this.organization = new OrganizationService(this.http);
|
|
324
449
|
this.whatsapp = new WhatsAppService(this.http);
|
|
325
450
|
this.onboarding = new OnboardingService(this.http);
|
|
326
451
|
this.webhooks = new WebhookService(this.http);
|
|
@@ -336,7 +461,7 @@ var index_default = Novapsis;
|
|
|
336
461
|
* Universal typed client for WhatsApp Business Cloud API, Hosted Onboarding,
|
|
337
462
|
* CRM, AI Agents and HMAC Webhook Verification.
|
|
338
463
|
*
|
|
339
|
-
* @version 1.
|
|
464
|
+
* @version 1.1.0
|
|
340
465
|
* @author Novapsis Technologies
|
|
341
466
|
* @license MIT
|
|
342
467
|
* ══════════════════════════════════════════════════════════════════════════════
|
|
@@ -347,6 +472,7 @@ exports.ContactsService = ContactsService;
|
|
|
347
472
|
exports.Novapsis = Novapsis;
|
|
348
473
|
exports.NovapsisAPIError = NovapsisAPIError;
|
|
349
474
|
exports.OnboardingService = OnboardingService;
|
|
475
|
+
exports.OrganizationService = OrganizationService;
|
|
350
476
|
exports.WebhookService = WebhookService;
|
|
351
477
|
exports.WhatsAppService = WhatsAppService;
|
|
352
478
|
exports.default = index_default;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["crypto"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * novapsis - Official TypeScript / JavaScript SDK\n * ══════════════════════════════════════════════════════════════════════════════\n * Official SDK for Novapsis SM.\n * Universal typed client for WhatsApp Business Cloud API, Hosted Onboarding,\n * CRM, AI Agents and HMAC Webhook Verification.\n *\n * @version 1.0.0\n * @author Novapsis Technologies\n * @license MIT\n * ══════════════════════════════════════════════════════════════════════════════\n */\n\nimport crypto from 'crypto';\n\n// ── TYPES & DEFINITIONS ──────────────────────────────────────────────────────\n\nexport interface NovapsisClientOptions {\n /** Clave de API de Novapsis (empieza por nvs_live_ o nvs_test_) */\n apiKey: string;\n /** URL base de la API (por defecto: https://app.novapsis.com) */\n baseUrl?: string;\n /** Timeout en milisegundos para peticiones HTTP (por defecto: 15000) */\n timeoutMs?: number;\n /** Número máximo de reintentos automáticos ante fallos de red transitorios (por defecto: 2) */\n maxRetries?: number;\n}\n\nexport interface APIResponse<T = any> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: any;\n };\n}\n\nexport class NovapsisAPIError extends Error {\n public readonly code: string;\n public readonly status: number;\n public readonly details?: any;\n\n constructor(message: string, code = 'API_ERROR', status = 500, details?: any) {\n super(message);\n this.name = 'NovapsisAPIError';\n this.code = code;\n this.status = status;\n this.details = details;\n }\n}\n\n// ── WHATSAPP TYPES ───────────────────────────────────────────────────────────\n\nexport interface SendBaseOptions {\n /** Número destinatario con código de país, sin '+' ni espacios (ej: '34600112233') */\n to: string;\n /** UUID de la conexión o Phone Number ID de Meta desde el cual enviar. Si se omite, usa la línea principal. */\n connectionId?: string;\n}\n\nexport interface SendTextOptions extends SendBaseOptions {\n /** Cuerpo del mensaje de texto */\n text: string;\n /** Si es true, genera vista previa de los enlaces web incluidos en el texto */\n previewUrl?: boolean;\n}\n\nexport interface SendImageOptions extends SendBaseOptions {\n /** URL HTTPS pública de la imagen (JPG, PNG, WebP) */\n imageUrl: string;\n /** Pie de foto opcional */\n caption?: string;\n}\n\nexport interface SendAudioOptions extends SendBaseOptions {\n /** URL HTTPS pública del archivo de audio (MP3, AAC, OGG, M4A) */\n audioUrl: string;\n}\n\nexport interface SendDocumentOptions extends SendBaseOptions {\n /** URL HTTPS pública del documento o PDF */\n documentUrl: string;\n /** Nombre visible del archivo (ej: 'factura_2026.pdf') */\n filename?: string;\n /** Descripción o pie opcional */\n caption?: string;\n}\n\nexport interface SendVideoOptions extends SendBaseOptions {\n /** URL HTTPS pública del video (MP4, 3GP) */\n videoUrl: string;\n /** Pie de video opcional */\n caption?: string;\n}\n\nexport interface SendLocationOptions extends SendBaseOptions {\n /** Coordenada de latitud decimal (ej: 40.416775) */\n latitude: number | string;\n /** Coordenada de longitud decimal (ej: -3.703790) */\n longitude: number | string;\n /** Nombre del lugar o establecimiento (ej: 'Sede Central Madrid') */\n name?: string;\n /** Dirección postal completa */\n address?: string;\n}\n\nexport interface SendContactCardOptions extends SendBaseOptions {\n /** Nombre completo del contacto a compartir */\n name: string;\n /** Número de teléfono del contacto compartido */\n phone: string;\n}\n\nexport interface SendTemplateOptions extends SendBaseOptions {\n /** Nombre exacto de la plantilla aprobada en Meta */\n templateName: string;\n /** Código de idioma (por defecto: 'es') */\n languageCode?: string;\n /** Componentes y variables dinámicas de la plantilla */\n components?: Array<{\n type: 'header' | 'body' | 'button';\n sub_type?: string;\n index?: string | number;\n parameters?: Array<{\n type: 'text' | 'image' | 'document' | 'video' | 'currency' | 'date_time';\n text?: string;\n [key: string]: any;\n }>;\n }>;\n}\n\nexport interface SendMessageResult {\n message_id: string;\n recipient: string;\n type: string;\n status: string;\n conversation_id: string | null;\n}\n\nexport interface WhatsAppConnection {\n id: string;\n display_name: string;\n phone_number: string | null;\n phone_number_id: string;\n verified_name: string | null;\n status: string;\n webhook_subscribed: boolean;\n}\n\nexport interface WhatsAppTemplate {\n id: string;\n name: string;\n category: string;\n language: string;\n status: string;\n components: any[];\n}\n\n// ── ONBOARDING TYPES ─────────────────────────────────────────────────────────\n\nexport interface CreateOnboardingSessionOptions {\n /** Nombre de la empresa, cliente o sede a mostrar en la pantalla de conexión */\n clientName?: string;\n /** URL de retorno a la que redirigir al usuario cuando vincule su WhatsApp */\n redirectUrl?: string;\n /** URL del logotipo de la empresa cliente para marca blanca */\n logoUrl?: string;\n /** Color hexadecimal corporativo para la interfaz de conexión (ej: '#0ea5e9') */\n brandColor?: string;\n /** Metadata personalizada para tracking en tu CRM */\n metadata?: Record<string, any>;\n}\n\nexport interface OnboardingSession {\n id: string;\n session_id: string;\n session_url: string;\n status: 'started' | 'completed' | 'expired' | 'failed';\n expires_at: string;\n created_at: string;\n}\n\n// ── WEBHOOK TYPES ────────────────────────────────────────────────────────────\n\nexport type NovapsisWebhookEvent =\n | 'whatsapp.message_received'\n | 'whatsapp.message_sent'\n | 'whatsapp.connected'\n | 'conversation.started'\n | 'lead.completed'\n | 'call.completed'\n | 'review.received'\n | '*';\n\nexport interface CreateWebhookSubscriptionOptions {\n /** Nombre descriptivo de la suscripción (ej: 'CRM Sincronizador') */\n name: string;\n /** URL HTTPS de tu backend que recibirá los eventos POST */\n url: string;\n /** Lista de eventos a escuchar */\n events: NovapsisWebhookEvent[];\n /** Secreto opcional para firma HMAC. Si se omite, Novapsis generará uno automáticamente. */\n secret?: string;\n}\n\nexport interface WebhookSubscription {\n id: string;\n name: string;\n url: string;\n events: string[];\n secret: string;\n is_active: boolean;\n created_at: string;\n}\n\nexport interface InboundWebhookPayload<T = any> {\n event: NovapsisWebhookEvent;\n timestamp: string;\n organization_id: string;\n data: T;\n}\n\n// ── CRM & CONTACTS TYPES ─────────────────────────────────────────────────────\n\nexport interface UpsertContactOptions {\n phone: string;\n name?: string;\n email?: string;\n tags?: string[];\n metadata?: Record<string, any>;\n}\n\nexport interface Contact {\n id: string;\n phone: string;\n name: string | null;\n email: string | null;\n tags: string[];\n created_at: string;\n}\n\n// ── INTERNAL HTTP CLIENT ────────────────────────────────────────────────────\n\nclass HttpClient {\n private apiKey: string;\n private baseUrl: string;\n private timeoutMs: number;\n private maxRetries: number;\n\n constructor(options: NovapsisClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl || 'https://app.novapsis.com').replace(/\\/+$/, '');\n this.timeoutMs = options.timeoutMs || 15000;\n this.maxRetries = options.maxRetries ?? 2;\n }\n\n async request<T>(method: string, path: string, body?: any, query?: Record<string, string>): Promise<T> {\n let url = `${this.baseUrl}/api/v1${path.startsWith('/') ? path : `/${path}`}`;\n if (query && Object.keys(query).length > 0) {\n const qs = new URLSearchParams(query).toString();\n url += `?${qs}`;\n }\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'Novapsis-SDK-Node/1.0.0',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const data: APIResponse<T> = await response.json().catch(() => ({\n success: false,\n error: { code: 'INVALID_JSON_RESPONSE', message: `HTTP ${response.status} Sin cuerpo JSON válido.` },\n }));\n\n if (!response.ok || !data.success) {\n throw new NovapsisAPIError(\n data.error?.message || `Error en petición HTTP ${response.status}`,\n data.error?.code || `HTTP_${response.status}`,\n response.status,\n data.error?.details\n );\n }\n\n return data.data as T;\n } catch (err: any) {\n clearTimeout(timeoutId);\n lastError = err;\n\n // No reintentar errores de validación de cliente 4xx\n if (err instanceof NovapsisAPIError && err.status >= 400 && err.status < 500) {\n throw err;\n }\n\n // Si es el último intento, lanzar el error\n if (attempt === this.maxRetries) {\n break;\n }\n\n // Backoff exponencial: 300ms, 900ms...\n await new Promise((resolve) => setTimeout(resolve, 300 * Math.pow(3, attempt)));\n }\n }\n\n throw lastError || new NovapsisAPIError('Error de red al comunicarse con Novapsis API', 'NETWORK_ERROR', 0);\n }\n}\n\n// ── SDK SERVICES ────────────────────────────────────────────────────────────\n\n/** Servicio para envíos y gestión de WhatsApp Cloud API */\nexport class WhatsAppService {\n constructor(private http: HttpClient) {}\n\n /** Envía un mensaje de texto plano */\n async sendText(options: SendTextOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'text',\n text: options.text,\n });\n }\n\n /** Envía una imagen o fotografía */\n async sendImage(options: SendImageOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'image',\n media_url: options.imageUrl,\n caption: options.caption,\n });\n }\n\n /** Envía un archivo de audio o nota de voz */\n async sendAudio(options: SendAudioOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'audio',\n media_url: options.audioUrl,\n });\n }\n\n /** Envía un documento (PDF, Word, Excel, etc.) con nombre de archivo personalizado */\n async sendDocument(options: SendDocumentOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'document',\n media_url: options.documentUrl,\n filename: options.filename,\n caption: options.caption,\n });\n }\n\n /** Envía un video */\n async sendVideo(options: SendVideoOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'video',\n media_url: options.videoUrl,\n caption: options.caption,\n });\n }\n\n /** Envía una ubicación con coordenadas y dirección en el mapa */\n async sendLocation(options: SendLocationOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'location',\n latitude: options.latitude,\n longitude: options.longitude,\n location_name: options.name,\n location_address: options.address,\n });\n }\n\n /** Envía una tarjeta de contacto (vCard) interactiva */\n async sendContact(options: SendContactCardOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'contacts',\n contact_name: options.name,\n contact_phone: options.phone,\n });\n }\n\n /** Envía una plantilla oficial aprobada por Meta con variables dinámicas */\n async sendTemplate(options: SendTemplateOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'template',\n template_name: options.templateName,\n language_code: options.languageCode || 'es',\n components: options.components || [],\n });\n }\n\n /** Marca un mensaje o chat como leído */\n async markAsRead(options: { to: string; connectionId?: string; messageId?: string }): Promise<any> {\n return this.http.request('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'mark_read',\n message_id: options.messageId,\n });\n }\n\n /** Obtiene la lista de líneas y números de WhatsApp conectados en la organización */\n async listConnections(): Promise<WhatsAppConnection[]> {\n const res = await this.http.request<{ connections: WhatsAppConnection[] }>('GET', '/whatsapp/connections');\n return res.connections;\n }\n\n /** Obtiene las plantillas oficiales de Meta aprobadas */\n async getTemplates(): Promise<WhatsAppTemplate[]> {\n const res = await this.http.request<{ templates: WhatsAppTemplate[] }>('GET', '/whatsapp/templates');\n return res.templates;\n }\n\n /** Crea una nueva plantilla para enviar a revisión a Meta */\n async createTemplate(options: {\n name: string;\n category: 'MARKETING' | 'UTILITY' | 'AUTHENTICATION';\n bodyText: string;\n }): Promise<any> {\n return this.http.request('POST', '/whatsapp/templates', {\n name: options.name,\n category: options.category,\n components: [{ type: 'BODY', text: options.bodyText }],\n });\n }\n\n /** Lista las campañas masivas de WhatsApp configuradas */\n async listCampaigns(): Promise<any[]> {\n const res = await this.http.request<{ campaigns: any[] }>('GET', '/whatsapp/campaigns');\n return res.campaigns;\n }\n\n /** Ejecuta una campaña masiva */\n async executeCampaign(campaignId: string): Promise<any> {\n return this.http.request('POST', `/whatsapp/campaigns/${campaignId}/execute`);\n }\n}\n\n/** Servicio para onboarding y conexión de WhatsApp de clientes B2B (Marca Blanca) */\nexport class OnboardingService {\n constructor(private http: HttpClient) {}\n\n /**\n * Crea una sesión de conexión hosted para que un cliente o sede vincule su WhatsApp.\n * Devuelve `session_url` que puedes abrir en un modal o popup en tu CRM.\n */\n async createSession(options: CreateOnboardingSessionOptions = {}): Promise<OnboardingSession> {\n return this.http.request<OnboardingSession>('POST', '/onboarding/sessions', {\n client_name: options.clientName,\n redirect_url: options.redirectUrl,\n logo_url: options.logoUrl,\n brand_color: options.brandColor,\n metadata: options.metadata,\n });\n }\n\n /** Consulta el estado de una sesión de onboarding por su ID */\n async getSessionStatus(sessionId: string): Promise<OnboardingSession> {\n return this.http.request<OnboardingSession>('GET', `/onboarding/sessions/${sessionId}`);\n }\n}\n\n/** Servicio para gestionar Webhooks salientes en tiempo real */\nexport class WebhookService {\n constructor(private http: HttpClient) {}\n\n /** Suscribe una URL de tu backend para recibir eventos en tiempo real */\n async subscribe(options: CreateWebhookSubscriptionOptions): Promise<WebhookSubscription> {\n return this.http.request<WebhookSubscription>('POST', '/webhooks/subscriptions', {\n name: options.name,\n url: options.url,\n events: options.events,\n secret: options.secret,\n is_active: true,\n });\n }\n\n /** Lista todas las suscripciones de webhooks activas */\n async list(): Promise<WebhookSubscription[]> {\n const res = await this.http.request<{ subscriptions: WebhookSubscription[] }>('GET', '/webhooks/subscriptions');\n return res.subscriptions;\n }\n\n /** Elimina una suscripción de webhook */\n async delete(webhookId: string): Promise<boolean> {\n const res = await this.http.request<{ success: boolean }>('DELETE', `/webhooks/subscriptions/${webhookId}`);\n return res.success;\n }\n\n /**\n * Valida la firma criptográfica HMAC SHA-256 de un webhook recibido de Novapsis SM.\n * Evita ataques de suplantación garantizando que la petición proviene de Novapsis.\n *\n * @param rawBody - El cuerpo crudo recibido en el request (string sin parsear)\n * @param signatureHeader - El header 'X-Novapsis-Signature'\n * @param secret - Tu secreto de webhook de Novapsis\n */\n verifySignature(rawBody: string, signatureHeader: string | null | undefined, secret: string): boolean {\n if (!signatureHeader || !secret || !rawBody) return false;\n try {\n const computed = crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');\n return crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(signatureHeader));\n } catch {\n return false;\n }\n }\n}\n\n/** Servicio para gestionar Contactos del CRM */\nexport class ContactsService {\n constructor(private http: HttpClient) {}\n\n /** Lista contactos del CRM */\n async list(): Promise<Contact[]> {\n const res = await this.http.request<{ contacts: Contact[] }>('GET', '/contacts');\n return res.contacts;\n }\n\n /** Crea o actualiza un contacto por número de teléfono */\n async upsert(options: UpsertContactOptions): Promise<Contact> {\n return this.http.request<Contact>('POST', '/contacts', options);\n }\n}\n\n/** Servicio para interactuar con Agentes de Inteligencia Artificial */\nexport class AIService {\n constructor(private http: HttpClient) {}\n\n /** Lista los agentes de IA configurados con sus modelos */\n async listAgents(): Promise<any[]> {\n const res = await this.http.request<{ agents: any[] }>('GET', '/ai/agents');\n return res.agents;\n }\n\n /** Ejecuta una consulta contra un agente de IA con su base de conocimiento RAG */\n async execute(options: { agentId: string; message: string }): Promise<{ response: string; tokens_used?: number }> {\n return this.http.request('POST', `/ai/agents/${options.agentId}/execute`, {\n message: options.message,\n });\n }\n}\n\n// ── MAIN CLIENT ─────────────────────────────────────────────────────────────\n\n/**\n * Cliente oficial de Novapsis SM.\n * Punto de entrada principal para interactuar con todos los servicios.\n *\n * @example\n * ```typescript\n * import { Novapsis } from 'novapsis';\n *\n * const client = new Novapsis({\n * apiKey: 'nvs_live_OfnAAb6sEGztGcdbR5IKnhFpPrDJSTq7',\n * });\n *\n * // Enviar mensaje de texto\n * await client.whatsapp.sendText({\n * to: '34600112233',\n * text: '¡Hola desde Novapsis SDK!'\n * });\n * ```\n */\nexport class Novapsis {\n private http: HttpClient;\n\n /** Métodos para envíos y operaciones de WhatsApp */\n public readonly whatsapp: WhatsAppService;\n /** Métodos para onboarding hosted y vinculación B2B */\n public readonly onboarding: OnboardingService;\n /** Métodos para suscripción y validación de Webhooks */\n public readonly webhooks: WebhookService;\n /** Métodos para contactos del CRM */\n public readonly contacts: ContactsService;\n /** Métodos para Agentes de Inteligencia Artificial */\n public readonly ai: AIService;\n\n constructor(options: NovapsisClientOptions) {\n if (!options.apiKey) {\n throw new NovapsisAPIError('Se requiere una apiKey válida para inicializar el cliente de Novapsis.', 'CONFIG_ERROR', 400);\n }\n this.http = new HttpClient(options);\n this.whatsapp = new WhatsAppService(this.http);\n this.onboarding = new OnboardingService(this.http);\n this.webhooks = new WebhookService(this.http);\n this.contacts = new ContactsService(this.http);\n this.ai = new AIService(this.http);\n }\n}\n\n// Default export\nexport default Novapsis;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["crypto"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * novapsis - Official TypeScript / JavaScript SDK\n * ══════════════════════════════════════════════════════════════════════════════\n * Official SDK for Novapsis SM.\n * Universal typed client for WhatsApp Business Cloud API, Hosted Onboarding,\n * CRM, AI Agents and HMAC Webhook Verification.\n *\n * @version 1.1.0\n * @author Novapsis Technologies\n * @license MIT\n * ══════════════════════════════════════════════════════════════════════════════\n */\n\nimport crypto from 'crypto';\n\n// ── TYPES & DEFINITIONS ──────────────────────────────────────────────────────\n\nexport interface NovapsisClientOptions {\n /** Clave de API de Novapsis (empieza por nvs_live_ o nvs_test_) */\n apiKey: string;\n /** URL base de la API (por defecto: https://app.novapsis.com) */\n baseUrl?: string;\n /** Timeout en milisegundos para peticiones HTTP (por defecto: 15000) */\n timeoutMs?: number;\n /** Número máximo de reintentos automáticos ante fallos de red transitorios (por defecto: 2) */\n maxRetries?: number;\n}\n\nexport interface APIResponse<T = any> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: any;\n };\n}\n\nexport class NovapsisAPIError extends Error {\n public readonly code: string;\n public readonly status: number;\n public readonly details?: any;\n\n constructor(message: string, code = 'API_ERROR', status = 500, details?: any) {\n super(message);\n this.name = 'NovapsisAPIError';\n this.code = code;\n this.status = status;\n this.details = details;\n }\n}\n\n// ── WHATSAPP TYPES ───────────────────────────────────────────────────────────\n\nexport interface SendBaseOptions {\n /** Número destinatario con código de país, sin '+' ni espacios (ej: '34600112233') */\n to: string;\n /** UUID de la conexión o Phone Number ID de Meta desde el cual enviar. Si se omite, usa la línea principal. */\n connectionId?: string;\n}\n\nexport interface SendTextOptions extends SendBaseOptions {\n /** Cuerpo del mensaje de texto */\n text: string;\n /** Si es true, genera vista previa de los enlaces web incluidos en el texto */\n previewUrl?: boolean;\n}\n\nexport interface SendImageOptions extends SendBaseOptions {\n /** URL HTTPS pública de la imagen (JPG, PNG, WebP) */\n imageUrl: string;\n /** Pie de foto opcional */\n caption?: string;\n}\n\nexport interface SendAudioOptions extends SendBaseOptions {\n /** URL HTTPS pública del archivo de audio (MP3, AAC, OGG, M4A) */\n audioUrl: string;\n}\n\nexport interface SendDocumentOptions extends SendBaseOptions {\n /** URL HTTPS pública del documento o PDF */\n documentUrl: string;\n /** Nombre visible del archivo (ej: 'factura_2026.pdf') */\n filename?: string;\n /** Descripción o pie opcional */\n caption?: string;\n}\n\nexport interface SendVideoOptions extends SendBaseOptions {\n /** URL HTTPS pública del video (MP4, 3GP) */\n videoUrl: string;\n /** Pie de video opcional */\n caption?: string;\n}\n\nexport interface SendLocationOptions extends SendBaseOptions {\n /** Coordenada de latitud decimal (ej: 40.416775) */\n latitude: number | string;\n /** Coordenada de longitud decimal (ej: -3.703790) */\n longitude: number | string;\n /** Nombre del lugar o establecimiento (ej: 'Sede Central Madrid') */\n name?: string;\n /** Dirección postal completa */\n address?: string;\n}\n\nexport interface SendContactCardOptions extends SendBaseOptions {\n /** Nombre completo del contacto a compartir */\n name: string;\n /** Número de teléfono del contacto compartido */\n phone: string;\n}\n\nexport interface SendTemplateOptions extends SendBaseOptions {\n /** Nombre exacto de la plantilla aprobada en Meta */\n templateName: string;\n /** Código de idioma (por defecto: 'es') */\n languageCode?: string;\n /** Componentes y variables dinámicas de la plantilla */\n components?: Array<{\n type: 'header' | 'body' | 'button';\n sub_type?: string;\n index?: string | number;\n parameters?: Array<{\n type: 'text' | 'image' | 'document' | 'video' | 'currency' | 'date_time';\n text?: string;\n [key: string]: any;\n }>;\n }>;\n}\n\nexport interface SendMessageResult {\n message_id: string;\n recipient: string;\n connection_id?: string;\n phone_number_id?: string;\n business_phone_number?: string | null;\n type: string;\n status: string;\n conversation_id: string | null;\n}\n\nexport interface WhatsAppConnection {\n id: string;\n display_name: string;\n phone_number: string | null;\n phone_number_id: string;\n waba_id?: string | null;\n verified_name: string | null;\n quality_rating?: string | null;\n status: string;\n webhook_subscribed: boolean;\n created_at?: string;\n}\n\nexport interface WhatsAppTemplate {\n id: string;\n template_name?: string;\n display_name?: string;\n name?: string;\n category: 'MARKETING' | 'UTILITY' | 'AUTHENTICATION' | string;\n language: string;\n status: 'APPROVED' | 'PENDING' | 'REJECTED' | 'PAUSED' | string;\n quality_rating?: string | null;\n components: any[];\n meta_template_id?: string | null;\n rejection_reason?: string | null;\n waba_id?: string | null;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface ListTemplatesOptions {\n /** Filtrar por estado en Meta (ej: 'APPROVED', 'PENDING', 'REJECTED') */\n status?: 'APPROVED' | 'PENDING' | 'REJECTED' | 'PAUSED' | string;\n /** Filtrar por categoría oficial */\n category?: 'MARKETING' | 'UTILITY' | 'AUTHENTICATION' | string;\n}\n\nexport interface CreateTemplateOptions {\n /** Nombre técnico en Meta (solo minúsculas, números y guiones bajos, ej: 'confirmacion_pedido_v1') */\n name?: string;\n template_name?: string;\n /** Nombre descriptivo para el panel */\n displayName?: string;\n display_name?: string;\n /** Categoría oficial de Meta */\n category: 'MARKETING' | 'UTILITY' | 'AUTHENTICATION';\n /** Código de idioma (por defecto: 'es') */\n language?: string;\n /** Componentes según especificación de Meta Graph API (HEADER, BODY, BUTTONS, etc.) */\n components?: any[];\n /** Texto plano del cuerpo si no se envían componentes avanzados */\n bodyText?: string;\n /** ID de conexión de WhatsApp (opcional si la cuenta tiene una sola activa) */\n connectionId?: string;\n connection_id?: string;\n /** TTL de entrega en segundos (opcional) */\n messageSendTtlSeconds?: number;\n}\n\n// ── ORGANIZATION & SETTINGS TYPES ───────────────────────────────────────────\n\nexport interface OrganizationDetails {\n id: string;\n name: string;\n timezone: string;\n tier: string;\n created_at: string;\n updated_at: string;\n}\n\nexport interface UpdateOrganizationOptions {\n /** Nombre de la empresa o aplicación (cambio de nombre / settings de la app) */\n name?: string;\n /** Zona horaria IANA (ej: 'Europe/Madrid', 'America/Bogota', 'America/Mexico_City') */\n timezone?: string;\n}\n\n// ── AI AGENTS & RAG TYPES ───────────────────────────────────────────────────\n\nexport interface AgentDetails {\n id: string;\n name: string;\n system_prompt: string;\n model: string;\n mode: 'agent' | 'rag' | 'both';\n temperature: number;\n is_active: boolean;\n grouping_timeout_seconds: number;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface CreateAgentOptions {\n /** Nombre del agente de IA (ej: 'Asistente Ventas') */\n name: string;\n /** Prompt de sistema e instrucciones de comportamiento */\n systemPrompt: string;\n /** Modelo de IA a utilizar (por defecto: 'gemini-2.5-flash') */\n model?: string;\n /** Modo de operación: 'agent', 'rag' o 'both' */\n mode?: 'agent' | 'rag' | 'both';\n /** Creatividad (temperatura 0.0 - 1.0) */\n temperature?: number;\n /** Si el agente está activo respondiendo chats */\n isActive?: boolean;\n /** Ventana de agrupación de mensajes en segundos */\n groupingTimeoutSeconds?: number;\n}\n\nexport interface UpdateAgentOptions {\n /** Nuevo nombre del agente (cambio de nombre del bot) */\n name?: string;\n /** Nuevo prompt de sistema */\n systemPrompt?: string;\n /** Modelo de IA */\n model?: string;\n /** Modo de operación */\n mode?: 'agent' | 'rag' | 'both';\n /** Creatividad */\n temperature?: number;\n /** Estado activo o inactivo */\n isActive?: boolean;\n /** Ventana de agrupación en segundos */\n groupingTimeoutSeconds?: number;\n}\n\nexport interface AgentSchedule {\n id: string;\n agent_id: string;\n name: string;\n days: number[]; // 1=Lunes, 7=Domingo\n active_from: string; // \"HH:MM\"\n active_until: string; // \"HH:MM\"\n is_active: boolean;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface SetScheduleOptions {\n /** Días activos: 1=Lunes, 2=Martes, 3=Miércoles, 4=Jueves, 5=Viernes, 6=Sábado, 7=Domingo */\n days: number[];\n /** Hora de apertura en formato HH:MM (ej: '09:00') */\n activeFrom: string;\n /** Hora de cierre en formato HH:MM (ej: '19:00') */\n activeUntil: string;\n /** Nombre de la franja horaria */\n name?: string;\n /** Si el horario está habilitado */\n isActive?: boolean;\n}\n\nexport interface KnowledgeDocument {\n id: string;\n title: string;\n description?: string | null;\n file_type: string;\n total_chunks?: number;\n created_at: string;\n updated_at?: string;\n}\n\nexport interface AddKnowledgeOptions {\n /** Título o tema del documento (ej: 'Políticas de garantía y devoluciones') */\n title: string;\n /** Contenido en texto plano a vectorizar para RAG */\n content: string;\n /** Descripción contextual */\n description?: string;\n}\n\n// ── ONBOARDING TYPES ─────────────────────────────────────────────────────────\n\nexport interface OnboardingFeatureBullet {\n title: string;\n description?: string;\n}\n\nexport interface CreateOnboardingSessionOptions {\n /** Nombre del cliente, empresa o sede (ej: 'Clínica Dental') */\n clientName?: string;\n /** Nombre corporativo visible */\n companyName?: string;\n /** URL de retorno tras conectar exitosamente con WhatsApp */\n redirectUrl?: string;\n /** URL pública del logotipo corporativo para marca blanca (PNG, SVG, JPG) */\n logoUrl?: string;\n\n // ── Personalización de Estilos y Colores (Marca Blanca) ──\n /** Color de acento principal (ej: '#0ea5e9') */\n brandColor?: string;\n /** Color de fondo general de la pantalla (ej: '#0f172a' o '#ffffff') */\n backgroundColor?: string;\n /** Color de fondo de la tarjeta/modal (ej: '#1e293b' o '#ffffff') */\n cardBackgroundColor?: string;\n /** Color del borde de la tarjeta (ej: 'rgba(255,255,255,0.1)') */\n cardBorderColor?: string;\n /** Color de los títulos y textos principales (ej: '#ffffff' o '#0f172a') */\n textColor?: string;\n /** Color de los textos secundarios y descripciones (ej: '#94a3b8') */\n textSecondaryColor?: string;\n /** Color de fondo del botón de acción (por defecto usa brandColor o verde WhatsApp) */\n buttonColor?: string;\n /** Color del texto dentro del botón de acción */\n buttonTextColor?: string;\n /** Color de fondo de la píldora superior */\n badgeColor?: string;\n /** Color del texto de la píldora superior */\n badgeTextColor?: string;\n\n // ── Personalización de Copys y Textos ──\n /** Título principal (por defecto: 'Conecta WhatsApp Business') */\n title?: string;\n /** Texto explicativo debajo del título */\n description?: string;\n /** Texto del botón principal (por defecto: 'Conectar con WhatsApp') */\n buttonText?: string;\n /** Texto de la píldora superior (por defecto: 'Vinculación Oficial', o '' para ocultar) */\n badgeText?: string;\n /** Texto legal o footer de la tarjeta */\n footerText?: string;\n /** Viñetas de beneficios o false para ocultar la caja */\n features?: OnboardingFeatureBullet[] | boolean;\n /** Título de la pantalla de éxito tras vincular */\n successTitle?: string;\n /** Descripción de la pantalla de éxito */\n successDescription?: string;\n /** Texto del botón en la pantalla de éxito */\n successButtonText?: string;\n /** Si es true, oculta el badge 'Meta Tech Provider Verified' del encabezado */\n hideMetaBadge?: boolean;\n /** Si es true, oculta el pie de página de copyright */\n hideFooter?: boolean;\n\n /** Horas de validez de la sesión antes de expirar (por defecto: 168 = 7 días) */\n expiresInHours?: number;\n /** Metadata personalizada para tracking en tu CRM */\n metadata?: Record<string, any>;\n}\n\nexport interface OnboardingSession {\n id: string;\n session_id: string;\n session_url: string;\n status: 'started' | 'completed' | 'expired' | 'failed';\n expires_at: string;\n created_at: string;\n}\n\n// ── WEBHOOK TYPES ────────────────────────────────────────────────────────────\n\nexport type NovapsisWebhookEvent =\n | 'whatsapp.message_received'\n | 'whatsapp.message_sent'\n | 'whatsapp.connected'\n | 'conversation.started'\n | 'lead.completed'\n | 'call.completed'\n | 'review.received'\n | '*';\n\nexport interface WhatsAppMessageReceivedData {\n conversation_id: string;\n message_id: string;\n external_message_id?: string | null;\n platform: 'whatsapp' | string;\n\n // ── Datos completos de la línea receptora (Empresa) ──\n connection_id: string;\n phone_number_id: string;\n waba_id?: string | null;\n business_phone_number: string | null;\n business_name?: string | null;\n connection_name?: string | null;\n to: string | null;\n\n // ── Datos del cliente emisor ──\n from: string;\n external_user_id: string;\n external_user_name: string;\n\n // ── Contenido y Multimedia ──\n content: string;\n media_type: 'image' | 'audio' | 'video' | 'document' | null;\n media_url: string | null;\n timestamp: string;\n}\n\nexport interface WhatsAppMessageSentData {\n conversation_id: string;\n message_id: string;\n platform: 'whatsapp' | string;\n\n // ── Datos completos de la línea emisora (Empresa) ──\n connection_id: string;\n phone_number_id: string;\n waba_id?: string | null;\n business_phone_number: string | null;\n business_name?: string | null;\n connection_name?: string | null;\n from: string | null;\n\n // ── Datos del destinatario (Cliente) ──\n to: string;\n external_user_id: string;\n\n role: 'assistant';\n sender_type: 'ai' | 'human';\n content: string;\n media_type?: string | null;\n media_url?: string | null;\n timestamp: string;\n}\n\nexport interface CreateWebhookSubscriptionOptions {\n /** Nombre descriptivo de la suscripción (ej: 'CRM Sincronizador') */\n name: string;\n /** URL HTTPS de tu backend que recibirá los eventos POST */\n url: string;\n /** Lista de eventos a escuchar */\n events: NovapsisWebhookEvent[];\n /** Secreto opcional para firma HMAC. Si se omite, Novapsis generará uno automáticamente. */\n secret?: string;\n}\n\nexport interface WebhookSubscription {\n id: string;\n name: string;\n url: string;\n events: string[];\n secret: string;\n is_active: boolean;\n created_at: string;\n}\n\nexport interface InboundWebhookPayload<T = any> {\n event: NovapsisWebhookEvent;\n timestamp: string;\n organization_id: string;\n data: T;\n}\n\n// ── CRM & CONTACTS TYPES ─────────────────────────────────────────────────────\n\nexport interface UpsertContactOptions {\n phone: string;\n name?: string;\n email?: string;\n tags?: string[];\n metadata?: Record<string, any>;\n}\n\nexport interface Contact {\n id: string;\n phone: string;\n name: string | null;\n email: string | null;\n tags: string[];\n created_at: string;\n}\n\n// ── INTERNAL HTTP CLIENT ────────────────────────────────────────────────────\n\nclass HttpClient {\n private apiKey: string;\n private baseUrl: string;\n private timeoutMs: number;\n private maxRetries: number;\n\n constructor(options: NovapsisClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl || 'https://app.novapsis.com').replace(/\\/+$/, '');\n this.timeoutMs = options.timeoutMs || 15000;\n this.maxRetries = options.maxRetries ?? 2;\n }\n\n async request<T>(method: string, path: string, body?: any, query?: Record<string, string>): Promise<T> {\n let url = `${this.baseUrl}/api/v1${path.startsWith('/') ? path : `/${path}`}`;\n if (query && Object.keys(query).length > 0) {\n const qs = new URLSearchParams(query).toString();\n url += `?${qs}`;\n }\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'Novapsis-SDK-Node/1.1.0',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const data: APIResponse<T> = await response.json().catch(() => ({\n success: false,\n error: { code: 'INVALID_JSON_RESPONSE', message: `HTTP ${response.status} Sin cuerpo JSON válido.` },\n }));\n\n if (!response.ok || !data.success) {\n throw new NovapsisAPIError(\n data.error?.message || `Error en petición HTTP ${response.status}`,\n data.error?.code || `HTTP_${response.status}`,\n response.status,\n data.error?.details\n );\n }\n\n return data.data as T;\n } catch (err: any) {\n clearTimeout(timeoutId);\n lastError = err;\n\n // No reintentar errores de validación de cliente 4xx\n if (err instanceof NovapsisAPIError && err.status >= 400 && err.status < 500) {\n throw err;\n }\n\n // Si es el último intento, lanzar el error\n if (attempt === this.maxRetries) {\n break;\n }\n\n // Backoff exponencial: 300ms, 900ms...\n await new Promise((resolve) => setTimeout(resolve, 300 * Math.pow(3, attempt)));\n }\n }\n\n throw lastError || new NovapsisAPIError('Error de red al comunicarse con Novapsis API', 'NETWORK_ERROR', 0);\n }\n}\n\n// ── SDK SERVICES ────────────────────────────────────────────────────────────\n\n/** Servicio para envíos y gestión de WhatsApp Cloud API */\nexport class WhatsAppService {\n constructor(private http: HttpClient) {}\n\n /** Envía un mensaje de texto plano */\n async sendText(options: SendTextOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'text',\n text: options.text,\n });\n }\n\n /** Envía una imagen o fotografía */\n async sendImage(options: SendImageOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'image',\n media_url: options.imageUrl,\n caption: options.caption,\n });\n }\n\n /** Envía un archivo de audio o nota de voz */\n async sendAudio(options: SendAudioOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'audio',\n media_url: options.audioUrl,\n });\n }\n\n /** Envía un documento (PDF, Word, Excel, etc.) con nombre de archivo personalizado */\n async sendDocument(options: SendDocumentOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'document',\n media_url: options.documentUrl,\n filename: options.filename,\n caption: options.caption,\n });\n }\n\n /** Envía un video */\n async sendVideo(options: SendVideoOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'video',\n media_url: options.videoUrl,\n caption: options.caption,\n });\n }\n\n /** Envía una ubicación con coordenadas y dirección en el mapa */\n async sendLocation(options: SendLocationOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'location',\n latitude: options.latitude,\n longitude: options.longitude,\n location_name: options.name,\n location_address: options.address,\n });\n }\n\n /** Envía una tarjeta de contacto (vCard) interactiva */\n async sendContact(options: SendContactCardOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'contacts',\n contact_name: options.name,\n contact_phone: options.phone,\n });\n }\n\n /** Envía una plantilla oficial aprobada por Meta con variables dinámicas */\n async sendTemplate(options: SendTemplateOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'template',\n template_name: options.templateName,\n language_code: options.languageCode || 'es',\n components: options.components || [],\n });\n }\n\n /** Marca un mensaje o chat como leído */\n async markAsRead(options: { to: string; connectionId?: string; messageId?: string }): Promise<any> {\n return this.http.request('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'mark_read',\n message_id: options.messageId,\n });\n }\n\n /** Obtiene la lista de líneas y números de WhatsApp conectados en la organización */\n async listConnections(): Promise<WhatsAppConnection[]> {\n const res = await this.http.request<{ connections: WhatsAppConnection[] }>('GET', '/whatsapp/connections');\n return res.connections;\n }\n\n /** Lista las plantillas oficiales de Meta con filtros opcionales de estado y categoría */\n async listTemplates(options: ListTemplatesOptions = {}): Promise<WhatsAppTemplate[]> {\n const query: Record<string, string> = {};\n if (options.status) query.status = options.status;\n if (options.category) query.category = options.category;\n const res = await this.http.request<{ templates: WhatsAppTemplate[] }>('GET', '/whatsapp/templates', undefined, query);\n return res.templates;\n }\n\n /** Obtiene las plantillas oficiales de Meta aprobadas (alias directo de listTemplates) */\n async getTemplates(): Promise<WhatsAppTemplate[]> {\n return this.listTemplates();\n }\n\n /** Crea una nueva plantilla oficial de WhatsApp para someter a revisión y aprobación en Meta */\n async createTemplate(options: CreateTemplateOptions): Promise<{ template: WhatsAppTemplate }> {\n const templateName = options.template_name || options.name;\n if (!templateName) {\n throw new NovapsisAPIError('Se requiere `name` o `template_name` para crear una plantilla.', 'VALIDATION_ERROR', 400);\n }\n const components = options.components || (options.bodyText ? [{ type: 'BODY', text: options.bodyText }] : []);\n\n return this.http.request<{ template: WhatsAppTemplate }>('POST', '/whatsapp/templates', {\n template_name: templateName,\n display_name: options.displayName || options.display_name,\n category: options.category,\n language: options.language || 'es',\n components,\n connection_id: options.connectionId || options.connection_id,\n message_send_ttl_seconds: options.messageSendTtlSeconds,\n });\n }\n\n /** Lista las campañas masivas de WhatsApp configuradas */\n async listCampaigns(): Promise<any[]> {\n const res = await this.http.request<{ campaigns: any[] }>('GET', '/whatsapp/campaigns');\n return res.campaigns;\n }\n\n /** Ejecuta una campaña masiva */\n async executeCampaign(campaignId: string): Promise<any> {\n return this.http.request('POST', `/whatsapp/campaigns/${campaignId}/execute`);\n }\n}\n\n/** Servicio para onboarding y conexión de WhatsApp de clientes B2B (Marca Blanca) */\nexport class OnboardingService {\n constructor(private http: HttpClient) {}\n\n /**\n * Crea una sesión de conexión hosted para que un cliente o sede vincule su WhatsApp.\n * Devuelve `session_url` que puedes abrir en un modal o popup en tu CRM.\n */\n async createSession(options: CreateOnboardingSessionOptions = {}): Promise<OnboardingSession> {\n return this.http.request<OnboardingSession>('POST', '/onboarding/sessions', {\n client_name: options.clientName,\n company_name: options.companyName,\n redirect_url: options.redirectUrl,\n logo_url: options.logoUrl,\n brand_color: options.brandColor,\n background_color: options.backgroundColor,\n card_background_color: options.cardBackgroundColor,\n card_border_color: options.cardBorderColor,\n text_color: options.textColor,\n text_secondary_color: options.textSecondaryColor,\n button_color: options.buttonColor,\n button_text_color: options.buttonTextColor,\n badge_color: options.badgeColor,\n badge_text_color: options.badgeTextColor,\n title: options.title,\n description: options.description,\n button_text: options.buttonText,\n badge_text: options.badgeText,\n footer_text: options.footerText,\n features: options.features,\n success_title: options.successTitle,\n success_description: options.successDescription,\n success_button_text: options.successButtonText,\n hide_meta_badge: options.hideMetaBadge,\n hide_footer: options.hideFooter,\n expires_in_hours: options.expiresInHours,\n metadata: options.metadata,\n });\n }\n\n /** Consulta el estado de una sesión de onboarding por su ID */\n async getSessionStatus(sessionId: string): Promise<OnboardingSession> {\n return this.http.request<OnboardingSession>('GET', `/onboarding/sessions/${sessionId}`);\n }\n}\n\n/** Servicio para gestionar Webhooks salientes en tiempo real */\nexport class WebhookService {\n constructor(private http: HttpClient) {}\n\n /** Suscribe una URL de tu backend para recibir eventos en tiempo real */\n async subscribe(options: CreateWebhookSubscriptionOptions): Promise<WebhookSubscription> {\n return this.http.request<WebhookSubscription>('POST', '/webhooks/subscriptions', {\n name: options.name,\n url: options.url,\n events: options.events,\n secret: options.secret,\n is_active: true,\n });\n }\n\n /** Lista todas las suscripciones de webhooks activas */\n async list(): Promise<WebhookSubscription[]> {\n const res = await this.http.request<{ subscriptions: WebhookSubscription[] }>('GET', '/webhooks/subscriptions');\n return res.subscriptions;\n }\n\n /** Elimina una suscripción de webhook */\n async delete(webhookId: string): Promise<boolean> {\n const res = await this.http.request<{ success: boolean }>('DELETE', `/webhooks/subscriptions/${webhookId}`);\n return res.success;\n }\n\n /**\n * Valida la firma criptográfica HMAC SHA-256 de un webhook recibido de Novapsis SM.\n * Evita ataques de suplantación garantizando que la petición proviene de Novapsis.\n *\n * @param rawBody - El cuerpo crudo recibido en el request (string sin parsear)\n * @param signatureHeader - El header 'X-Novapsis-Signature'\n * @param secret - Tu secreto de webhook de Novapsis\n */\n verifySignature(rawBody: string, signatureHeader: string | null | undefined, secret: string): boolean {\n if (!signatureHeader || !secret || !rawBody) return false;\n try {\n const cleanSig = signatureHeader.startsWith('sha256=')\n ? signatureHeader.slice(7)\n : signatureHeader;\n const computed = crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');\n const bufA = Buffer.from(computed, 'hex');\n const bufB = Buffer.from(cleanSig, 'hex');\n if (bufA.length !== bufB.length) return false;\n return crypto.timingSafeEqual(bufA, bufB);\n } catch {\n return false;\n }\n }\n}\n\n/** Servicio para gestionar Contactos del CRM */\nexport class ContactsService {\n constructor(private http: HttpClient) {}\n\n /** Lista contactos del CRM */\n async list(): Promise<Contact[]> {\n const res = await this.http.request<{ contacts: Contact[] }>('GET', '/contacts');\n return res.contacts;\n }\n\n /** Crea o actualiza un contacto por número de teléfono */\n async upsert(options: UpsertContactOptions): Promise<Contact> {\n return this.http.request<Contact>('POST', '/contacts', options);\n }\n}\n\n/** Servicio para gestión de la organización y configuración general (Marca / Settings) */\nexport class OrganizationService {\n constructor(private http: HttpClient) {}\n\n /** Obtiene la información y configuración de la organización actual */\n async get(): Promise<OrganizationDetails> {\n const res = await this.http.request<{ organization: OrganizationDetails }>('GET', '/organization');\n return res.organization;\n }\n\n /**\n * Actualiza la configuración de la organización (cambio de nombre de la app/empresa, zona horaria)\n */\n async update(options: UpdateOrganizationOptions): Promise<OrganizationDetails> {\n const res = await this.http.request<{ organization: OrganizationDetails }>('PATCH', '/organization', {\n name: options.name,\n timezone: options.timezone,\n });\n return res.organization;\n }\n}\n\n/** Servicio para interactuar y configurar Agentes de Inteligencia Artificial (Headless AI) */\nexport class AIService {\n constructor(private http: HttpClient) {}\n\n /** Lista los agentes de IA configurados en la organización */\n async listAgents(): Promise<AgentDetails[]> {\n const res = await this.http.request<{ agents: AgentDetails[] }>('GET', '/ai/agents');\n return res.agents;\n }\n\n /** Obtiene la configuración completa de un agente por su ID */\n async getAgent(agentId: string): Promise<AgentDetails> {\n const res = await this.http.request<{ agent: AgentDetails }>('GET', `/ai/agents/${agentId}`);\n return res.agent;\n }\n\n /** Crea un nuevo agente de IA para la organización */\n async createAgent(options: CreateAgentOptions): Promise<AgentDetails> {\n const res = await this.http.request<{ agent: AgentDetails }>('POST', '/ai/agents', {\n name: options.name,\n system_prompt: options.systemPrompt,\n model: options.model,\n mode: options.mode,\n temperature: options.temperature,\n is_active: options.isActive,\n grouping_timeout_seconds: options.groupingTimeoutSeconds,\n });\n return res.agent;\n }\n\n /** Actualiza nombre, prompt de sistema, modelo o configuración de un agente */\n async updateAgent(agentId: string, options: UpdateAgentOptions): Promise<AgentDetails> {\n const res = await this.http.request<{ agent: AgentDetails }>('PATCH', `/ai/agents/${agentId}`, {\n name: options.name,\n system_prompt: options.systemPrompt,\n model: options.model,\n mode: options.mode,\n temperature: options.temperature,\n is_active: options.isActive,\n grouping_timeout_seconds: options.groupingTimeoutSeconds,\n });\n return res.agent;\n }\n\n /** Consulta el horario de atención configurado para el agente y la zona horaria */\n async getSchedule(agentId: string): Promise<{ schedule: AgentSchedule | null; timezone: string }> {\n return this.http.request<{ schedule: AgentSchedule | null; timezone: string }>('GET', `/ai/agents/${agentId}/schedule`);\n }\n\n /** Configura o reemplaza el horario de atención activa del agente */\n async setSchedule(agentId: string, options: SetScheduleOptions): Promise<{ schedule: AgentSchedule; timezone: string }> {\n return this.http.request<{ schedule: AgentSchedule; timezone: string }>('PUT', `/ai/agents/${agentId}/schedule`, {\n days: options.days,\n active_from: options.activeFrom,\n active_until: options.activeUntil,\n name: options.name,\n is_active: options.isActive,\n });\n }\n\n /** Lista los documentos de la base de conocimiento RAG asociados al agente */\n async listKnowledge(agentId: string): Promise<KnowledgeDocument[]> {\n const res = await this.http.request<{ documents: KnowledgeDocument[] }>('GET', `/ai/agents/${agentId}/knowledge`);\n return res.documents;\n }\n\n /** Ingesta y vectoriza nuevo conocimiento en texto plano directamente al agente */\n async addKnowledge(agentId: string, options: AddKnowledgeOptions): Promise<KnowledgeDocument> {\n const res = await this.http.request<{ document: KnowledgeDocument }>('POST', `/ai/agents/${agentId}/knowledge`, {\n title: options.title,\n content: options.content,\n description: options.description,\n });\n return res.document;\n }\n\n /** Ejecuta una consulta conversacional contra el agente y su base de conocimiento RAG */\n async execute(options: { agentId: string; message: string }): Promise<{ response: string; tokens_used?: number }> {\n return this.http.request('POST', `/ai/agents/${options.agentId}/execute`, {\n message: options.message,\n });\n }\n}\n\n// ── MAIN CLIENT ─────────────────────────────────────────────────────────────\n\n/**\n * Cliente oficial de Novapsis SM.\n * Punto de entrada principal para interactuar con todos los servicios.\n *\n * @example\n * ```typescript\n * import { Novapsis } from 'novapsis';\n *\n * const client = new Novapsis({\n * apiKey: 'nvs_live_sample_abcdef1234567890',\n * });\n *\n * // Enviar mensaje de texto\n * await client.whatsapp.sendText({\n * to: '34600112233',\n * text: '¡Hola desde Novapsis SDK!'\n * });\n * ```\n */\nexport class Novapsis {\n private http: HttpClient;\n\n /** Métodos para ajustes de la organización y cambio de nombre de la app */\n public readonly organization: OrganizationService;\n /** Métodos para envíos y operaciones de WhatsApp */\n public readonly whatsapp: WhatsAppService;\n /** Métodos para onboarding hosted y vinculación B2B */\n public readonly onboarding: OnboardingService;\n /** Métodos para suscripción y validación de Webhooks */\n public readonly webhooks: WebhookService;\n /** Métodos para contactos del CRM */\n public readonly contacts: ContactsService;\n /** Métodos para Agentes de Inteligencia Artificial (prompts, RAG, horarios) */\n public readonly ai: AIService;\n\n constructor(options: NovapsisClientOptions) {\n if (!options.apiKey) {\n throw new NovapsisAPIError('Se requiere una apiKey válida para inicializar el cliente de Novapsis.', 'CONFIG_ERROR', 400);\n }\n this.http = new HttpClient(options);\n this.organization = new OrganizationService(this.http);\n this.whatsapp = new WhatsAppService(this.http);\n this.onboarding = new OnboardingService(this.http);\n this.webhooks = new WebhookService(this.http);\n this.contacts = new ContactsService(this.http);\n this.ai = new AIService(this.http);\n }\n}\n\n// Default export\nexport default Novapsis;\n"]}
|