cuoral-ionic 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/android/build/.transforms/bb54161301273cf9b5b94a21c0fb3f23/transformed/classes/classes_dex/classes.dex +0 -0
  2. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$1.dex +0 -0
  3. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$2.dex +0 -0
  4. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$3.dex +0 -0
  5. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$4.dex +0 -0
  6. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$5.dex +0 -0
  7. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$6.dex +0 -0
  8. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$InitiateCallback.dex +0 -0
  9. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin$UploadCallback.dex +0 -0
  10. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/debug_dex/com/cuoral/ionic/CuoralPlugin.dex +0 -0
  11. package/android/build/.transforms/f1aabffcd8b03aa664e77a79b3e1de5d/transformed/debug/desugar_graph.bin +0 -0
  12. package/android/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
  13. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$1.class +0 -0
  14. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$2.class +0 -0
  15. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$3.class +0 -0
  16. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$4.class +0 -0
  17. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$5.class +0 -0
  18. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$6.class +0 -0
  19. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$InitiateCallback.class +0 -0
  20. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin$UploadCallback.class +0 -0
  21. package/android/build/intermediates/javac/debug/classes/com/cuoral/ionic/CuoralPlugin.class +0 -0
  22. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$1.class +0 -0
  23. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$2.class +0 -0
  24. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$3.class +0 -0
  25. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$4.class +0 -0
  26. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$5.class +0 -0
  27. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$6.class +0 -0
  28. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$InitiateCallback.class +0 -0
  29. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin$UploadCallback.class +0 -0
  30. package/android/build/intermediates/runtime_library_classes_dir/debug/com/cuoral/ionic/CuoralPlugin.class +0 -0
  31. package/android/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
  32. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  33. package/android/build.gradle +1 -0
  34. package/android/src/main/java/com/cuoral/ionic/CuoralPlugin.java +205 -5
  35. package/dist/cuoral.d.ts +15 -1
  36. package/dist/cuoral.d.ts.map +1 -1
  37. package/dist/cuoral.js +113 -9
  38. package/dist/index.esm.js +159 -19
  39. package/dist/index.esm.js.map +1 -1
  40. package/dist/index.js +159 -19
  41. package/dist/index.js.map +1 -1
  42. package/dist/intelligence.d.ts +4 -0
  43. package/dist/intelligence.d.ts.map +1 -1
  44. package/dist/intelligence.js +19 -0
  45. package/dist/plugin.d.ts +15 -2
  46. package/dist/plugin.d.ts.map +1 -1
  47. package/dist/plugin.js +23 -10
  48. package/dist/types.d.ts +4 -0
  49. package/dist/types.d.ts.map +1 -1
  50. package/dist/types.js +4 -0
  51. package/ios/Plugin/CuoralPlugin.swift +249 -13
  52. package/package.json +1 -1
  53. package/src/cuoral.ts +128 -11
  54. package/src/intelligence.ts +23 -0
  55. package/src/plugin.ts +39 -11
  56. package/src/types.ts +4 -0
package/dist/index.esm.js CHANGED
@@ -11,6 +11,7 @@ var CuoralMessageType;
11
11
  CuoralMessageType["STOP_RECORDING"] = "CUORAL_STOP_RECORDING";
12
12
  CuoralMessageType["RECORDING_STARTED"] = "CUORAL_RECORDING_STARTED";
13
13
  CuoralMessageType["RECORDING_STOPPED"] = "CUORAL_RECORDING_STOPPED";
14
+ CuoralMessageType["RECORDING_UPLOADED"] = "CUORAL_RECORDING_UPLOADED";
14
15
  CuoralMessageType["RECORDING_ERROR"] = "CUORAL_RECORDING_ERROR";
15
16
  // Screenshot
16
17
  CuoralMessageType["TAKE_SCREENSHOT"] = "CUORAL_TAKE_SCREENSHOT";
@@ -19,6 +20,9 @@ var CuoralMessageType;
19
20
  // Widget Communication
20
21
  CuoralMessageType["WIDGET_READY"] = "CUORAL_WIDGET_READY";
21
22
  CuoralMessageType["WIDGET_CLOSED"] = "CUORAL_WIDGET_CLOSED";
23
+ CuoralMessageType["SESSION_UPDATED"] = "CUORAL_SESSION_UPDATED";
24
+ CuoralMessageType["REQUEST_SESSION_ID"] = "CUORAL_REQUEST_SESSION_ID";
25
+ CuoralMessageType["SESSION_ID_RESPONSE"] = "CUORAL_SESSION_ID_RESPONSE";
22
26
  // File Upload
23
27
  CuoralMessageType["UPLOAD_FILE"] = "CUORAL_UPLOAD_FILE";
24
28
  CuoralMessageType["UPLOAD_PROGRESS"] = "CUORAL_UPLOAD_PROGRESS";
@@ -93,7 +97,7 @@ class CuoralRecorder {
93
97
  /**
94
98
  * Stop recording
95
99
  */
96
- async stopRecording() {
100
+ async stopRecording(options) {
97
101
  try {
98
102
  if (!this.isRecording) {
99
103
  // Send error message to widget so it can exit "stopping" state
@@ -103,23 +107,36 @@ class CuoralRecorder {
103
107
  });
104
108
  return null;
105
109
  }
106
- const result = await CuoralPlugin$1.stopRecording();
110
+ const result = await CuoralPlugin$1.stopRecording(options);
107
111
  if (result.success) {
108
112
  this.isRecording = false;
109
113
  const duration = this.recordingStartTime
110
114
  ? Math.floor((Date.now() - this.recordingStartTime) / 1000)
111
115
  : 0;
112
- // Post message to widget
113
- this.postMessage({
114
- type: CuoralMessageType.RECORDING_STOPPED,
115
- payload: {
116
- filePath: result.filePath,
117
- duration: result.duration || duration,
118
- },
119
- });
116
+ // If uploaded, notify widget differently
117
+ if (result.uploaded) {
118
+ this.postMessage({
119
+ type: CuoralMessageType.RECORDING_UPLOADED,
120
+ payload: {
121
+ duration: result.duration || duration,
122
+ uploaded: true
123
+ },
124
+ });
125
+ }
126
+ else {
127
+ // Post message to widget (old behavior)
128
+ this.postMessage({
129
+ type: CuoralMessageType.RECORDING_STOPPED,
130
+ payload: {
131
+ filePath: result.filePath,
132
+ duration: result.duration || duration,
133
+ },
134
+ });
135
+ }
120
136
  return {
121
137
  filePath: result.filePath,
122
138
  duration: result.duration || duration,
139
+ uploaded: result.uploaded,
123
140
  };
124
141
  }
125
142
  // If result.success is false, send error to widget
@@ -636,6 +653,24 @@ class CuoralIntelligence {
636
653
  this.rageClickWindowMs = 2000; // Within 2 seconds
637
654
  this.sessionId = sessionId;
638
655
  }
656
+ /**
657
+ * Update the session ID (e.g., when user logs in)
658
+ */
659
+ updateSessionId(newSessionId) {
660
+ console.log('[Cuoral Intelligence] Updating session ID from', this.sessionId, 'to', newSessionId);
661
+ this.sessionId = newSessionId;
662
+ // Flush any pending events with the old session before switching
663
+ this.flush();
664
+ // Update native error capture with new session ID
665
+ if (Capacitor.isNativePlatform()) {
666
+ CuoralPlugin.setupNativeErrorCapture({
667
+ backendUrl: this.config.consoleErrorBackendUrl,
668
+ sessionId: newSessionId
669
+ }).catch(error => {
670
+ console.warn('[Cuoral Intelligence] Failed to update native error capture:', error);
671
+ });
672
+ }
673
+ }
639
674
  /**
640
675
  * Initialize intelligence tracking
641
676
  */
@@ -965,6 +1000,7 @@ class CuoralIntelligence {
965
1000
  url: window.location.href,
966
1001
  data,
967
1002
  };
1003
+ console.log(`[Intelligence] Enqueuing ${type} event with session:`, this.sessionId);
968
1004
  queue.push(event);
969
1005
  // Flush immediately for critical errors
970
1006
  const shouldFlushImmediately = type === 'api_call' && (data.status_code === 0 || data.status_code >= 400);
@@ -1410,6 +1446,11 @@ class Cuoral {
1410
1446
  key: options.publicKey,
1411
1447
  _t: Date.now().toString(),
1412
1448
  });
1449
+ // Add session_id if available (for widget to use existing session)
1450
+ const existingSessionId = localStorage.getItem('__x_loadID');
1451
+ if (existingSessionId) {
1452
+ params.set('cuoral_mobile_session_id', existingSessionId);
1453
+ }
1413
1454
  if (options.email)
1414
1455
  params.set('email', options.email);
1415
1456
  if (options.firstName)
@@ -1434,18 +1475,23 @@ class Cuoral {
1434
1475
  * Initialize Cuoral
1435
1476
  */
1436
1477
  async initialize() {
1478
+ // Fetch session configuration and initialize intelligence if enabled by backend
1479
+ await this.initializeIntelligence();
1480
+ console.log('[Cuoral] Initialize - Session ID:', localStorage.getItem('__x_loadID'));
1481
+ // Setup localStorage listener to detect when widget changes session
1482
+ this.setupStorageListener();
1437
1483
  this.bridge.initialize();
1438
1484
  // Recreate modal if it was destroyed (e.g., after clearSession)
1439
1485
  if (this.options.useModal && !this.modal) {
1440
1486
  const widgetUrl = this.getWidgetUrl();
1441
1487
  this.modal = new CuoralModal(widgetUrl, this.options.showFloatingButton);
1442
1488
  }
1443
- // Initialize modal if enabled
1489
+ // Update modal URL with session ID
1444
1490
  if (this.modal) {
1491
+ const widgetUrl = this.getWidgetUrl();
1492
+ this.modal.updateWidgetUrl(widgetUrl);
1445
1493
  this.modal.initialize();
1446
1494
  }
1447
- // Fetch session configuration and initialize intelligence if enabled by backend
1448
- await this.initializeIntelligence();
1449
1495
  }
1450
1496
  /**
1451
1497
  * Initialize intelligence based on backend configuration
@@ -1477,9 +1523,13 @@ class Cuoral {
1477
1523
  }
1478
1524
  // Only initialize intelligence if customer_intelligence is enabled in backend
1479
1525
  if (config && config.customer_intelligence === true) {
1526
+ console.log('[Cuoral] Initializing intelligence with session:', sessionId);
1480
1527
  this.intelligence = new CuoralIntelligence(sessionId);
1481
1528
  this.intelligence.init();
1482
1529
  }
1530
+ else {
1531
+ console.log('[Cuoral] Intelligence not enabled or no config for session:', sessionId);
1532
+ }
1483
1533
  }
1484
1534
  catch (error) {
1485
1535
  console.warn('[Cuoral] Failed to initialize intelligence:', error);
@@ -1536,6 +1586,48 @@ class Cuoral {
1536
1586
  this.intelligence.trackError(message, stackTrace, metadata);
1537
1587
  }
1538
1588
  }
1589
+ /**
1590
+ * Update user profile for the current session
1591
+ * Call this after user logs in to update the intelligence session with their profile
1592
+ * @param email - User's email address
1593
+ * @param name - User's full name
1594
+ */
1595
+ async updateUserProfile(email, name) {
1596
+ try {
1597
+ const sessionId = localStorage.getItem('__x_loadID');
1598
+ if (!sessionId) {
1599
+ console.warn('[Cuoral] No session ID found, cannot update profile');
1600
+ return false;
1601
+ }
1602
+ console.log('[Cuoral] Updating user profile for session:', sessionId);
1603
+ const response = await fetch('https://api.cuoral.com/conversation/set-profile', {
1604
+ method: 'POST',
1605
+ headers: { 'Content-Type': 'application/json' },
1606
+ body: JSON.stringify({
1607
+ session_id: sessionId,
1608
+ email: email,
1609
+ name: name,
1610
+ }),
1611
+ });
1612
+ if (!response.ok) {
1613
+ console.error('[Cuoral] Failed to update profile:', response.statusText);
1614
+ return false;
1615
+ }
1616
+ console.log('[Cuoral] ✓ User profile updated successfully for session:', sessionId);
1617
+ // Store user info locally
1618
+ this.options.email = email;
1619
+ const nameParts = name.split(' ');
1620
+ if (nameParts.length > 0) {
1621
+ this.options.firstName = nameParts[0];
1622
+ this.options.lastName = nameParts.slice(1).join(' ');
1623
+ }
1624
+ return true;
1625
+ }
1626
+ catch (error) {
1627
+ console.error('[Cuoral] Error updating user profile:', error);
1628
+ return false;
1629
+ }
1630
+ }
1539
1631
  /**
1540
1632
  * Start native screen recording programmatically
1541
1633
  * @returns Promise<boolean> - true if recording started successfully
@@ -1551,11 +1643,19 @@ class Cuoral {
1551
1643
  }
1552
1644
  /**
1553
1645
  * Stop native screen recording programmatically
1554
- * @returns Promise<{filePath?: string; duration?: number} | null> - Recording result or null if failed
1646
+ * Recording will be automatically uploaded to the portal
1647
+ * @returns Promise<{filePath?: string; duration?: number; uploaded?: boolean} | null> - Recording result or null if failed
1555
1648
  */
1556
1649
  async stopRecording() {
1557
1650
  try {
1558
- return await this.recorder.stopRecording();
1651
+ const sessionId = localStorage.getItem('__x_loadID');
1652
+ const customerId = localStorage.getItem('cuoralCustomerId');
1653
+ return await this.recorder.stopRecording({
1654
+ autoUpload: true,
1655
+ sessionId: sessionId || undefined,
1656
+ publicKey: this.options.publicKey,
1657
+ customerId: customerId || undefined,
1658
+ });
1559
1659
  }
1560
1660
  catch (error) {
1561
1661
  console.error('[Cuoral] Failed to stop recording:', error);
@@ -1601,7 +1701,7 @@ class Cuoral {
1601
1701
  // Add session_id if available
1602
1702
  const sessionId = localStorage.getItem('__x_loadID');
1603
1703
  if (sessionId) {
1604
- params.set('session_id', sessionId);
1704
+ params.set('cuoral_mobile_session_id', sessionId);
1605
1705
  }
1606
1706
  if (this.options.email)
1607
1707
  params.set('email', this.options.email);
@@ -1655,6 +1755,28 @@ class Cuoral {
1655
1755
  }
1656
1756
  }
1657
1757
  }
1758
+ /**
1759
+ * Setup localStorage listener for session changes
1760
+ * Widget updates localStorage when creating new session, SDK detects and syncs
1761
+ */
1762
+ setupStorageListener() {
1763
+ // Poll localStorage every 2 seconds to detect session changes
1764
+ // (storage event doesn't fire for same-window changes)
1765
+ let lastKnownSession = localStorage.getItem('__x_loadID');
1766
+ setInterval(() => {
1767
+ const currentSession = localStorage.getItem('__x_loadID');
1768
+ if (currentSession && currentSession !== lastKnownSession) {
1769
+ console.log('[Cuoral] 🔄 Session changed in localStorage');
1770
+ console.log('[Cuoral] Old session:', lastKnownSession);
1771
+ console.log('[Cuoral] New session:', currentSession);
1772
+ lastKnownSession = currentSession;
1773
+ // Update intelligence to use new session
1774
+ if (this.intelligence) {
1775
+ this.intelligence.updateSessionId(currentSession);
1776
+ }
1777
+ }
1778
+ }, 2000);
1779
+ }
1658
1780
  /**
1659
1781
  * Clean up resources
1660
1782
  */
@@ -1746,9 +1868,27 @@ class Cuoral {
1746
1868
  });
1747
1869
  // Handle stop recording requests from widget
1748
1870
  this.bridge.on(CuoralMessageType.STOP_RECORDING, async () => {
1749
- const result = await this.recorder.stopRecording();
1750
- if (result) {
1751
- // Convert file path to web-accessible URL
1871
+ const sessionId = localStorage.getItem('__x_loadID');
1872
+ const customerId = localStorage.getItem('cuoralCustomerId');
1873
+ const result = await this.recorder.stopRecording({
1874
+ autoUpload: true,
1875
+ sessionId: sessionId || undefined,
1876
+ publicKey: this.options.publicKey,
1877
+ customerId: customerId || undefined,
1878
+ });
1879
+ if (result && result.uploaded) {
1880
+ // Video was automatically uploaded, just notify widget
1881
+ this.bridge.sendToWidget({
1882
+ type: CuoralMessageType.RECORDING_UPLOADED,
1883
+ payload: {
1884
+ duration: result.duration,
1885
+ uploaded: true,
1886
+ timestamp: Date.now()
1887
+ }
1888
+ });
1889
+ }
1890
+ else if (result) {
1891
+ // Upload failed or was disabled, send video data to widget (old behavior)
1752
1892
  const capacitorUrl = result.filePath ? Capacitor.convertFileSrc(result.filePath) : '';
1753
1893
  try {
1754
1894
  // Fetch the video blob from the capacitor URL
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.js CHANGED
@@ -32,6 +32,7 @@ exports.CuoralMessageType = void 0;
32
32
  CuoralMessageType["STOP_RECORDING"] = "CUORAL_STOP_RECORDING";
33
33
  CuoralMessageType["RECORDING_STARTED"] = "CUORAL_RECORDING_STARTED";
34
34
  CuoralMessageType["RECORDING_STOPPED"] = "CUORAL_RECORDING_STOPPED";
35
+ CuoralMessageType["RECORDING_UPLOADED"] = "CUORAL_RECORDING_UPLOADED";
35
36
  CuoralMessageType["RECORDING_ERROR"] = "CUORAL_RECORDING_ERROR";
36
37
  // Screenshot
37
38
  CuoralMessageType["TAKE_SCREENSHOT"] = "CUORAL_TAKE_SCREENSHOT";
@@ -40,6 +41,9 @@ exports.CuoralMessageType = void 0;
40
41
  // Widget Communication
41
42
  CuoralMessageType["WIDGET_READY"] = "CUORAL_WIDGET_READY";
42
43
  CuoralMessageType["WIDGET_CLOSED"] = "CUORAL_WIDGET_CLOSED";
44
+ CuoralMessageType["SESSION_UPDATED"] = "CUORAL_SESSION_UPDATED";
45
+ CuoralMessageType["REQUEST_SESSION_ID"] = "CUORAL_REQUEST_SESSION_ID";
46
+ CuoralMessageType["SESSION_ID_RESPONSE"] = "CUORAL_SESSION_ID_RESPONSE";
43
47
  // File Upload
44
48
  CuoralMessageType["UPLOAD_FILE"] = "CUORAL_UPLOAD_FILE";
45
49
  CuoralMessageType["UPLOAD_PROGRESS"] = "CUORAL_UPLOAD_PROGRESS";
@@ -114,7 +118,7 @@ class CuoralRecorder {
114
118
  /**
115
119
  * Stop recording
116
120
  */
117
- async stopRecording() {
121
+ async stopRecording(options) {
118
122
  try {
119
123
  if (!this.isRecording) {
120
124
  // Send error message to widget so it can exit "stopping" state
@@ -124,23 +128,36 @@ class CuoralRecorder {
124
128
  });
125
129
  return null;
126
130
  }
127
- const result = await CuoralPlugin$1.stopRecording();
131
+ const result = await CuoralPlugin$1.stopRecording(options);
128
132
  if (result.success) {
129
133
  this.isRecording = false;
130
134
  const duration = this.recordingStartTime
131
135
  ? Math.floor((Date.now() - this.recordingStartTime) / 1000)
132
136
  : 0;
133
- // Post message to widget
134
- this.postMessage({
135
- type: exports.CuoralMessageType.RECORDING_STOPPED,
136
- payload: {
137
- filePath: result.filePath,
138
- duration: result.duration || duration,
139
- },
140
- });
137
+ // If uploaded, notify widget differently
138
+ if (result.uploaded) {
139
+ this.postMessage({
140
+ type: exports.CuoralMessageType.RECORDING_UPLOADED,
141
+ payload: {
142
+ duration: result.duration || duration,
143
+ uploaded: true
144
+ },
145
+ });
146
+ }
147
+ else {
148
+ // Post message to widget (old behavior)
149
+ this.postMessage({
150
+ type: exports.CuoralMessageType.RECORDING_STOPPED,
151
+ payload: {
152
+ filePath: result.filePath,
153
+ duration: result.duration || duration,
154
+ },
155
+ });
156
+ }
141
157
  return {
142
158
  filePath: result.filePath,
143
159
  duration: result.duration || duration,
160
+ uploaded: result.uploaded,
144
161
  };
145
162
  }
146
163
  // If result.success is false, send error to widget
@@ -657,6 +674,24 @@ class CuoralIntelligence {
657
674
  this.rageClickWindowMs = 2000; // Within 2 seconds
658
675
  this.sessionId = sessionId;
659
676
  }
677
+ /**
678
+ * Update the session ID (e.g., when user logs in)
679
+ */
680
+ updateSessionId(newSessionId) {
681
+ console.log('[Cuoral Intelligence] Updating session ID from', this.sessionId, 'to', newSessionId);
682
+ this.sessionId = newSessionId;
683
+ // Flush any pending events with the old session before switching
684
+ this.flush();
685
+ // Update native error capture with new session ID
686
+ if (core.Capacitor.isNativePlatform()) {
687
+ CuoralPlugin.setupNativeErrorCapture({
688
+ backendUrl: this.config.consoleErrorBackendUrl,
689
+ sessionId: newSessionId
690
+ }).catch(error => {
691
+ console.warn('[Cuoral Intelligence] Failed to update native error capture:', error);
692
+ });
693
+ }
694
+ }
660
695
  /**
661
696
  * Initialize intelligence tracking
662
697
  */
@@ -986,6 +1021,7 @@ class CuoralIntelligence {
986
1021
  url: window.location.href,
987
1022
  data,
988
1023
  };
1024
+ console.log(`[Intelligence] Enqueuing ${type} event with session:`, this.sessionId);
989
1025
  queue.push(event);
990
1026
  // Flush immediately for critical errors
991
1027
  const shouldFlushImmediately = type === 'api_call' && (data.status_code === 0 || data.status_code >= 400);
@@ -1431,6 +1467,11 @@ class Cuoral {
1431
1467
  key: options.publicKey,
1432
1468
  _t: Date.now().toString(),
1433
1469
  });
1470
+ // Add session_id if available (for widget to use existing session)
1471
+ const existingSessionId = localStorage.getItem('__x_loadID');
1472
+ if (existingSessionId) {
1473
+ params.set('cuoral_mobile_session_id', existingSessionId);
1474
+ }
1434
1475
  if (options.email)
1435
1476
  params.set('email', options.email);
1436
1477
  if (options.firstName)
@@ -1455,18 +1496,23 @@ class Cuoral {
1455
1496
  * Initialize Cuoral
1456
1497
  */
1457
1498
  async initialize() {
1499
+ // Fetch session configuration and initialize intelligence if enabled by backend
1500
+ await this.initializeIntelligence();
1501
+ console.log('[Cuoral] Initialize - Session ID:', localStorage.getItem('__x_loadID'));
1502
+ // Setup localStorage listener to detect when widget changes session
1503
+ this.setupStorageListener();
1458
1504
  this.bridge.initialize();
1459
1505
  // Recreate modal if it was destroyed (e.g., after clearSession)
1460
1506
  if (this.options.useModal && !this.modal) {
1461
1507
  const widgetUrl = this.getWidgetUrl();
1462
1508
  this.modal = new CuoralModal(widgetUrl, this.options.showFloatingButton);
1463
1509
  }
1464
- // Initialize modal if enabled
1510
+ // Update modal URL with session ID
1465
1511
  if (this.modal) {
1512
+ const widgetUrl = this.getWidgetUrl();
1513
+ this.modal.updateWidgetUrl(widgetUrl);
1466
1514
  this.modal.initialize();
1467
1515
  }
1468
- // Fetch session configuration and initialize intelligence if enabled by backend
1469
- await this.initializeIntelligence();
1470
1516
  }
1471
1517
  /**
1472
1518
  * Initialize intelligence based on backend configuration
@@ -1498,9 +1544,13 @@ class Cuoral {
1498
1544
  }
1499
1545
  // Only initialize intelligence if customer_intelligence is enabled in backend
1500
1546
  if (config && config.customer_intelligence === true) {
1547
+ console.log('[Cuoral] Initializing intelligence with session:', sessionId);
1501
1548
  this.intelligence = new CuoralIntelligence(sessionId);
1502
1549
  this.intelligence.init();
1503
1550
  }
1551
+ else {
1552
+ console.log('[Cuoral] Intelligence not enabled or no config for session:', sessionId);
1553
+ }
1504
1554
  }
1505
1555
  catch (error) {
1506
1556
  console.warn('[Cuoral] Failed to initialize intelligence:', error);
@@ -1557,6 +1607,48 @@ class Cuoral {
1557
1607
  this.intelligence.trackError(message, stackTrace, metadata);
1558
1608
  }
1559
1609
  }
1610
+ /**
1611
+ * Update user profile for the current session
1612
+ * Call this after user logs in to update the intelligence session with their profile
1613
+ * @param email - User's email address
1614
+ * @param name - User's full name
1615
+ */
1616
+ async updateUserProfile(email, name) {
1617
+ try {
1618
+ const sessionId = localStorage.getItem('__x_loadID');
1619
+ if (!sessionId) {
1620
+ console.warn('[Cuoral] No session ID found, cannot update profile');
1621
+ return false;
1622
+ }
1623
+ console.log('[Cuoral] Updating user profile for session:', sessionId);
1624
+ const response = await fetch('https://api.cuoral.com/conversation/set-profile', {
1625
+ method: 'POST',
1626
+ headers: { 'Content-Type': 'application/json' },
1627
+ body: JSON.stringify({
1628
+ session_id: sessionId,
1629
+ email: email,
1630
+ name: name,
1631
+ }),
1632
+ });
1633
+ if (!response.ok) {
1634
+ console.error('[Cuoral] Failed to update profile:', response.statusText);
1635
+ return false;
1636
+ }
1637
+ console.log('[Cuoral] ✓ User profile updated successfully for session:', sessionId);
1638
+ // Store user info locally
1639
+ this.options.email = email;
1640
+ const nameParts = name.split(' ');
1641
+ if (nameParts.length > 0) {
1642
+ this.options.firstName = nameParts[0];
1643
+ this.options.lastName = nameParts.slice(1).join(' ');
1644
+ }
1645
+ return true;
1646
+ }
1647
+ catch (error) {
1648
+ console.error('[Cuoral] Error updating user profile:', error);
1649
+ return false;
1650
+ }
1651
+ }
1560
1652
  /**
1561
1653
  * Start native screen recording programmatically
1562
1654
  * @returns Promise<boolean> - true if recording started successfully
@@ -1572,11 +1664,19 @@ class Cuoral {
1572
1664
  }
1573
1665
  /**
1574
1666
  * Stop native screen recording programmatically
1575
- * @returns Promise<{filePath?: string; duration?: number} | null> - Recording result or null if failed
1667
+ * Recording will be automatically uploaded to the portal
1668
+ * @returns Promise<{filePath?: string; duration?: number; uploaded?: boolean} | null> - Recording result or null if failed
1576
1669
  */
1577
1670
  async stopRecording() {
1578
1671
  try {
1579
- return await this.recorder.stopRecording();
1672
+ const sessionId = localStorage.getItem('__x_loadID');
1673
+ const customerId = localStorage.getItem('cuoralCustomerId');
1674
+ return await this.recorder.stopRecording({
1675
+ autoUpload: true,
1676
+ sessionId: sessionId || undefined,
1677
+ publicKey: this.options.publicKey,
1678
+ customerId: customerId || undefined,
1679
+ });
1580
1680
  }
1581
1681
  catch (error) {
1582
1682
  console.error('[Cuoral] Failed to stop recording:', error);
@@ -1622,7 +1722,7 @@ class Cuoral {
1622
1722
  // Add session_id if available
1623
1723
  const sessionId = localStorage.getItem('__x_loadID');
1624
1724
  if (sessionId) {
1625
- params.set('session_id', sessionId);
1725
+ params.set('cuoral_mobile_session_id', sessionId);
1626
1726
  }
1627
1727
  if (this.options.email)
1628
1728
  params.set('email', this.options.email);
@@ -1676,6 +1776,28 @@ class Cuoral {
1676
1776
  }
1677
1777
  }
1678
1778
  }
1779
+ /**
1780
+ * Setup localStorage listener for session changes
1781
+ * Widget updates localStorage when creating new session, SDK detects and syncs
1782
+ */
1783
+ setupStorageListener() {
1784
+ // Poll localStorage every 2 seconds to detect session changes
1785
+ // (storage event doesn't fire for same-window changes)
1786
+ let lastKnownSession = localStorage.getItem('__x_loadID');
1787
+ setInterval(() => {
1788
+ const currentSession = localStorage.getItem('__x_loadID');
1789
+ if (currentSession && currentSession !== lastKnownSession) {
1790
+ console.log('[Cuoral] 🔄 Session changed in localStorage');
1791
+ console.log('[Cuoral] Old session:', lastKnownSession);
1792
+ console.log('[Cuoral] New session:', currentSession);
1793
+ lastKnownSession = currentSession;
1794
+ // Update intelligence to use new session
1795
+ if (this.intelligence) {
1796
+ this.intelligence.updateSessionId(currentSession);
1797
+ }
1798
+ }
1799
+ }, 2000);
1800
+ }
1679
1801
  /**
1680
1802
  * Clean up resources
1681
1803
  */
@@ -1767,9 +1889,27 @@ class Cuoral {
1767
1889
  });
1768
1890
  // Handle stop recording requests from widget
1769
1891
  this.bridge.on(exports.CuoralMessageType.STOP_RECORDING, async () => {
1770
- const result = await this.recorder.stopRecording();
1771
- if (result) {
1772
- // Convert file path to web-accessible URL
1892
+ const sessionId = localStorage.getItem('__x_loadID');
1893
+ const customerId = localStorage.getItem('cuoralCustomerId');
1894
+ const result = await this.recorder.stopRecording({
1895
+ autoUpload: true,
1896
+ sessionId: sessionId || undefined,
1897
+ publicKey: this.options.publicKey,
1898
+ customerId: customerId || undefined,
1899
+ });
1900
+ if (result && result.uploaded) {
1901
+ // Video was automatically uploaded, just notify widget
1902
+ this.bridge.sendToWidget({
1903
+ type: exports.CuoralMessageType.RECORDING_UPLOADED,
1904
+ payload: {
1905
+ duration: result.duration,
1906
+ uploaded: true,
1907
+ timestamp: Date.now()
1908
+ }
1909
+ });
1910
+ }
1911
+ else if (result) {
1912
+ // Upload failed or was disabled, send video data to widget (old behavior)
1773
1913
  const capacitorUrl = result.filePath ? core.Capacitor.convertFileSrc(result.filePath) : '';
1774
1914
  try {
1775
1915
  // Fetch the video blob from the capacitor URL
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -17,6 +17,10 @@ export declare class CuoralIntelligence {
17
17
  private rageClickThreshold;
18
18
  private rageClickWindowMs;
19
19
  constructor(sessionId: string);
20
+ /**
21
+ * Update the session ID (e.g., when user logs in)
22
+ */
23
+ updateSessionId(newSessionId: string): void;
20
24
  /**
21
25
  * Initialize intelligence tracking
22
26
  */
@@ -1 +1 @@
1
- {"version":3,"file":"intelligence.d.ts","sourceRoot":"","sources":["../src/intelligence.ts"],"names":[],"mappings":"AA0EA,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAWZ;IAEF,OAAO,CAAC,MAAM,CAKZ;IAEF,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,qBAAqB,CAAc;IAC3C,OAAO,CAAC,kBAAkB,CAAM;IAChC,OAAO,CAAC,aAAa,CAAa;IAGlC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,sBAAsB,CAAa;IAG3C,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,iBAAiB,CAAQ;gBAErB,SAAS,EAAE,MAAM;IAI7B;;OAEG;IACI,IAAI,IAAI,IAAI;IAgBnB;;OAEG;IACI,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,IAAI;IAc1D;;OAEG;IACI,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,IAAI;IAS7E;;OAEG;IACI,KAAK,IAAI,IAAI;IAMpB;;OAEG;IACI,OAAO,IAAI,IAAI;IA0CtB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAoFjC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA8H9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgB7B;;OAEG;IACH,OAAO,CAAC,YAAY;IAwCpB;;OAEG;IACH,OAAO,CAAC,UAAU;IAoFlB;;OAEG;YACW,aAAa;IAiC3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgB/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiC1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoD1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwC3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6DzB;;OAEG;IACI,gBAAgB,CACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACpC,eAAe,CAAC,EAAE,MAAM,EACxB,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI;IAgBP;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAwB/B;;OAEG;YACW,sBAAsB;IAkBpC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;OAEG;IACH,OAAO,CAAC,WAAW;CAOpB"}
1
+ {"version":3,"file":"intelligence.d.ts","sourceRoot":"","sources":["../src/intelligence.ts"],"names":[],"mappings":"AA0EA,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAWZ;IAEF,OAAO,CAAC,MAAM,CAKZ;IAEF,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,qBAAqB,CAAc;IAC3C,OAAO,CAAC,kBAAkB,CAAM;IAChC,OAAO,CAAC,aAAa,CAAa;IAGlC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,sBAAsB,CAAa;IAG3C,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,iBAAiB,CAAQ;gBAErB,SAAS,EAAE,MAAM;IAI7B;;OAEG;IACI,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAkBlD;;OAEG;IACI,IAAI,IAAI,IAAI;IAgBnB;;OAEG;IACI,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,IAAI;IAc1D;;OAEG;IACI,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,IAAI;IAS7E;;OAEG;IACI,KAAK,IAAI,IAAI;IAMpB;;OAEG;IACI,OAAO,IAAI,IAAI;IA0CtB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAoFjC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA8H9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgB7B;;OAEG;IACH,OAAO,CAAC,YAAY;IAyCpB;;OAEG;IACH,OAAO,CAAC,UAAU;IAqFlB;;OAEG;YACW,aAAa;IAiC3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAgB/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiC1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoD1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwC3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6DzB;;OAEG;IACI,gBAAgB,CACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACpC,eAAe,CAAC,EAAE,MAAM,EACxB,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI;IAgBP;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAwB/B;;OAEG;YACW,sBAAsB;IAkBpC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;OAEG;IACH,OAAO,CAAC,WAAW;CAOpB"}
@@ -42,6 +42,24 @@ export class CuoralIntelligence {
42
42
  this.rageClickWindowMs = 2000; // Within 2 seconds
43
43
  this.sessionId = sessionId;
44
44
  }
45
+ /**
46
+ * Update the session ID (e.g., when user logs in)
47
+ */
48
+ updateSessionId(newSessionId) {
49
+ console.log('[Cuoral Intelligence] Updating session ID from', this.sessionId, 'to', newSessionId);
50
+ this.sessionId = newSessionId;
51
+ // Flush any pending events with the old session before switching
52
+ this.flush();
53
+ // Update native error capture with new session ID
54
+ if (Capacitor.isNativePlatform()) {
55
+ CuoralPlugin.setupNativeErrorCapture({
56
+ backendUrl: this.config.consoleErrorBackendUrl,
57
+ sessionId: newSessionId
58
+ }).catch(error => {
59
+ console.warn('[Cuoral Intelligence] Failed to update native error capture:', error);
60
+ });
61
+ }
62
+ }
45
63
  /**
46
64
  * Initialize intelligence tracking
47
65
  */
@@ -371,6 +389,7 @@ export class CuoralIntelligence {
371
389
  url: window.location.href,
372
390
  data,
373
391
  };
392
+ console.log(`[Intelligence] Enqueuing ${type} event with session:`, this.sessionId);
374
393
  queue.push(event);
375
394
  // Flush immediately for critical errors
376
395
  const shouldFlushImmediately = type === 'api_call' && (data.status_code === 0 || data.status_code >= 400);