@ctchealth/plato-sdk 0.0.17 → 0.0.19
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 +35 -24
- package/package.json +1 -1
- package/src/lib/plato-intefaces.ts +3 -1
- package/src/lib/plato-sdk.ts +22 -35
package/README.md
CHANGED
|
@@ -8,13 +8,7 @@ The Plato SDK provides a simple and type-safe way to integrate with the Plato pl
|
|
|
8
8
|
|
|
9
9
|
## Authentication
|
|
10
10
|
|
|
11
|
-
All API requests require authentication
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
API-AUTH: Bearer <your-jwt-token>
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Requests without a valid JWT token will be rejected with a `401 Unauthorized` response.
|
|
11
|
+
All API requests require authentication via a client token. Pass a pre-signed JWT token as `jwtToken` when initializing the client. This is sent as the `x-client-token` header on every request.
|
|
18
12
|
|
|
19
13
|
## Features
|
|
20
14
|
|
|
@@ -39,8 +33,8 @@ import { PlatoApiClient, AvatarLanguage } from 'plato-sdk';
|
|
|
39
33
|
// Initialize the client
|
|
40
34
|
const client = new PlatoApiClient({
|
|
41
35
|
baseUrl: 'https://your-plato-api.com',
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
jwtToken: 'your-jwt-token',
|
|
37
|
+
publicKey: 'your-public-key',
|
|
44
38
|
});
|
|
45
39
|
|
|
46
40
|
// Get available assistant images
|
|
@@ -76,7 +70,7 @@ const simulation = await client.createSimulation({
|
|
|
76
70
|
description:
|
|
77
71
|
'A nonsteroidal anti-inflammatory drug used to reduce pain, inflammation, and fever',
|
|
78
72
|
},
|
|
79
|
-
|
|
73
|
+
pdfSlideId: 'pdf-slide-id', // optional, ID from uploadPdfSlides()
|
|
80
74
|
scenario: 'Discussing treatment options for an elderly patient with chronic arthritis',
|
|
81
75
|
objectives:
|
|
82
76
|
'Demonstrate efficacy of Ibuprofen in pain management Highlight safety profile and contraindications Encourage patient adherence',
|
|
@@ -133,19 +127,17 @@ new PlatoApiClient(config: ApiClientConfig)
|
|
|
133
127
|
|
|
134
128
|
**Parameters:**
|
|
135
129
|
|
|
136
|
-
- `config.baseUrl` (string): The base URL of the Plato API
|
|
137
|
-
- `config.
|
|
138
|
-
- `config.
|
|
139
|
-
- `config.jwtToken` (string, optional): A per-user JWT token sent as the `x-client-token` header on every request
|
|
130
|
+
- `config.baseUrl` (string, required): The base URL of the Plato API
|
|
131
|
+
- `config.jwtToken` (string, required): A pre-signed JWT token sent as the `x-client-token` header on every request
|
|
132
|
+
- `config.publicKey` (string, required): Your public key for voice call functionality
|
|
140
133
|
|
|
141
|
-
**Example
|
|
134
|
+
**Example:**
|
|
142
135
|
|
|
143
136
|
```typescript
|
|
144
137
|
const client = new PlatoApiClient({
|
|
145
138
|
baseUrl: 'https://your-plato-api.com',
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
jwtToken: 'eyJhbGciOiJSUzI1NiIs...', // optional, per-user token
|
|
139
|
+
jwtToken: 'eyJhbGciOiJSUzI1NiIs...',
|
|
140
|
+
publicKey: 'your-public-key',
|
|
149
141
|
});
|
|
150
142
|
```
|
|
151
143
|
|
|
@@ -218,6 +210,24 @@ const callDetails = await client.getCallDetails(call._id);
|
|
|
218
210
|
console.log('Call Summary:', callDetails.summary);
|
|
219
211
|
```
|
|
220
212
|
|
|
213
|
+
##### deleteCall(callId: string)
|
|
214
|
+
|
|
215
|
+
Deletes a single call and all associated data including messages, recommendations, and the S3 recording. Only the owner of the call (the rep who made it) can delete it.
|
|
216
|
+
|
|
217
|
+
**Parameters:**
|
|
218
|
+
|
|
219
|
+
- `callId` (string): The MongoDB `_id` of the call to delete
|
|
220
|
+
|
|
221
|
+
**Returns:** `Promise<void>`
|
|
222
|
+
|
|
223
|
+
**Example:**
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
await client.deleteCall('507f1f77bcf86cd799439011');
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Note:** This action is irreversible. The call, its transcript, messages, recording, and any recommendations generated from it will be permanently removed.
|
|
230
|
+
|
|
221
231
|
##### getCallRecordings(queryParams: SimulationRecordingsQueryDto)
|
|
222
232
|
|
|
223
233
|
Retrieves a paginated list of call recordings for the authenticated user.
|
|
@@ -655,8 +665,8 @@ import { PlatoApiClient } from 'plato-sdk';
|
|
|
655
665
|
function TrainingApp() {
|
|
656
666
|
const [platoClient] = useState(() => new PlatoApiClient({
|
|
657
667
|
baseUrl: 'https://your-api.com',
|
|
658
|
-
|
|
659
|
-
|
|
668
|
+
jwtToken: 'your-jwt-token',
|
|
669
|
+
publicKey: 'your-public-key',
|
|
660
670
|
}));
|
|
661
671
|
|
|
662
672
|
useEffect(() => {
|
|
@@ -1151,13 +1161,12 @@ Configuration for creating a simulation:
|
|
|
1151
1161
|
interface CreateSimulationDto {
|
|
1152
1162
|
persona: CharacterCreateDto;
|
|
1153
1163
|
product: ProductConfig;
|
|
1154
|
-
presentation?: string;
|
|
1155
1164
|
scenario: string;
|
|
1156
1165
|
objectives?: string;
|
|
1157
1166
|
anticipatedObjections?: string;
|
|
1158
|
-
trainingConfiguration: TrainingConfigurationDto;
|
|
1159
1167
|
imageId: string;
|
|
1160
1168
|
avatarLanguage: AvatarLanguage;
|
|
1169
|
+
pdfSlideId?: string;
|
|
1161
1170
|
}
|
|
1162
1171
|
```
|
|
1163
1172
|
|
|
@@ -1393,6 +1402,8 @@ enum AvatarLanguage {
|
|
|
1393
1402
|
Spanish = 'es',
|
|
1394
1403
|
Italian = 'it',
|
|
1395
1404
|
French = 'fr',
|
|
1405
|
+
Arabic = 'ar',
|
|
1406
|
+
Russian = 'ru',
|
|
1396
1407
|
}
|
|
1397
1408
|
```
|
|
1398
1409
|
|
|
@@ -1404,8 +1415,8 @@ The SDK throws errors for invalid configurations and API failures:
|
|
|
1404
1415
|
try {
|
|
1405
1416
|
const client = new PlatoApiClient({
|
|
1406
1417
|
baseUrl: 'https://api.plato.com',
|
|
1407
|
-
|
|
1408
|
-
|
|
1418
|
+
jwtToken: 'your-jwt-token',
|
|
1419
|
+
publicKey: 'your-public-key',
|
|
1409
1420
|
});
|
|
1410
1421
|
|
|
1411
1422
|
const simulation = await client.createSimulation(simulationConfig);
|
package/package.json
CHANGED
|
@@ -44,6 +44,8 @@ export enum AvatarLanguage {
|
|
|
44
44
|
Spanish = 'es',
|
|
45
45
|
Italian = 'it',
|
|
46
46
|
French = 'fr',
|
|
47
|
+
Arabic = 'ar',
|
|
48
|
+
Russian = 'ru',
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
export class PersonalityAndBehaviourDto {
|
|
@@ -84,12 +86,12 @@ export class ProductConfig {
|
|
|
84
86
|
export class CreateSimulationDto {
|
|
85
87
|
persona!: CharacterCreateDto;
|
|
86
88
|
product!: ProductConfig;
|
|
87
|
-
presentation?: string;
|
|
88
89
|
scenario!: string;
|
|
89
90
|
objectives?: string;
|
|
90
91
|
anticipatedObjections?: string;
|
|
91
92
|
imageId!: string;
|
|
92
93
|
avatarLanguage!: AvatarLanguage;
|
|
94
|
+
pdfSlideId?: string;
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
export type RecordingsLimit = 5 | 10 | 25;
|
package/src/lib/plato-sdk.ts
CHANGED
|
@@ -34,34 +34,10 @@ import { Call } from '@vapi-ai/web/dist/api';
|
|
|
34
34
|
import { checkFile, calculateHash, getPdfPageCount } from './utils';
|
|
35
35
|
import { MAX_PDF_FILE_SIZE, ALLOWED_PDF_MIME_TYPES, MAX_PDF_PAGES } from './constants';
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
* Encodes API key and user into a ClientToken (base64 JSON) for x-client-token header.
|
|
39
|
-
* The API decodes this to extract Token and User for validation.
|
|
40
|
-
*/
|
|
41
|
-
function encodeApiKeyClientToken(token: string, user: string): string {
|
|
42
|
-
const payload = {
|
|
43
|
-
Token: token,
|
|
44
|
-
User: user,
|
|
45
|
-
UserId: user,
|
|
46
|
-
Exp: Math.floor(Date.now() / 1000) + 86400, // 24h
|
|
47
|
-
};
|
|
48
|
-
const json = JSON.stringify(payload);
|
|
49
|
-
if (typeof Buffer !== 'undefined') {
|
|
50
|
-
return Buffer.from(json, 'utf8').toString('base64');
|
|
51
|
-
}
|
|
52
|
-
const bytes = new TextEncoder().encode(json);
|
|
53
|
-
let binary = '';
|
|
54
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
55
|
-
binary += String.fromCharCode(bytes[i]);
|
|
56
|
-
}
|
|
57
|
-
return btoa(binary);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
37
|
export interface ApiClientConfig {
|
|
61
38
|
baseUrl: string;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
jwtToken?: string;
|
|
39
|
+
jwtToken: string;
|
|
40
|
+
publicKey: string;
|
|
65
41
|
}
|
|
66
42
|
|
|
67
43
|
export interface ToolCall {
|
|
@@ -139,22 +115,15 @@ export class PlatoApiClient {
|
|
|
139
115
|
if (!config.baseUrl) {
|
|
140
116
|
throw new Error('baseUrl is required');
|
|
141
117
|
}
|
|
142
|
-
const token = config.token;
|
|
143
|
-
const user = config.user;
|
|
144
|
-
if (!token || !user) {
|
|
145
|
-
throw new Error('token and user are required');
|
|
146
|
-
}
|
|
147
118
|
|
|
148
119
|
if (config.baseUrl.endsWith('/')) {
|
|
149
120
|
config.baseUrl = config.baseUrl.slice(0, -1);
|
|
150
121
|
}
|
|
151
122
|
|
|
152
|
-
const clientToken = config.jwtToken ? config.jwtToken : encodeApiKeyClientToken(token, user);
|
|
153
|
-
|
|
154
123
|
this.http = axios.create({
|
|
155
124
|
baseURL: config.baseUrl,
|
|
156
125
|
headers: {
|
|
157
|
-
'x-client-token':
|
|
126
|
+
'x-client-token': config.jwtToken,
|
|
158
127
|
},
|
|
159
128
|
});
|
|
160
129
|
}
|
|
@@ -515,7 +484,7 @@ export class PlatoApiClient {
|
|
|
515
484
|
this.clearCallState();
|
|
516
485
|
|
|
517
486
|
this.callControllerInstance = new Vapi(
|
|
518
|
-
|
|
487
|
+
this.config.publicKey,
|
|
519
488
|
'https://db41aykk1gw9e.cloudfront.net' // base url
|
|
520
489
|
);
|
|
521
490
|
if (!this.eventsAttached) {
|
|
@@ -786,4 +755,22 @@ export class PlatoApiClient {
|
|
|
786
755
|
throw e;
|
|
787
756
|
}
|
|
788
757
|
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Deletes a call and all associated data (messages, recommendations, recording).
|
|
761
|
+
* Only the owner of the call can delete it.
|
|
762
|
+
* @param callId - MongoDB ObjectId of the call
|
|
763
|
+
* @throws 404 if call not found
|
|
764
|
+
* @throws 403 if the caller is not the call owner
|
|
765
|
+
*/
|
|
766
|
+
async deleteCall(callId: string): Promise<void> {
|
|
767
|
+
try {
|
|
768
|
+
await this.http.delete(`/api/v1/simulation/call/${callId}`);
|
|
769
|
+
} catch (e) {
|
|
770
|
+
if (axios.isAxiosError(e)) {
|
|
771
|
+
console.error('Error deleting call:', e.response?.data.message);
|
|
772
|
+
}
|
|
773
|
+
throw e;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
789
776
|
}
|