@astermind/cybernetic-chatbot-client 2.2.74 → 2.3.4

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.
@@ -216,6 +216,89 @@
216
216
  }
217
217
  }
218
218
 
219
+ // src/SalesApiClient.ts
220
+ // API client for Sales Agent external endpoints (/api/external/sales/*)
221
+ /**
222
+ * Client for the Sales Agent external API endpoints.
223
+ * Handles visitor tracking, sales-aware chat, and lead capture.
224
+ */
225
+ class SalesApiClient {
226
+ constructor(apiUrl, apiKey) {
227
+ // Normalize base URL (strip trailing slash)
228
+ this.baseUrl = apiUrl.replace(/\/$/, '');
229
+ this.apiKey = apiKey;
230
+ }
231
+ /**
232
+ * Initialize or resume a visitor session.
233
+ * Call on first page load to register the visitor with the backend.
234
+ */
235
+ async initVisitor(visitorId, pageUrl, referrer, utmParams) {
236
+ return this.post('visitor/init', {
237
+ visitorId,
238
+ pageUrl,
239
+ referrer,
240
+ utmParams,
241
+ });
242
+ }
243
+ /**
244
+ * Track a page view event.
245
+ * Call when the visitor navigates to a new page.
246
+ */
247
+ async trackPageView(visitorId, url, title, timeOnPageMs, scrollDepth) {
248
+ return this.post('visitor/pageview', {
249
+ visitorId,
250
+ url,
251
+ title,
252
+ timeOnPageMs,
253
+ scrollDepth,
254
+ });
255
+ }
256
+ /**
257
+ * Associate a visitor with identity data (email, name, etc.).
258
+ * Call when the visitor provides identifying information.
259
+ */
260
+ async identifyVisitor(visitorId, data) {
261
+ return this.post('visitor/identify', {
262
+ visitorId,
263
+ ...data,
264
+ });
265
+ }
266
+ /**
267
+ * Send a sales-aware chat message.
268
+ * Returns the assistant reply along with sales context (lead score, CTA buttons, etc.).
269
+ */
270
+ async salesChat(message, options = {}) {
271
+ return this.post('chat', {
272
+ message,
273
+ ...options,
274
+ });
275
+ }
276
+ /**
277
+ * Submit a lead capture form.
278
+ * Creates or updates a lead record in the backend.
279
+ */
280
+ async captureLeadForm(data) {
281
+ return this.post('lead/capture', data);
282
+ }
283
+ // ─── Private ─────────────────────────────────────────────────────────────────
284
+ async post(path, body) {
285
+ const url = `${this.baseUrl}/api/external/sales/${path}`;
286
+ const response = await fetch(url, {
287
+ method: 'POST',
288
+ headers: {
289
+ 'Content-Type': 'application/json',
290
+ 'X-Api-Key': this.apiKey,
291
+ },
292
+ body: JSON.stringify(body),
293
+ });
294
+ if (!response.ok) {
295
+ const err = await response.json().catch(() => ({ error: 'Unknown error' }));
296
+ throw new Error(err.error || `Sales API error: ${response.status}`);
297
+ }
298
+ return response.json();
299
+ }
300
+ }
301
+
219
302
  const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
220
303
 
221
304
  let idbProxyableTypes;
@@ -2186,8 +2269,10 @@ LJ5AZXvOhHaXdHzMuYKX5BpK4w7TqbPvJ6QPvKmLKvHh1VKcUJ6mJQgJJw==
2186
2269
  /**
2187
2270
  * License enforcement message shown in production when license is invalid
2188
2271
  */
2189
- const LICENSE_WARNING_MESSAGE = '\n\n---\n⚠️ License Notice: Your AsterMind license key needs to be updated. ' +
2190
- 'Please contact support@astermind.ai or visit https://astermind.ai/license to renew your license.';
2272
+ // TODO: Re-enable when license key system is fully implemented
2273
+ // const LICENSE_WARNING_MESSAGE =
2274
+ // '\n\n---\n⚠️ License Notice: Your AsterMind license key needs to be updated. ' +
2275
+ // 'Please contact support@astermind.ai or visit https://astermind.ai/license to renew your license.';
2191
2276
  /**
2192
2277
  * Detect current environment based on URL and other signals
2193
2278
  */
@@ -2255,7 +2340,8 @@ LJ5AZXvOhHaXdHzMuYKX5BpK4w7TqbPvJ6QPvKmLKvHh1VKcUJ6mJQgJJw==
2255
2340
  constructor(config = {}) {
2256
2341
  this.state = null;
2257
2342
  this.verificationPromise = null;
2258
- this.hasLoggedWarning = false;
2343
+ // TODO: Re-enable when license key system is fully implemented
2344
+ // private hasLoggedWarning = false;
2259
2345
  this.loggedMissingFeatures = new Set();
2260
2346
  this.config = config;
2261
2347
  this.environment = config.environment || detectEnvironment();
@@ -2332,25 +2418,30 @@ LJ5AZXvOhHaXdHzMuYKX5BpK4w7TqbPvJ6QPvKmLKvHh1VKcUJ6mJQgJJw==
2332
2418
  * @returns Modified response (or original if license valid)
2333
2419
  */
2334
2420
  processResponse(response) {
2335
- // License not verified yet - allow through
2336
- if (!this.state) {
2337
- return response;
2338
- }
2339
- // Valid license - no modification
2340
- if (this.isValid() && !this.state.inGracePeriod) {
2341
- return response;
2342
- }
2343
- // Handle based on enforcement mode
2344
- if (this.enforcementMode === 'soft') {
2345
- // Development: just log warning (once)
2346
- if (!this.hasLoggedWarning) {
2347
- this.logDevelopmentWarning();
2348
- this.hasLoggedWarning = true;
2349
- }
2350
- return response;
2351
- }
2352
- // Production: append warning to response
2353
- return response + LICENSE_WARNING_MESSAGE;
2421
+ // TODO: License enforcement disabled until license key system is fully implemented
2422
+ return response;
2423
+ // // License not verified yet - allow through
2424
+ // if (!this.state) {
2425
+ // return response;
2426
+ // }
2427
+ //
2428
+ // // Valid license - no modification
2429
+ // if (this.isValid() && !this.state.inGracePeriod) {
2430
+ // return response;
2431
+ // }
2432
+ //
2433
+ // // Handle based on enforcement mode
2434
+ // if (this.enforcementMode === 'soft') {
2435
+ // // Development: just log warning (once)
2436
+ // if (!this.hasLoggedWarning) {
2437
+ // this.logDevelopmentWarning();
2438
+ // this.hasLoggedWarning = true;
2439
+ // }
2440
+ // return response;
2441
+ // }
2442
+ //
2443
+ // // Production: append warning to response
2444
+ // return response + LICENSE_WARNING_MESSAGE;
2354
2445
  }
2355
2446
  /**
2356
2447
  * Get a human-readable license status message
@@ -2382,7 +2473,7 @@ LJ5AZXvOhHaXdHzMuYKX5BpK4w7TqbPvJ6QPvKmLKvHh1VKcUJ6mJQgJJw==
2382
2473
  */
2383
2474
  async reVerify() {
2384
2475
  this.state = null;
2385
- this.hasLoggedWarning = false;
2476
+ // this.hasLoggedWarning = false;
2386
2477
  this.loggedMissingFeatures.clear();
2387
2478
  return this.verify();
2388
2479
  }
@@ -2487,15 +2578,6 @@ LJ5AZXvOhHaXdHzMuYKX5BpK4w7TqbPvJ6QPvKmLKvHh1VKcUJ6mJQgJJw==
2487
2578
  break;
2488
2579
  }
2489
2580
  }
2490
- /**
2491
- * Log development-only warning
2492
- */
2493
- logDevelopmentWarning() {
2494
- console.warn('[Cybernetic License] Running in development mode with ' +
2495
- `${this.state?.status || 'unknown'} license. ` +
2496
- 'In production, a warning will be appended to chatbot responses. ' +
2497
- 'Get a license at https://astermind.ai/license');
2498
- }
2499
2581
  }
2500
2582
  /**
2501
2583
  * Create a pre-configured license manager and verify immediately
@@ -2529,6 +2611,8 @@ LJ5AZXvOhHaXdHzMuYKX5BpK4w7TqbPvJ6QPvKmLKvHh1VKcUJ6mJQgJJw==
2529
2611
  this.offlineStorage = null;
2530
2612
  // Omega RAG (optional, loaded dynamically)
2531
2613
  this.omegaRAG = null;
2614
+ // Sales API client (optional, enabled via salesMode config)
2615
+ this.salesClient = null;
2532
2616
  // Track if offline warning has been shown
2533
2617
  this.offlineWarningShown = false;
2534
2618
  // Resolve WebSocket URL (explicit → env → auto-derived from apiUrl)
@@ -2598,6 +2682,10 @@ LJ5AZXvOhHaXdHzMuYKX5BpK4w7TqbPvJ6QPvKmLKvHh1VKcUJ6mJQgJJw==
2598
2682
  // Silent failure on init - cache may be stale but usable
2599
2683
  });
2600
2684
  }
2685
+ // Initialize sales client if configured
2686
+ if (config.salesMode?.enabled) {
2687
+ this.salesClient = new SalesApiClient(config.apiUrl, config.apiKey);
2688
+ }
2601
2689
  // Initialize offline vector support if configured
2602
2690
  if (this.config.offline?.enabled) {
2603
2691
  this.initializeOffline(this.config.offline).catch((error) => {
@@ -2912,6 +3000,63 @@ LJ5AZXvOhHaXdHzMuYKX5BpK4w7TqbPvJ6QPvKmLKvHh1VKcUJ6mJQgJJw==
2912
3000
  startNewSession(sessionId) {
2913
3001
  this.sessionStorage.startNewSession(sessionId);
2914
3002
  }
3003
+ // ==================== SALES API METHODS ====================
3004
+ /**
3005
+ * Check if sales mode is enabled
3006
+ */
3007
+ isSalesModeEnabled() {
3008
+ return this.salesClient !== null;
3009
+ }
3010
+ /**
3011
+ * Get the sales API client for direct access
3012
+ */
3013
+ getSalesClient() {
3014
+ return this.salesClient;
3015
+ }
3016
+ /**
3017
+ * Send a sales-aware chat message.
3018
+ * Returns the assistant reply with sales context (lead score, CTA buttons, etc.).
3019
+ * Requires salesMode to be enabled in config.
3020
+ */
3021
+ async salesChat(message, options = {}) {
3022
+ if (!this.salesClient) {
3023
+ throw new Error('Sales mode is not enabled. Set salesMode.enabled = true in config.');
3024
+ }
3025
+ return this.salesClient.salesChat(message, options);
3026
+ }
3027
+ /**
3028
+ * Initialize or resume a visitor session.
3029
+ * Call on first page load to register the visitor with the backend.
3030
+ * Requires salesMode to be enabled in config.
3031
+ */
3032
+ async initVisitor(visitorId, pageUrl, referrer, utmParams) {
3033
+ if (!this.salesClient) {
3034
+ throw new Error('Sales mode is not enabled. Set salesMode.enabled = true in config.');
3035
+ }
3036
+ return this.salesClient.initVisitor(visitorId, pageUrl, referrer, utmParams);
3037
+ }
3038
+ /**
3039
+ * Track a page view event for a visitor.
3040
+ * Call when the visitor navigates to a new page.
3041
+ * Requires salesMode to be enabled in config.
3042
+ */
3043
+ async trackPageView(visitorId, url, title, timeOnPageMs, scrollDepth) {
3044
+ if (!this.salesClient) {
3045
+ throw new Error('Sales mode is not enabled. Set salesMode.enabled = true in config.');
3046
+ }
3047
+ return this.salesClient.trackPageView(visitorId, url, title, timeOnPageMs, scrollDepth);
3048
+ }
3049
+ /**
3050
+ * Submit a lead capture form.
3051
+ * Creates or updates a lead record in the backend.
3052
+ * Requires salesMode to be enabled in config.
3053
+ */
3054
+ async captureLeadForm(data) {
3055
+ if (!this.salesClient) {
3056
+ throw new Error('Sales mode is not enabled. Set salesMode.enabled = true in config.');
3057
+ }
3058
+ return this.salesClient.captureLeadForm(data);
3059
+ }
2915
3060
  // ==================== CORE METHODS ====================
2916
3061
  /**
2917
3062
  * Send a message to the chatbot
@@ -7483,6 +7628,7 @@ LJ5AZXvOhHaXdHzMuYKX5BpK4w7TqbPvJ6QPvKmLKvHh1VKcUJ6mJQgJJw==
7483
7628
  exports.LicenseManager = LicenseManager;
7484
7629
  exports.OmegaOfflineRAG = OmegaOfflineRAG;
7485
7630
  exports.REQUIRED_FEATURES = REQUIRED_FEATURES;
7631
+ exports.SalesApiClient = SalesApiClient;
7486
7632
  exports.SiteMapDiscovery = SiteMapDiscovery;
7487
7633
  exports.WebSocketTransport = WebSocketTransport;
7488
7634
  exports.configLoaders = configLoaders;