@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 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 using a Bearer token. Include your JWT token in the `API-AUTH` header:
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
- token: 'your-api-token',
43
- user: 'test@test.test',
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
- presentation: 'Oral tablets, 10 tablets per pack',
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.token` (string): Your API authentication token
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
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 with JWT token:**
134
+ **Example:**
142
135
 
143
136
  ```typescript
144
137
  const client = new PlatoApiClient({
145
138
  baseUrl: 'https://your-plato-api.com',
146
- token: 'your-api-key',
147
- user: 'user@example.com',
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
- token: 'your-token',
659
- user: 'your-user',
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
- token: 'your-token',
1408
- user: 'your-user',
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctchealth/plato-sdk",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "dependencies": {
5
5
  "tslib": "^2.3.0",
6
6
  "@vapi-ai/web": "2.1.8",
@@ -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;
@@ -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
- token?: string;
63
- user?: string;
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': clientToken,
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
- 'f07d17ec-d4e6-487d-a0b9-0539c01aecbb',
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
  }