@ctchealth/plato-sdk 0.0.12 → 0.0.14

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 CHANGED
@@ -104,7 +104,15 @@ call.on('message', message => {
104
104
  });
105
105
 
106
106
  call.on('call-end', () => {
107
- console.log('Call ended');
107
+ console.log('Call ended - processing feedback...');
108
+ });
109
+
110
+ // Automatically receive post-call feedback when ready
111
+ call.on('call-details-ready', callDetails => {
112
+ console.log('Call Summary:', callDetails.summary);
113
+ console.log('Score:', callDetails.score);
114
+ console.log('Strengths:', callDetails.strengths);
115
+ console.log('Areas to improve:', callDetails.weaknesses);
108
116
  });
109
117
 
110
118
  // Stop the call when done
@@ -128,9 +136,37 @@ new PlatoApiClient(config: ApiClientConfig)
128
136
  - `config.baseUrl` (string): The base URL of the Plato API
129
137
  - `config.token` (string): Your API authentication token
130
138
  - `config.user` (string): Your user identifier
139
+ - `config.jwtToken` (string, optional): A per-user JWT token sent as the `x-client-token` header on every request
140
+
141
+ **Example with JWT token:**
142
+
143
+ ```typescript
144
+ const client = new PlatoApiClient({
145
+ baseUrl: 'https://your-plato-api.com',
146
+ token: 'your-api-key',
147
+ user: 'user@example.com',
148
+ jwtToken: 'eyJhbGciOiJSUzI1NiIs...', // optional, per-user token
149
+ });
150
+ ```
131
151
 
132
152
  #### Methods
133
153
 
154
+ ##### setJwtToken(jwtToken: string)
155
+
156
+ Updates the JWT token for all subsequent requests. Use this when the token is refreshed or when switching user context.
157
+
158
+ ```typescript
159
+ client.setJwtToken('new-jwt-token');
160
+ ```
161
+
162
+ ##### clearJwtToken()
163
+
164
+ Removes the JWT token from subsequent requests.
165
+
166
+ ```typescript
167
+ client.clearJwtToken();
168
+ ```
169
+
134
170
  ##### createSimulation(params: CreateSimulationDto)
135
171
 
136
172
  Creates a new medical training simulation. It may take a few minutes for the simulation to be ready for use.
@@ -332,7 +368,7 @@ const images = await client.getAssistantImages();
332
368
 
333
369
  ##### getRecommendations()
334
370
 
335
- Retrieves recommendations based on the user's recent call performance. Analyzes up to 10 of the most recent calls to identify patterns and provide actionable insights.
371
+ Retrieves recommendations based on the user's recent call performance. Analyzes the 5 most recent calls using a sliding window of 3 calls to identify patterns and provide actionable insights. Calls shorter than 2 minutes are excluded from analysis. No new recommendations are generated if fewer than 3 eligible calls are available.
336
372
 
337
373
  **Returns:** `Promise<RecommendationsResponseDto>` — An object containing:
338
374
 
@@ -445,6 +481,308 @@ const inProgress = simulations.find(
445
481
  );
446
482
  ```
447
483
 
484
+ ## Call Recovery
485
+
486
+ The SDK automatically handles call recovery in case of page refreshes or browser closures during active calls. This ensures that call data is never lost and all calls get properly processed by the backend, even if the page is refreshed while a call is in progress.
487
+
488
+ ### How It Works
489
+
490
+ When you start a call, the SDK stores minimal call state in the browser's localStorage. If the page is refreshed:
491
+
492
+ 1. **On app initialization**: The `recoverAbandonedCall()` method checks for any stored call state
493
+ 2. **Age-based recovery**: Calls older than 5 minutes are considered abandoned and automatically recovered
494
+ 3. **Backend notification**: The backend is notified to process the call's transcript, recording, and analytics
495
+ 4. **Automatic cleanup**: The stored state is cleared after recovery or when a call ends naturally
496
+
497
+ This recovery mechanism works in **two stages** to ensure complete data integrity:
498
+
499
+ - **Stage 1 (App Init)**: Recovers truly abandoned calls (>5 minutes old)
500
+ - **Stage 2 (New Call Start)**: Notifies backend of ANY previous call before starting a new one
501
+
502
+ This dual approach ensures no call data is ever lost, regardless of user behavior patterns.
503
+
504
+ ### Integration
505
+
506
+ #### Angular
507
+
508
+ Call `recoverAbandonedCall()` during component initialization:
509
+
510
+ ```typescript
511
+ import { Component, OnInit } from '@angular/core';
512
+ import { PlatoApiClient } from 'plato-sdk';
513
+
514
+ @Component({
515
+ selector: 'app-training',
516
+ templateUrl: './training.component.html',
517
+ })
518
+ export class TrainingComponent implements OnInit {
519
+ constructor(private platoClient: PlatoApiClient) {}
520
+
521
+ async ngOnInit(): Promise<void> {
522
+ // Recover any abandoned calls from previous session
523
+ const recovered = await this.platoClient.recoverAbandonedCall();
524
+
525
+ if (recovered) {
526
+ console.log('Recovered abandoned call from previous session');
527
+ // Optional: Show notification to user
528
+ this.showNotification('Previous call data recovered and processed');
529
+ }
530
+
531
+ // Continue with normal initialization
532
+ await this.loadSimulations();
533
+ }
534
+
535
+ showNotification(message: string) {
536
+ // Your notification logic here
537
+ }
538
+ }
539
+ ```
540
+
541
+ #### React
542
+
543
+ Call `recoverAbandonedCall()` in a useEffect hook:
544
+
545
+ ```typescript
546
+ import { useEffect, useState } from 'react';
547
+ import { PlatoApiClient } from 'plato-sdk';
548
+
549
+ function TrainingApp() {
550
+ const [platoClient] = useState(() => new PlatoApiClient({
551
+ baseUrl: 'https://your-api.com',
552
+ token: 'your-token',
553
+ user: 'your-user',
554
+ }));
555
+
556
+ useEffect(() => {
557
+ const recoverCall = async () => {
558
+ try {
559
+ const recovered = await platoClient.recoverAbandonedCall();
560
+
561
+ if (recovered) {
562
+ console.log('Recovered abandoned call');
563
+ // Optional: Show toast notification
564
+ showToast('Previous call data recovered');
565
+ }
566
+ } catch (error) {
567
+ console.error('Recovery error:', error);
568
+ }
569
+ };
570
+
571
+ recoverCall();
572
+ }, [platoClient]);
573
+
574
+ return (
575
+ // Your app UI
576
+ );
577
+ }
578
+ ```
579
+
580
+ ### recoverAbandonedCall()
581
+
582
+ Recovers and processes any abandoned calls from previous sessions.
583
+
584
+ **Returns:** `Promise<boolean>`
585
+
586
+ - `true` if an abandoned call was found and recovered
587
+ - `false` if no abandoned call exists or the call is too recent (<5 minutes)
588
+
589
+ **Example:**
590
+
591
+ ```typescript
592
+ // Check if any calls were recovered
593
+ const wasRecovered = await client.recoverAbandonedCall();
594
+
595
+ if (wasRecovered) {
596
+ // An abandoned call was processed
597
+ console.log('Successfully recovered abandoned call');
598
+ } else {
599
+ // No recovery needed
600
+ console.log('No abandoned calls to recover');
601
+ }
602
+ ```
603
+
604
+ ### Behavior Details
605
+
606
+ #### When Recovery Happens
607
+
608
+ **Scenario 1: Abandoned Call (>5 minutes)**
609
+
610
+ ```
611
+ 10:00:00 - User starts call → State stored
612
+ 10:02:00 - User closes browser
613
+ 10:08:00 - User returns and opens app
614
+ 10:08:01 - recoverAbandonedCall() detects call (>5 min old)
615
+ 10:08:01 - Backend notified → Call processed ✓
616
+ ```
617
+
618
+ **Scenario 2: Recent Call (<5 minutes)**
619
+
620
+ ```
621
+ 10:00:00 - User starts call → State stored
622
+ 10:01:00 - User refreshes page
623
+ 10:01:01 - recoverAbandonedCall() checks call (1 min old)
624
+ 10:01:01 - Too recent, skip recovery
625
+ 10:03:00 - User starts new call
626
+ 10:03:00 - startCall() detects previous call
627
+ 10:03:00 - Backend notified of previous call → Processed ✓
628
+ 10:03:01 - New call starts
629
+ ```
630
+
631
+ #### Automatic Cleanup
632
+
633
+ The SDK automatically clears stored call state when:
634
+
635
+ 1. **Call ends naturally**: When `call-end` event fires
636
+ 2. **User stops call**: When `stopCall()` is called manually
637
+ 3. **New call starts**: Before starting a new call (after notifying backend of previous call)
638
+ 4. **After recovery**: After successfully notifying backend of abandoned call
639
+
640
+ ### Technical Details
641
+
642
+ #### What Gets Stored
643
+
644
+ The SDK stores minimal state in `localStorage` under the key `plato_active_call`:
645
+
646
+ ```typescript
647
+ {
648
+ callId: "mongodb-call-id", // MongoDB ID for backend notification
649
+ externalCallId: "external-provider-id", // External provider's call ID
650
+ simulationId: "simulation-id", // Associated simulation
651
+ startedAt: "2025-01-15T10:00:00Z", // ISO 8601 timestamp
652
+ version: 1 // Schema version for future compatibility
653
+ }
654
+ ```
655
+
656
+ #### Privacy & Storage
657
+
658
+ - **Storage location**: Browser localStorage (persists across sessions)
659
+ - **Data size**: ~300 bytes (minimal footprint)
660
+ - **Privacy**: Stored locally, never sent to third parties
661
+ - **Graceful degradation**: If localStorage is disabled (e.g., private browsing), the SDK continues to work normally but recovery won't be available
662
+
663
+ #### Backend Idempotency
664
+
665
+ The backend `/api/v1/postcall/call-ended` endpoint is idempotent, meaning:
666
+
667
+ - ✅ Safe to call multiple times for the same call
668
+ - ✅ No duplicate processing or data corruption
669
+ - ✅ Recovery logic can safely notify backend even if uncertain
670
+
671
+ This design ensures **data integrity** over potential duplicate notifications.
672
+
673
+ ### Edge Cases
674
+
675
+ #### Multiple Tabs
676
+
677
+ If you have multiple tabs open:
678
+
679
+ - Only the most recent call state is stored (single localStorage key)
680
+ - Each new call in any tab overwrites previous state
681
+ - The most recent call is recovered if needed
682
+
683
+ **Impact**: Minimal - calls typically happen one at a time, and the backend handles all notifications properly.
684
+
685
+ #### Rapid Actions
686
+
687
+ If the user refreshes immediately after starting a call:
688
+
689
+ - The call state is stored but not considered abandoned (<5 minutes)
690
+ - When the user starts a new call later, the previous call is automatically notified to backend
691
+ - No data loss occurs
692
+
693
+ #### Browser Closure
694
+
695
+ If the browser is force-closed during a call:
696
+
697
+ - State persists in localStorage
698
+ - On next app launch, recovery detects and processes the call
699
+ - Call data is recovered successfully
700
+
701
+ #### localStorage Disabled
702
+
703
+ If localStorage is disabled (e.g., private browsing mode):
704
+
705
+ - All storage operations fail silently
706
+ - No errors thrown
707
+ - SDK continues to work for normal call flow
708
+ - Recovery simply won't be available
709
+
710
+ **This is acceptable** because localStorage is enabled in 99%+ of browsers.
711
+
712
+ ### Best Practices
713
+
714
+ 1. **Always call `recoverAbandonedCall()`** during app initialization to ensure data integrity
715
+ 2. **Call it early** in your initialization flow, before other operations
716
+ 3. **Handle the return value** to show user notifications when calls are recovered
717
+ 4. **Don't block UI** - recovery is fast (<500ms typically) but async
718
+ 5. **Trust the system** - the SDK and backend handle all edge cases automatically
719
+
720
+ ### Example: Complete Integration
721
+
722
+ ```typescript
723
+ // Angular Component
724
+ @Component({
725
+ selector: 'app-root',
726
+ templateUrl: './app.component.html',
727
+ })
728
+ export class AppComponent implements OnInit {
729
+ constructor(private platoClient: PlatoApiClient, private toastr: ToastrService) {}
730
+
731
+ async ngOnInit(): Promise<void> {
732
+ try {
733
+ // Step 1: Recover any abandoned calls
734
+ const recovered = await this.platoClient.recoverAbandonedCall();
735
+
736
+ if (recovered) {
737
+ this.toastr.info('Previous call data was recovered and processed');
738
+ }
739
+
740
+ // Step 2: Continue with normal app initialization
741
+ await this.loadUserData();
742
+ await this.loadSimulations();
743
+ } catch (error) {
744
+ console.error('Initialization error:', error);
745
+ }
746
+ }
747
+
748
+ async startCall(simulationId: string): Promise<void> {
749
+ try {
750
+ // The SDK automatically handles any previous call state
751
+ const call = await this.platoClient.startCall(simulationId);
752
+
753
+ call.on('call-end', () => {
754
+ console.log('Call ended');
755
+ // State automatically cleared
756
+ });
757
+
758
+ call.on('call-details-ready', callDetails => {
759
+ console.log('Feedback ready:', callDetails);
760
+ });
761
+ } catch (error) {
762
+ console.error('Call error:', error);
763
+ }
764
+ }
765
+ }
766
+ ```
767
+
768
+ ### Troubleshooting
769
+
770
+ **Q: What if I forget to call `recoverAbandonedCall()`?**
771
+
772
+ A: The SDK still protects against data loss through Stage 2 recovery - when you start a new call, it automatically notifies the backend of any previous call. However, it's still recommended to call `recoverAbandonedCall()` for optimal behavior.
773
+
774
+ **Q: Can I disable call recovery?**
775
+
776
+ A: While you can skip calling `recoverAbandonedCall()`, the Stage 2 recovery (in `startCall()`) always runs to prevent data loss. This is by design to ensure data integrity.
777
+
778
+ **Q: How do I know if a call was recovered?**
779
+
780
+ A: The `recoverAbandonedCall()` method returns `true` when a call is recovered. Use this to show user notifications or update UI accordingly.
781
+
782
+ **Q: What if the backend is down during recovery?**
783
+
784
+ A: The recovery attempt is logged and the stored state is cleared to prevent infinite retries. The SDK continues working normally. Recovery failures are graceful and don't break the app.
785
+
448
786
  ## Event System
449
787
 
450
788
  The SDK provides a comprehensive event system for managing voice calls:
@@ -458,6 +796,7 @@ The SDK provides a comprehensive event system for managing voice calls:
458
796
  - `message`: Triggered when a message is received (contains transcript and metadata)
459
797
  - `volume-level`: Triggered with volume level updates (number)
460
798
  - `error`: Triggered when an error occurs
799
+ - `call-details-ready`: Triggered when post-call processing completes and call details are available (includes full `CallDTO` with transcript, summary, ratings, and evaluation)
461
800
 
462
801
  ### Event Usage
463
802
 
@@ -475,10 +814,229 @@ call.on('volume-level', level => {
475
814
  call.on('error', error => {
476
815
  console.error('Call error:', error);
477
816
  });
817
+
818
+ // Listen for call details after post-call processing
819
+ call.on('call-details-ready', callDetails => {
820
+ console.log('Post-call feedback ready:', callDetails);
821
+ });
822
+ ```
823
+
824
+ ## Automatic Post-Call Feedback
825
+
826
+ The SDK automatically fetches detailed call information after each call ends and completes post-call processing. This includes comprehensive feedback such as transcript, summary, evaluation metrics, strengths, weaknesses, and ratings.
827
+
828
+ ### How It Works
829
+
830
+ When a call ends, the SDK automatically:
831
+
832
+ 1. Triggers the `call-end` event
833
+ 2. Processes the call on the backend (post-call analysis)
834
+ 3. Fetches complete call details
835
+ 4. Emits the `call-details-ready` event with full `CallDTO` data
836
+
837
+ This happens automatically—you don't need to manually call `getCallDetails()` after each call.
838
+
839
+ ### Event Lifecycle
840
+
841
+ ```typescript
842
+ const call = await client.startCall(simulationId);
843
+
844
+ // 1. Call begins
845
+ call.on('call-start', () => {
846
+ console.log('Call started');
847
+ });
848
+
849
+ // 2. Real-time transcript messages during the call
850
+ call.on('message', message => {
851
+ console.log('Real-time:', message.transcript);
852
+ });
853
+
854
+ // 3. Call ends
855
+ call.on('call-end', () => {
856
+ console.log('Call ended - processing feedback...');
857
+ });
858
+
859
+ // 4. Post-call details are automatically fetched and ready
860
+ call.on('call-details-ready', callDetails => {
861
+ console.log('Post-call feedback is ready!');
862
+
863
+ // Access all call details
864
+ console.log('Summary:', callDetails.summary);
865
+ console.log('Full Transcript:', callDetails.transcript);
866
+ console.log('Call Duration:', callDetails.callDurationMs, 'ms');
867
+ console.log('Success:', callDetails.successEvaluation);
868
+ console.log('Score:', callDetails.score);
869
+
870
+ // Display evaluation metrics
871
+ console.log(`${callDetails.metric1}: ${callDetails.metric1Value}`);
872
+ console.log(`${callDetails.metric2}: ${callDetails.metric2Value}`);
873
+ console.log(`${callDetails.metric3}: ${callDetails.metric3Value}`);
874
+
875
+ // Show strengths and areas for improvement
876
+ callDetails.strengths?.forEach(strength => {
877
+ console.log('✓ Strength:', strength);
878
+ });
879
+
880
+ callDetails.weaknesses?.forEach(weakness => {
881
+ console.log('⚠ Area to improve:', weakness);
882
+ });
883
+
884
+ // Access recording
885
+ if (callDetails.recordingUrl) {
886
+ console.log('Recording:', callDetails.recordingUrl);
887
+ }
888
+ });
889
+ ```
890
+
891
+ ### Practical Use Cases
892
+
893
+ #### 1. Display Post-Call Feedback in UI
894
+
895
+ ```typescript
896
+ // Angular/React example
897
+ async startCall() {
898
+ const call = await this.client.startCall(this.simulationId);
899
+
900
+ // Automatically update UI when feedback is ready
901
+ call.on('call-details-ready', callDetails => {
902
+ this.callSummary = callDetails.summary;
903
+ this.callScore = callDetails.score;
904
+ this.strengths = callDetails.strengths;
905
+ this.weaknesses = callDetails.weaknesses;
906
+ this.showFeedbackModal = true; // Display feedback to user
907
+ });
908
+ }
909
+ ```
910
+
911
+ #### 2. Track Performance Analytics
912
+
913
+ ```typescript
914
+ call.on('call-details-ready', callDetails => {
915
+ // Send analytics to tracking service
916
+ analytics.track('call_completed', {
917
+ callId: callDetails._id,
918
+ duration: callDetails.callDurationMs,
919
+ score: callDetails.score,
920
+ success: callDetails.successEvaluation,
921
+ metrics: {
922
+ [callDetails.metric1]: callDetails.metric1Value,
923
+ [callDetails.metric2]: callDetails.metric2Value,
924
+ [callDetails.metric3]: callDetails.metric3Value,
925
+ },
926
+ });
927
+ });
928
+ ```
929
+
930
+ #### 3. Store Call History
931
+
932
+ ```typescript
933
+ call.on('call-details-ready', async callDetails => {
934
+ // Save to local storage or database
935
+ const callHistory = JSON.parse(localStorage.getItem('call_history') || '[]');
936
+ callHistory.push({
937
+ id: callDetails._id,
938
+ date: callDetails.createdAt,
939
+ summary: callDetails.summary,
940
+ score: callDetails.score,
941
+ });
942
+ localStorage.setItem('call_history', JSON.stringify(callHistory));
943
+ });
478
944
  ```
479
945
 
946
+ #### 4. Generate Learning Insights
947
+
948
+ ```typescript
949
+ call.on('call-details-ready', callDetails => {
950
+ // Aggregate insights across multiple calls
951
+ if (callDetails.successEvaluation) {
952
+ this.successfulCalls++;
953
+ this.successStrategies.push(...(callDetails.strengths || []));
954
+ } else {
955
+ this.areasToImprove.push(...(callDetails.weaknesses || []));
956
+ }
957
+
958
+ this.updateLearningDashboard();
959
+ });
960
+ ```
961
+
962
+ ### Manual Fetching (Alternative Approach)
963
+
964
+ While the SDK automatically fetches call details after each call, you can also manually retrieve them later using the call ID:
965
+
966
+ ```typescript
967
+ // Get call details at any time
968
+ const callDetails = await client.getCallDetails(callId);
969
+ ```
970
+
971
+ This is useful when:
972
+
973
+ - Viewing historical calls
974
+ - Refreshing data after updates
975
+ - Building a call history view
976
+
977
+ ### Error Handling
978
+
979
+ If fetching call details fails after a call ends, the error is logged but does not prevent the `call-end` event from completing. The call will still end gracefully.
980
+
981
+ ```typescript
982
+ call.on('call-end', () => {
983
+ console.log('Call ended successfully');
984
+ // This will always fire, even if call-details-ready fails
985
+ });
986
+
987
+ call.on('call-details-ready', callDetails => {
988
+ // This may not fire if post-call processing fails
989
+ // In that case, you can manually fetch later using getCallDetails()
990
+ });
991
+ ```
992
+
993
+ ### Best Practices
994
+
995
+ 1. **Always subscribe to `call-details-ready`** to capture post-call feedback automatically
996
+ 2. **Show loading state** between `call-end` and `call-details-ready` events
997
+ 3. **Handle missing data gracefully** - some fields may be `null` or `undefined` depending on call status
998
+ 4. **Store call IDs** for later retrieval using `getCallDetails()` if needed
999
+ 5. **Use the event data** to provide immediate feedback to users rather than making additional API calls
1000
+
1001
+ ### Timing Considerations
1002
+
1003
+ - `call-end`: Fires immediately when the call stops
1004
+ - `call-details-ready`: Fires after backend processing completes (typically 2-5 seconds after call ends)
1005
+
1006
+ Plan your UX accordingly—show a loading/processing state between these two events.
1007
+
480
1008
  ## Data Types
481
1009
 
1010
+ ### CallDTO
1011
+
1012
+ Complete call details returned by `call-details-ready` event and `getCallDetails()` method:
1013
+
1014
+ ```typescript
1015
+ interface CallDTO {
1016
+ _id: string; // MongoDB ID of the call
1017
+ callId: string; // Vapi call ID
1018
+ assistantId: string; // ID of the AI assistant used
1019
+ summary?: string; // AI-generated summary of the conversation
1020
+ transcript?: string; // Full transcript of the call
1021
+ recordingUrl?: string; // URL to the call recording
1022
+ rating?: number; // User-provided rating (0-5)
1023
+ successEvaluation?: boolean; // Whether the call was successful
1024
+ score?: number; // Overall score for the call
1025
+ strengths?: string[]; // Array of identified strengths
1026
+ weaknesses?: string[]; // Array of areas for improvement
1027
+ metric1?: string; // Name of evaluation metric 1
1028
+ metric1Value?: number; // Value for metric 1
1029
+ metric2?: string; // Name of evaluation metric 2
1030
+ metric2Value?: number; // Value for metric 2
1031
+ metric3?: string; // Name of evaluation metric 3
1032
+ metric3Value?: number; // Value for metric 3
1033
+ createdAt: Date; // When the call was created
1034
+ endedAt?: Date; // When the call ended
1035
+ callDurationMs?: number; // Duration in milliseconds
1036
+ // Additional fields may be present depending on call status
1037
+ }
1038
+ ```
1039
+
482
1040
  ### CreateSimulationDto
483
1041
 
484
1042
  Configuration for creating a simulation:
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@ctchealth/plato-sdk",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "dependencies": {
5
5
  "tslib": "^2.3.0",
6
6
  "@vapi-ai/web": "2.1.8",
7
- "axios": "^1.7.9"
7
+ "axios": "^1.7.9",
8
+ "pdf-lib": "^1.17.1"
8
9
  },
9
10
  "type": "commonjs",
10
11
  "main": "./src/index.js",
@@ -13,3 +13,4 @@
13
13
  */
14
14
  export declare const MAX_PDF_FILE_SIZE: number;
15
15
  export declare const ALLOWED_PDF_MIME_TYPES: string[];
16
+ export declare const MAX_PDF_PAGES = 100;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ALLOWED_PDF_MIME_TYPES = exports.MAX_PDF_FILE_SIZE = void 0;
3
+ exports.MAX_PDF_PAGES = exports.ALLOWED_PDF_MIME_TYPES = exports.MAX_PDF_FILE_SIZE = void 0;
4
4
  /**
5
5
  * Copyright (c) 2025 ctcHealth. All rights reserved.
6
6
  *
@@ -16,4 +16,5 @@ exports.ALLOWED_PDF_MIME_TYPES = exports.MAX_PDF_FILE_SIZE = void 0;
16
16
  */
17
17
  exports.MAX_PDF_FILE_SIZE = 20 * 1024 * 1024; // 20MB
18
18
  exports.ALLOWED_PDF_MIME_TYPES = ['application/pdf'];
19
+ exports.MAX_PDF_PAGES = 100;
19
20
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/constants.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;GAYG;AACU,QAAA,iBAAiB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAC7C,QAAA,sBAAsB,GAAG,CAAC,iBAAiB,CAAC,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/constants.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;GAYG;AACU,QAAA,iBAAiB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAC7C,QAAA,sBAAsB,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAC7C,QAAA,aAAa,GAAG,GAAG,CAAC"}
@@ -307,3 +307,29 @@ export interface AssistantImageDto {
307
307
  _id: string;
308
308
  imageUrl: string;
309
309
  }
310
+ /**
311
+ * Represents the state of an active call stored in localStorage for recovery purposes.
312
+ * Used to detect and recover abandoned calls after page refresh.
313
+ */
314
+ export interface ActiveCallState {
315
+ /**
316
+ * MongoDB ID of the call record
317
+ */
318
+ callId: string;
319
+ /**
320
+ * External call provider ID
321
+ */
322
+ externalCallId: string;
323
+ /**
324
+ * ID of the simulation this call belongs to
325
+ */
326
+ simulationId: string;
327
+ /**
328
+ * ISO 8601 timestamp when the call was started
329
+ */
330
+ startedAt: string;
331
+ /**
332
+ * Schema version for future compatibility
333
+ */
334
+ version: number;
335
+ }
@@ -3,6 +3,7 @@ export interface ApiClientConfig {
3
3
  baseUrl: string;
4
4
  token?: string;
5
5
  user?: string;
6
+ jwtToken?: string;
6
7
  }
7
8
  export interface ToolCall {
8
9
  function: {
@@ -35,17 +36,30 @@ export interface CallEventMap {
35
36
  [key: string]: unknown;
36
37
  };
37
38
  'volume-level': number;
39
+ 'call-details-ready': CallDTO;
38
40
  }
39
41
  export type CallEventNames = keyof CallEventMap;
40
42
  export type CallEventListener<K extends CallEventNames> = (payload: CallEventMap[K]) => void;
41
43
  export declare class PlatoApiClient {
42
44
  private config;
45
+ private static readonly ACTIVE_CALL_STORAGE_KEY;
43
46
  private http;
44
47
  private eventListeners;
45
48
  private callControllerInstance?;
46
49
  private eventsAttached;
50
+ private currentCallId?;
51
+ private vapiEventNames;
47
52
  eventNames: CallEventNames[];
48
53
  constructor(config: ApiClientConfig);
54
+ /**
55
+ * Update the JWT token for all subsequent requests.
56
+ * Useful when the token is refreshed or when switching user context.
57
+ */
58
+ setJwtToken(jwtToken: string): void;
59
+ /**
60
+ * Remove the JWT token from subsequent requests.
61
+ */
62
+ clearJwtToken(): void;
49
63
  /**
50
64
  * Register a listener for a call event with strict typing.
51
65
  * @param event Event name
@@ -62,6 +76,70 @@ export declare class PlatoApiClient {
62
76
  * Internal: Attach event listeners and propagate to registered listeners.
63
77
  */
64
78
  private attachEvents;
79
+ /**
80
+ * Internal: Emit SDK-specific events that are not part of Vapi.
81
+ */
82
+ private emit;
83
+ /**
84
+ * Store active call state in localStorage for recovery purposes.
85
+ * @private
86
+ */
87
+ private storeCallState;
88
+ /**
89
+ * Retrieve active call state from localStorage.
90
+ * Validates the stored data and clears it if invalid.
91
+ * @private
92
+ * @returns The stored call state or null if not found or invalid
93
+ */
94
+ private getStoredCallState;
95
+ /**
96
+ * Clear active call state from localStorage.
97
+ * @private
98
+ */
99
+ private clearCallState;
100
+ /**
101
+ * Check if a stored call is considered abandoned based on age.
102
+ * Calls older than 5 minutes are considered abandoned.
103
+ * @private
104
+ * @param state The call state to check
105
+ * @returns true if the call is abandoned, false otherwise
106
+ */
107
+ private isCallAbandoned;
108
+ /**
109
+ * Recover and clean up any abandoned calls from previous sessions.
110
+ *
111
+ * This method should be called during application initialization,
112
+ * typically in ngOnInit() or useEffect(). It detects calls that were
113
+ * active when the page was last refreshed and notifies the backend
114
+ * to process them if they're older than 5 minutes.
115
+ *
116
+ * The backend endpoint is idempotent, so calling this method multiple
117
+ * times for the same call is safe.
118
+ *
119
+ * @returns Promise<boolean> - true if an abandoned call was recovered and processed
120
+ *
121
+ * @example
122
+ * // In Angular component
123
+ * async ngOnInit(): Promise<void> {
124
+ * const recovered = await this.platoClient.recoverAbandonedCall();
125
+ * if (recovered) {
126
+ * console.log('Recovered abandoned call from previous session');
127
+ * }
128
+ * }
129
+ *
130
+ * @example
131
+ * // In React component
132
+ * useEffect(() => {
133
+ * platoClient.recoverAbandonedCall()
134
+ * .then(recovered => {
135
+ * if (recovered) {
136
+ * console.log('Recovered abandoned call');
137
+ * }
138
+ * })
139
+ * .catch(console.error);
140
+ * }, []);
141
+ */
142
+ recoverAbandonedCall(): Promise<boolean>;
65
143
  createSimulation(createSimulationParams: CreateSimulationDto): Promise<{
66
144
  simulationId: string;
67
145
  phase: CreationPhase;
@@ -97,6 +175,7 @@ export declare class PlatoApiClient {
97
175
  */
98
176
  off: <K extends CallEventNames>(event: K, listener: CallEventListener<K>) => void;
99
177
  }>;
178
+ private onCallEnded;
100
179
  private createCall;
101
180
  uploadPdfSlides(file: File | Blob): Promise<string>;
102
181
  getRecommendations(): Promise<RecommendationsResponseDto>;
@@ -21,11 +21,25 @@ const utils_1 = require("./utils");
21
21
  const constants_1 = require("./constants");
22
22
  class PlatoApiClient {
23
23
  config;
24
+ static ACTIVE_CALL_STORAGE_KEY = 'plato_active_call';
24
25
  http;
25
26
  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
26
27
  eventListeners = {};
27
28
  callControllerInstance;
28
29
  eventsAttached = false;
30
+ currentCallId;
31
+ // Vapi-native events (events that Vapi SDK supports)
32
+ // Exclude our custom SDK events from this list
33
+ vapiEventNames = [
34
+ 'call-start',
35
+ 'call-end',
36
+ 'speech-start',
37
+ 'speech-end',
38
+ 'error',
39
+ 'message',
40
+ 'volume-level',
41
+ ];
42
+ // All event names including SDK-specific events
29
43
  eventNames = [
30
44
  'call-start',
31
45
  'call-end',
@@ -34,6 +48,7 @@ class PlatoApiClient {
34
48
  'error',
35
49
  'message',
36
50
  'volume-level',
51
+ 'call-details-ready',
37
52
  ];
38
53
  constructor(config) {
39
54
  this.config = config;
@@ -54,9 +69,23 @@ class PlatoApiClient {
54
69
  headers: {
55
70
  'x-api-key': config.token,
56
71
  'x-api-key-user': config.user,
72
+ ...(config.jwtToken && { 'x-client-token': config.jwtToken }),
57
73
  },
58
74
  });
59
75
  }
76
+ /**
77
+ * Update the JWT token for all subsequent requests.
78
+ * Useful when the token is refreshed or when switching user context.
79
+ */
80
+ setJwtToken(jwtToken) {
81
+ this.http.defaults.headers.common['x-client-token'] = jwtToken;
82
+ }
83
+ /**
84
+ * Remove the JWT token from subsequent requests.
85
+ */
86
+ clearJwtToken() {
87
+ delete this.http.defaults.headers.common['x-client-token'];
88
+ }
60
89
  /**
61
90
  * Register a listener for a call event with strict typing.
62
91
  * @param event Event name
@@ -93,12 +122,148 @@ class PlatoApiClient {
93
122
  return;
94
123
  this.eventsAttached = true;
95
124
  const vapi = this.callControllerInstance;
96
- this.eventNames.forEach(event => {
125
+ // Only attach Vapi-native events to the Vapi instance
126
+ this.vapiEventNames.forEach(event => {
97
127
  vapi.on(event, (payload) => {
98
128
  (this.eventListeners[event] || []).forEach(listener => listener(payload));
99
129
  });
100
130
  });
101
131
  }
132
+ /**
133
+ * Internal: Emit SDK-specific events that are not part of Vapi.
134
+ */
135
+ emit(event, payload) {
136
+ const listeners = this.eventListeners[event];
137
+ if (listeners) {
138
+ listeners.forEach(listener => listener(payload));
139
+ }
140
+ }
141
+ /**
142
+ * Store active call state in localStorage for recovery purposes.
143
+ * @private
144
+ */
145
+ storeCallState(state) {
146
+ try {
147
+ localStorage.setItem(PlatoApiClient.ACTIVE_CALL_STORAGE_KEY, JSON.stringify(state));
148
+ }
149
+ catch (error) {
150
+ console.warn('Failed to store call state:', error);
151
+ }
152
+ }
153
+ /**
154
+ * Retrieve active call state from localStorage.
155
+ * Validates the stored data and clears it if invalid.
156
+ * @private
157
+ * @returns The stored call state or null if not found or invalid
158
+ */
159
+ getStoredCallState() {
160
+ try {
161
+ const stored = localStorage.getItem(PlatoApiClient.ACTIVE_CALL_STORAGE_KEY);
162
+ if (!stored) {
163
+ return null;
164
+ }
165
+ const parsed = JSON.parse(stored);
166
+ // Validate required fields
167
+ if (!parsed.callId || !parsed.externalCallId || !parsed.simulationId || !parsed.startedAt) {
168
+ console.warn('Invalid stored call state, clearing');
169
+ this.clearCallState();
170
+ return null;
171
+ }
172
+ return parsed;
173
+ }
174
+ catch (error) {
175
+ console.warn('Failed to retrieve call state:', error);
176
+ return null;
177
+ }
178
+ }
179
+ /**
180
+ * Clear active call state from localStorage.
181
+ * @private
182
+ */
183
+ clearCallState() {
184
+ try {
185
+ localStorage.removeItem(PlatoApiClient.ACTIVE_CALL_STORAGE_KEY);
186
+ }
187
+ catch (error) {
188
+ console.warn('Failed to clear call state:', error);
189
+ }
190
+ }
191
+ /**
192
+ * Check if a stored call is considered abandoned based on age.
193
+ * Calls older than 5 minutes are considered abandoned.
194
+ * @private
195
+ * @param state The call state to check
196
+ * @returns true if the call is abandoned, false otherwise
197
+ */
198
+ isCallAbandoned(state) {
199
+ const ABANDONMENT_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes
200
+ const startedAt = new Date(state.startedAt).getTime();
201
+ const now = Date.now();
202
+ const age = now - startedAt;
203
+ return age > ABANDONMENT_THRESHOLD_MS;
204
+ }
205
+ /**
206
+ * Recover and clean up any abandoned calls from previous sessions.
207
+ *
208
+ * This method should be called during application initialization,
209
+ * typically in ngOnInit() or useEffect(). It detects calls that were
210
+ * active when the page was last refreshed and notifies the backend
211
+ * to process them if they're older than 5 minutes.
212
+ *
213
+ * The backend endpoint is idempotent, so calling this method multiple
214
+ * times for the same call is safe.
215
+ *
216
+ * @returns Promise<boolean> - true if an abandoned call was recovered and processed
217
+ *
218
+ * @example
219
+ * // In Angular component
220
+ * async ngOnInit(): Promise<void> {
221
+ * const recovered = await this.platoClient.recoverAbandonedCall();
222
+ * if (recovered) {
223
+ * console.log('Recovered abandoned call from previous session');
224
+ * }
225
+ * }
226
+ *
227
+ * @example
228
+ * // In React component
229
+ * useEffect(() => {
230
+ * platoClient.recoverAbandonedCall()
231
+ * .then(recovered => {
232
+ * if (recovered) {
233
+ * console.log('Recovered abandoned call');
234
+ * }
235
+ * })
236
+ * .catch(console.error);
237
+ * }, []);
238
+ */
239
+ async recoverAbandonedCall() {
240
+ try {
241
+ const storedState = this.getStoredCallState();
242
+ if (!storedState) {
243
+ return false;
244
+ }
245
+ if (!this.isCallAbandoned(storedState)) {
246
+ return false;
247
+ }
248
+ console.log('Detected abandoned call, notifying backend:', storedState.callId);
249
+ try {
250
+ const response = await this.http.post('/api/v1/postcall/call-ended', {
251
+ callId: storedState.callId,
252
+ });
253
+ console.log('Backend notified of abandoned call:', response.data);
254
+ }
255
+ catch (error) {
256
+ console.error('Failed to notify backend of abandoned call:', error);
257
+ }
258
+ this.clearCallState();
259
+ return true;
260
+ }
261
+ catch (error) {
262
+ console.error('Error during call recovery:', error);
263
+ this.clearCallState();
264
+ return false;
265
+ }
266
+ }
102
267
  async createSimulation(createSimulationParams) {
103
268
  try {
104
269
  const res = await this.http.post('/api/v1/simulation', {
@@ -199,11 +364,34 @@ class PlatoApiClient {
199
364
  this.eventsAttached = false;
200
365
  }
201
366
  async startCall(simulationId) {
367
+ // Check for any previous call state before starting new call
368
+ // If found, notify backend to ensure it gets processed
369
+ const storedState = this.getStoredCallState();
370
+ if (storedState) {
371
+ console.log('Found previous call state, notifying backend before starting new call:', storedState.callId);
372
+ try {
373
+ await this.http.post('/api/v1/postcall/call-ended', {
374
+ callId: storedState.callId,
375
+ });
376
+ console.log('Backend notified of previous call');
377
+ }
378
+ catch (error) {
379
+ console.error('Failed to notify backend of previous call:', error);
380
+ }
381
+ }
382
+ // Now clear the state before starting new call
383
+ this.clearCallState();
202
384
  this.callControllerInstance = new web_1.default('f07d17ec-d4e6-487d-a0b9-0539c01aecbb', 'https://db41aykk1gw9e.cloudfront.net' // base url
203
385
  );
204
386
  if (!this.eventsAttached) {
205
387
  this.attachEvents();
206
388
  }
389
+ // Internal call-end listener
390
+ this.callControllerInstance.on('call-end', () => {
391
+ this.onCallEnded().catch(error => {
392
+ console.error('Error in onCallEnded: ', error);
393
+ });
394
+ });
207
395
  const { data } = await this.http.get(`/api/v1/simulation/${simulationId}`);
208
396
  const assistantId = data;
209
397
  const call = await this.callControllerInstance.start(assistantId);
@@ -215,11 +403,22 @@ class PlatoApiClient {
215
403
  callId: call.id,
216
404
  assistantId: call.assistantId,
217
405
  });
406
+ // Store the callId for use in onCallEnded
407
+ this.currentCallId = apiCall._id;
408
+ // Store call state in localStorage for recovery
409
+ this.storeCallState({
410
+ callId: apiCall._id,
411
+ externalCallId: call.id,
412
+ simulationId: simulationId,
413
+ startedAt: new Date().toISOString(),
414
+ version: 1,
415
+ });
218
416
  // Return stopCall, callId, and event subscription methods with strict typing
219
417
  return {
220
418
  stopCall: () => {
221
419
  this.callControllerInstance?.stop();
222
420
  this.removeAllEventListeners();
421
+ this.clearCallState();
223
422
  },
224
423
  callId: apiCall._id,
225
424
  /**
@@ -239,9 +438,47 @@ class PlatoApiClient {
239
438
  catch (e) {
240
439
  this.callControllerInstance?.stop();
241
440
  this.removeAllEventListeners();
441
+ this.clearCallState();
242
442
  throw e;
243
443
  }
244
444
  }
445
+ async onCallEnded() {
446
+ let callIdForRetry;
447
+ try {
448
+ if (!this.currentCallId) {
449
+ return;
450
+ }
451
+ callIdForRetry = this.currentCallId;
452
+ // First attempt
453
+ let response = await this.http.post('/api/v1/postcall/call-ended', {
454
+ callId: callIdForRetry,
455
+ });
456
+ // If status is "processing", retry once immediately
457
+ if (response.data?.status === 'processing') {
458
+ response = await this.http.post('/api/v1/postcall/call-ended', {
459
+ callId: callIdForRetry,
460
+ });
461
+ }
462
+ // After onCallEnded completes successfully, fetch and emit call details
463
+ try {
464
+ const callDetails = await this.getCallDetails(callIdForRetry);
465
+ this.emit('call-details-ready', callDetails);
466
+ }
467
+ catch (error) {
468
+ console.error('Error fetching call details after call ended:', error);
469
+ // Don't throw - we don't want to break the onCallEnded flow
470
+ }
471
+ }
472
+ catch {
473
+ // Silently handle errors in post-call processing
474
+ }
475
+ finally {
476
+ // Clean up the callId after processing (success or failure)
477
+ this.currentCallId = undefined;
478
+ // Clear stored call state after normal call end
479
+ this.clearCallState();
480
+ }
481
+ }
245
482
  async createCall(payload) {
246
483
  const response = await this.http.post('/api/v1/simulation/call', {
247
484
  ...payload,
@@ -254,6 +491,11 @@ class PlatoApiClient {
254
491
  if (checkResult !== true) {
255
492
  throw new Error(checkResult);
256
493
  }
494
+ // Check PDF page count before proceeding
495
+ const pageCount = await (0, utils_1.getPdfPageCount)(file);
496
+ if (pageCount > constants_1.MAX_PDF_PAGES) {
497
+ throw new Error(`PDF has ${pageCount} pages, which exceeds the maximum allowed page count of ${constants_1.MAX_PDF_PAGES} pages.`);
498
+ }
257
499
  const contentHash = await (0, utils_1.calculateHash)(file);
258
500
  const filename = file instanceof File ? file.name : file.filename;
259
501
  if (!filename) {
@@ -1 +1 @@
1
- {"version":3,"file":"plato-sdk.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/plato-sdk.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plato-sdk.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/plato-sdk.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,3 @@
1
- /**
2
- * Copyright (c) 2025 ctcHealth. All rights reserved.
3
- *
4
- * This file is part of the ctcHealth Plato Platform, a proprietary software system developed by ctcHealth.
5
- *
6
- * This source code and all related materials are confidential and proprietary to ctcHealth.
7
- * Unauthorized access, use, copying, modification, distribution, or disclosure is strictly prohibited
8
- * and may result in disciplinary action and civil and/or criminal penalties.
9
- *
10
- * This software is intended solely for authorized use within ctcHealth and its designated partners.
11
- *
12
- * For internal use only.
13
- */
14
1
  /**
15
2
  * Validates a file against size and type constraints.
16
3
  *
@@ -27,3 +14,11 @@ export declare function checkFile(file: File | Blob, maxFileSize: number, allowe
27
14
  * @returns A promise that resolves to the hexadecimal SHA-256 hash.
28
15
  */
29
16
  export declare function calculateHash(file: File | Blob): Promise<string>;
17
+ /**
18
+ * Gets the page count of a PDF file.
19
+ *
20
+ * @param file - The PDF file or blob to check.
21
+ * @returns A promise that resolves to the number of pages in the PDF.
22
+ * @throws Error if the PDF cannot be parsed.
23
+ */
24
+ export declare function getPdfPageCount(file: File | Blob): Promise<number>;
package/src/lib/utils.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.checkFile = checkFile;
4
4
  exports.calculateHash = calculateHash;
5
+ exports.getPdfPageCount = getPdfPageCount;
5
6
  /**
6
7
  * Copyright (c) 2025 ctcHealth. All rights reserved.
7
8
  *
@@ -15,6 +16,7 @@ exports.calculateHash = calculateHash;
15
16
  *
16
17
  * For internal use only.
17
18
  */
19
+ const pdf_lib_1 = require("pdf-lib");
18
20
  /**
19
21
  * Validates a file against size and type constraints.
20
22
  *
@@ -47,4 +49,22 @@ async function calculateHash(file) {
47
49
  const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
48
50
  return hashHex;
49
51
  }
52
+ /**
53
+ * Gets the page count of a PDF file.
54
+ *
55
+ * @param file - The PDF file or blob to check.
56
+ * @returns A promise that resolves to the number of pages in the PDF.
57
+ * @throws Error if the PDF cannot be parsed.
58
+ */
59
+ async function getPdfPageCount(file) {
60
+ try {
61
+ const arrayBuffer = await file.arrayBuffer();
62
+ const pdf = await pdf_lib_1.PDFDocument.load(arrayBuffer);
63
+ return pdf.getPageCount();
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : 'Unknown error';
67
+ throw new Error(`Failed to read PDF page count: ${message}`);
68
+ }
69
+ }
50
70
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/utils.ts"],"names":[],"mappings":";;AAqBA,8BAgBC;AAQD,sCAMC;AAnDD;;;;;;;;;;;;GAYG;AACH;;;;;;;GAOG;AACH,SAAgB,SAAS,CACvB,IAAiB,EACjB,WAAmB,EACnB,gBAA0B;IAE1B,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,EAAE,CAAC;QAC5B,MAAM,cAAc,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,CAAC,WAAW,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC3D,OAAO,cAAc,cAAc,4CAA4C,SAAS,MAAM,CAAC;IACjG,CAAC;IAED,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAO,sBAAsB,IAAI,CAAC,IAAI,wBAAwB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAC/F,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,aAAa,CAAC,IAAiB;IACnD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7E,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/utils.ts"],"names":[],"mappings":";;AAuBA,8BAgBC;AAQD,sCAMC;AASD,0CASC;AAvED;;;;;;;;;;;;GAYG;AACH,qCAAsC;AAEtC;;;;;;;GAOG;AACH,SAAgB,SAAS,CACvB,IAAiB,EACjB,WAAmB,EACnB,gBAA0B;IAE1B,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,EAAE,CAAC;QAC5B,MAAM,cAAc,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC9D,MAAM,SAAS,GAAG,CAAC,WAAW,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC3D,OAAO,cAAc,cAAc,4CAA4C,SAAS,MAAM,CAAC;IACjG,CAAC;IAED,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAO,sBAAsB,IAAI,CAAC,IAAI,wBAAwB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAC/F,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,aAAa,CAAC,IAAiB;IACnD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7E,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,eAAe,CAAC,IAAiB;IACrD,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,MAAM,qBAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChD,OAAO,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,kCAAkC,OAAO,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC"}