@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 +560 -2
- package/package.json +3 -2
- package/src/lib/constants.d.ts +1 -0
- package/src/lib/constants.js +2 -1
- package/src/lib/constants.js.map +1 -1
- package/src/lib/plato-intefaces.d.ts +26 -0
- package/src/lib/plato-sdk.d.ts +79 -0
- package/src/lib/plato-sdk.js +243 -1
- package/src/lib/plato-sdk.js.map +1 -1
- package/src/lib/utils.d.ts +8 -13
- package/src/lib/utils.js +20 -0
- package/src/lib/utils.js.map +1 -1
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
|
|
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.
|
|
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",
|
package/src/lib/constants.d.ts
CHANGED
package/src/lib/constants.js
CHANGED
|
@@ -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
|
package/src/lib/constants.js.map
CHANGED
|
@@ -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
|
+
}
|
package/src/lib/plato-sdk.d.ts
CHANGED
|
@@ -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>;
|
package/src/lib/plato-sdk.js
CHANGED
|
@@ -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
|
-
|
|
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) {
|
package/src/lib/plato-sdk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plato-sdk.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/plato-sdk.ts"],"names":[],"mappings":";;;;AAAA;;;;;;;;;;;;GAYG;AACH,0DAA6C;AAgB7C,+DAAgC;AAEhC,mCAAmD;AACnD,2CAAwE;AA8CxE,MAAa,cAAc;IAgBL;IAfZ,IAAI,CAAgB;IAC5B,sEAAsE;IAC9D,cAAc,GAAgD,EAAE,CAAC;IACjE,sBAAsB,CAAQ;IAC9B,cAAc,GAAG,KAAK,CAAC;IAC/B,UAAU,GAAqB;QAC7B,YAAY;QACZ,UAAU;QACV,cAAc;QACd,YAAY;QACZ,OAAO;QACP,SAAS;QACT,cAAc;KACf,CAAC;IAEF,YAAoB,MAAuB;QAAvB,WAAM,GAAN,MAAM,CAAiB;QACzC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,CAAC,IAAI,GAAG,eAAK,CAAC,MAAM,CAAC;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE;gBACP,WAAW,EAAE,MAAM,CAAC,KAAK;gBACzB,gBAAgB,EAAE,MAAM,CAAC,IAAI;aAC9B;SACF,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACK,EAAE,CAA2B,KAAQ,EAAE,QAA8B;QAC3E,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAClC,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,SAAS,EAAE,CAAC;YACd,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,IAAI,CAAC,sBAAsB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACxD,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,GAAG,CAA2B,KAAQ,EAAE,QAA8B;QAC5E,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,CAAC,SAAS;YAAE,OAAO;QACvB,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,CAAC,sBAAsB;YAAE,OAAO;QAChE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,sBAAsB,CAAC;QAEzC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAC9B,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,OAAqC,EAAE,EAAE;gBACvD,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAC5E,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,sBAA2C;QAIhE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE;gBACrD,GAAG,sBAAsB;aAC1B,CAAC,CAAC;YACH,OAAO;gBACL,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY;gBACnC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;aACtB,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACxE,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,YAAoB;QAG9C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,6BAA6B,YAAY,EAAE,CAAC,CAAC;QAE7E,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;YACvE,OAAO,GAAG,CAAC,IAAI,CAAC;QAClB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC7E,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,YAAoB;QAC7C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,8BAA8B,YAAY,EAAE,CAAC,CAAC;YAC9E,OAAO,GAAG,CAAC,IAA4B,CAAC;QAC1C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/E,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc;QACjC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,2BAA2B,MAAM,EAAE,CAAC,CAAC;YACrE,OAAO,GAAG,CAAC,IAAe,CAAC;QAC7B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACzE,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,WAAyC;QAEzC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,oCAAoC,EAAE;gBACpE,MAAM,EAAE,WAAW;aACpB,CAAC,CAAC;YACH,OAAO,GAAG,CAAC,IAAiC,CAAC;QAC/C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5E,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,MAAc;QACnC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,sCAAsC,MAAM,EAAE,CAAC,CAAC;YAChF,OAAO,GAAG,CAAC,IAAc,CAAC;QAC5B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3E,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED;;OAEG;IACK,uBAAuB;QAC7B,IAAI,CAAC,IAAI,CAAC,sBAAsB;YAAE,OAAO;QACzC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAC9B,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;gBACpD,6DAA6D;gBAC7D,mBAAmB;gBACnB,IAAI,CAAC,sBAAsB,EAAE,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,YAAoB;QAClC,IAAI,CAAC,sBAAsB,GAAG,IAAI,aAAI,CACpC,sCAAsC,EACtC,sCAAsC,CAAC,WAAW;SACnD,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,sBAAsB,YAAY,EAAE,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAG,IAAc,CAAC;QACnC,MAAM,IAAI,GAAgB,MAAM,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAE/E,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;gBACpC,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,WAAW,EAAE,IAAI,CAAC,WAAW;aAC9B,CAAC,CAAC;YAEH,6EAA6E;YAC7E,OAAO;gBACL,QAAQ,EAAE,GAAG,EAAE;oBACb,IAAI,CAAC,sBAAsB,EAAE,IAAI,EAAE,CAAC;oBACpC,IAAI,CAAC,uBAAuB,EAAE,CAAC;gBACjC,CAAC;gBACD,MAAM,EAAE,OAAO,CAAC,GAAG;gBACnB;;;;mBAIG;gBACH,EAAE,EAAE,CAA2B,KAAQ,EAAE,QAA8B,EAAE,EAAE,CACzE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;gBAC1B;;;;mBAIG;gBACH,GAAG,EAAE,CAA2B,KAAQ,EAAE,QAA8B,EAAE,EAAE,CAC1E,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC;aAC5B,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,sBAAsB,EAAE,IAAI,EAAE,CAAC;YACpC,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC/B,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,OAAsB;QAC7C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE;YAC/D,GAAG,OAAO;SACX,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC,IAAe,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAiB;QACrC,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAA,iBAAS,EAAC,IAAI,EAAE,6BAAiB,EAAE,kCAAsB,CAAC,CAAC;YAE/E,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;YAC/B,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,IAAA,qBAAa,EAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,QAAQ,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,IAA8B,CAAC,QAAQ,CAAC;YAE7F,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;YACJ,CAAC;YAED,IAAI,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CACb,kHAAkH,CACnH,CAAC;YACJ,CAAC;YAED,MAAM,EAAE,aAAa,EAAE,GAAG,CACxB,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAA2B,kCAAkC,EAAE;gBACjF,WAAW;gBACX,QAAQ;aACT,CAAC,CACH,CAAC,IAAI,CAAC;YAEP,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;gBAC5D,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAE9B,MAAM,eAAK,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE;gBAC5C,OAAO,EAAE;oBACP,cAAc,EAAE,qBAAqB;iBACtC;aACF,CAAC,CAAC;YAEH;;;;;;cAME;YAEF,OAAO,uBAAuB,CAAC;QACjC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;YACvF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CACX,6BAA6B,EAC7B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CACjD,CAAC;YACJ,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAA6B,yBAAyB,CAAC,CAAC;YACvF,OAAO,GAAG,CAAC,IAAI,CAAC;QAClB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5E,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,WAAsC;QAC5D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAiB,mBAAmB,EAAE;gBACnE,MAAM,EAAE,WAAW;aACpB,CAAC,CAAC;YACH,OAAO,GAAG,CAAC,IAAI,CAAC;QAClB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAChF,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,EAAU;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAc,qBAAqB,EAAE,EAAE,CAAC,CAAC;YACxE,OAAO,GAAG,CAAC,IAAI,CAAC;QAClB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACrF,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,EAAU;QAClC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAChF,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAsB,0BAA0B,CAAC,CAAC;YACjF,OAAO,GAAG,CAAC,IAAI,CAAC;QAClB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,eAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC7E,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;CACF;AAxXD,wCAwXC"}
|
|
1
|
+
{"version":3,"file":"plato-sdk.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/plato-sdk.ts"],"names":[],"mappings":"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"}
|
package/src/lib/utils.d.ts
CHANGED
|
@@ -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
|
package/src/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/utils.ts"],"names":[],"mappings":";;
|
|
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"}
|