@ctchealth/plato-sdk 0.0.1
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 +222 -0
- package/package.json +14 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +5 -0
- package/src/index.js.map +1 -0
- package/src/lib/plato-intefaces.d.ts +171 -0
- package/src/lib/plato-intefaces.js +86 -0
- package/src/lib/plato-intefaces.js.map +1 -0
- package/src/lib/plato-sdk.d.ts +77 -0
- package/src/lib/plato-sdk.js +166 -0
- package/src/lib/plato-sdk.js.map +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Plato SDK
|
|
2
|
+
|
|
3
|
+
A TypeScript SDK for interacting with the Plato API to create and manage AI-powered medical training simulations.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Plato SDK provides a simple and type-safe way to integrate with the Plato platform, allowing you to create medical training simulations with AI personas and manage voice-based interactions.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 🎭 Create AI personas with customizable professional profiles and personalities
|
|
12
|
+
- 🗣️ Real-time voice interactions with AI assistants
|
|
13
|
+
- 📊 Comprehensive event system for call management
|
|
14
|
+
- 🔒 Type-safe API with full TypeScript support
|
|
15
|
+
- 🎯 Medical training simulation configuration
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install plato-sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { PlatoApiClient } from 'plato-sdk';
|
|
27
|
+
|
|
28
|
+
// Initialize the client
|
|
29
|
+
const client = new PlatoApiClient({
|
|
30
|
+
baseUrl: 'https://your-plato-api.com',
|
|
31
|
+
token: 'your-api-token',
|
|
32
|
+
user: 'test@test.test'
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Create a simulation
|
|
36
|
+
const simulation = await client.createSimulation({
|
|
37
|
+
persona: {
|
|
38
|
+
name: "Dr. Smith",
|
|
39
|
+
professionalProfile: {
|
|
40
|
+
practiceSettings: "Hospital",
|
|
41
|
+
yearOfExperience: 10,
|
|
42
|
+
specialityAndDepartment: "Cardiology",
|
|
43
|
+
location: "New York"
|
|
44
|
+
},
|
|
45
|
+
segment: "The Traditionalist",
|
|
46
|
+
personalityAndBehaviour: {
|
|
47
|
+
riskTolerance: 3,
|
|
48
|
+
researchOrientation: 40,
|
|
49
|
+
recognitionNeed: 2,
|
|
50
|
+
brandLoyalty: 50,
|
|
51
|
+
patientEmpathy: 4,
|
|
52
|
+
trainingDifficulty: 3,
|
|
53
|
+
friendliness: 4
|
|
54
|
+
},
|
|
55
|
+
context: {
|
|
56
|
+
subSpecialityOrTherapyFocus: "Heart failure",
|
|
57
|
+
typicalPatientMix: "Elderly patients",
|
|
58
|
+
keyClinicalDrivers: "Evidence-based medicine"
|
|
59
|
+
},
|
|
60
|
+
assistantGender: "Male"
|
|
61
|
+
},
|
|
62
|
+
product: {
|
|
63
|
+
name: "CardioMed Pro",
|
|
64
|
+
description: "Advanced cardiac medication"
|
|
65
|
+
},
|
|
66
|
+
scenario: "Discussing treatment options for heart failure",
|
|
67
|
+
trainingConfiguration: {
|
|
68
|
+
trainingDifficulty: 3,
|
|
69
|
+
communicationFormality: 4,
|
|
70
|
+
friendlinessLevel: 4,
|
|
71
|
+
subjectMatterExpertise: 5
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Start a voice call
|
|
76
|
+
const call = await client.startCall(simulation.simulationId);
|
|
77
|
+
|
|
78
|
+
// Listen to call events
|
|
79
|
+
call.on('call-start', () => {
|
|
80
|
+
console.log('Call started');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
call.on('message', (message) => {
|
|
84
|
+
console.log('Message received:', message.transcript);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
call.on('call-end', () => {
|
|
88
|
+
console.log('Call ended');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Stop the call when done
|
|
92
|
+
call.stopCall();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## API Reference
|
|
96
|
+
|
|
97
|
+
### PlatoApiClient
|
|
98
|
+
|
|
99
|
+
The main class for interacting with the Plato API.
|
|
100
|
+
|
|
101
|
+
#### Constructor
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
new PlatoApiClient(config: ApiClientConfig)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Parameters:**
|
|
108
|
+
- `config.baseUrl` (string): The base URL of the Plato API
|
|
109
|
+
- `config.token` (string): Your API authentication token
|
|
110
|
+
- `config.user` (string): Your user identifier
|
|
111
|
+
|
|
112
|
+
#### Methods
|
|
113
|
+
|
|
114
|
+
##### createSimulation(params: CreateSimulationDto)
|
|
115
|
+
|
|
116
|
+
Creates a new medical training simulation.
|
|
117
|
+
|
|
118
|
+
**Returns:** `Promise<{ simulationId: string }>`
|
|
119
|
+
|
|
120
|
+
##### startCall(simulationId: string)
|
|
121
|
+
|
|
122
|
+
Starts a voice call with the AI persona for the specified simulation.
|
|
123
|
+
|
|
124
|
+
**Returns:** Object with:
|
|
125
|
+
- `stopCall()`: Function to end the call
|
|
126
|
+
- `callId`: Unique identifier for the call
|
|
127
|
+
- `on<K>(event: K, listener: CallEventListener<K>)`: Subscribe to call events
|
|
128
|
+
- `off<K>(event: K, listener: CallEventListener<K>)`: Unsubscribe from call events
|
|
129
|
+
|
|
130
|
+
## Event System
|
|
131
|
+
|
|
132
|
+
The SDK provides a comprehensive event system for managing voice calls:
|
|
133
|
+
|
|
134
|
+
### Available Events
|
|
135
|
+
|
|
136
|
+
- `call-start`: Triggered when a call begins
|
|
137
|
+
- `call-end`: Triggered when a call ends
|
|
138
|
+
- `speech-start`: Triggered when speech detection starts
|
|
139
|
+
- `speech-end`: Triggered when speech detection ends
|
|
140
|
+
- `message`: Triggered when a message is received (contains transcript and metadata)
|
|
141
|
+
- `volume-level`: Triggered with volume level updates (number)
|
|
142
|
+
- `error`: Triggered when an error occurs
|
|
143
|
+
|
|
144
|
+
### Event Usage
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// Subscribe to events
|
|
148
|
+
call.on('message', (message) => {
|
|
149
|
+
console.log('Transcript:', message.transcript);
|
|
150
|
+
console.log('Type:', message.transcriptType); // 'final' or 'partial'
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
call.on('volume-level', (level) => {
|
|
154
|
+
console.log('Volume level:', level);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
call.on('error', (error) => {
|
|
158
|
+
console.error('Call error:', error);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Unsubscribe from events
|
|
162
|
+
const messageHandler = (message) => console.log(message);
|
|
163
|
+
call.on('message', messageHandler);
|
|
164
|
+
call.off('message', messageHandler);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Data Types
|
|
168
|
+
|
|
169
|
+
### CreateSimulationDto
|
|
170
|
+
|
|
171
|
+
Configuration for creating a simulation:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
interface CreateSimulationDto {
|
|
175
|
+
persona: CharacterCreateDto;
|
|
176
|
+
product: ProductConfig;
|
|
177
|
+
presentation?: string;
|
|
178
|
+
scenario: string;
|
|
179
|
+
objectives?: string[];
|
|
180
|
+
anticipatedObjections?: string[];
|
|
181
|
+
trainingConfiguration: TrainingConfigurationDto;
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### CharacterCreateDto
|
|
186
|
+
|
|
187
|
+
AI persona configuration:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
interface CharacterCreateDto {
|
|
191
|
+
name: string;
|
|
192
|
+
professionalProfile: ProfessionalProfileDto;
|
|
193
|
+
segment: SegmentType;
|
|
194
|
+
personalityAndBehaviour: PersonalityAndBehaviourDto;
|
|
195
|
+
context: ContextDto;
|
|
196
|
+
assistantGender: AssistantVoiceGender;
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Error Handling
|
|
201
|
+
|
|
202
|
+
The SDK throws errors for invalid configurations and API failures:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
try {
|
|
206
|
+
const client = new PlatoApiClient({
|
|
207
|
+
baseUrl: 'https://api.plato.com',
|
|
208
|
+
token: 'your-token',
|
|
209
|
+
user: 'your-user'
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const simulation = await client.createSimulation(simulationConfig);
|
|
213
|
+
const call = await client.startCall(simulation.simulationId);
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.error('Error:', error.message);
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
## Support
|
|
221
|
+
|
|
222
|
+
For support and questions, please contact the development team or create an issue in the project repository.
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ctchealth/plato-sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"tslib": "^2.3.0"
|
|
6
|
+
},
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"main": "./src/index.js",
|
|
9
|
+
"typings": "./src/index.d.ts",
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"types": "./src/index.d.ts"
|
|
14
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/plato-sdk';
|
package/src/index.js
ADDED
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/plato-sdk/src/index.ts"],"names":[],"mappings":";;;AAAA,0DAAgC"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
export declare enum YearOfExperience {
|
|
2
|
+
'1-5' = "1-5 years",
|
|
3
|
+
'6-10' = "6-10 years",
|
|
4
|
+
'11-20' = "16-20 years",
|
|
5
|
+
'20+' = "20+ years"
|
|
6
|
+
}
|
|
7
|
+
export declare enum PracticeType {
|
|
8
|
+
Private = "Private Practice",
|
|
9
|
+
Hospital = "Hospital",
|
|
10
|
+
AcademicMedicalCenter = "Academic Medical Center",
|
|
11
|
+
Clinic = "Clinic"
|
|
12
|
+
}
|
|
13
|
+
export declare enum SegmentType {
|
|
14
|
+
Traditionalist = "The Traditionalist",
|
|
15
|
+
Innovator = "The Innovator",
|
|
16
|
+
PatientOrientedPhysician = "The Patient-Oriented Physician",
|
|
17
|
+
FinanciallyDrivenPrescriber = "The Financially-Driven Prescriber",
|
|
18
|
+
EvidencePurist = "The Evidence-Purist",
|
|
19
|
+
CostConsciousPrescriber = "The Cost-Conscious Prescriber"
|
|
20
|
+
}
|
|
21
|
+
export declare enum AssistantVoiceGender {
|
|
22
|
+
Male = "Male",
|
|
23
|
+
Female = "Female"
|
|
24
|
+
}
|
|
25
|
+
export declare class PersonalityAndBehaviourDto {
|
|
26
|
+
riskTolerance: number;
|
|
27
|
+
researchOrientation: number;
|
|
28
|
+
recognitionNeed: number;
|
|
29
|
+
brandLoyalty: number;
|
|
30
|
+
patientEmpathy: number;
|
|
31
|
+
trainingDifficulty: number;
|
|
32
|
+
friendliness: number;
|
|
33
|
+
}
|
|
34
|
+
export declare class ProfessionalProfileDto {
|
|
35
|
+
practiceSettings: string;
|
|
36
|
+
yearOfExperience: number;
|
|
37
|
+
specialityAndDepartment: string;
|
|
38
|
+
location: string;
|
|
39
|
+
}
|
|
40
|
+
export declare class ContextDto {
|
|
41
|
+
subSpecialityOrTherapyFocus: string;
|
|
42
|
+
typicalPatientMix: string;
|
|
43
|
+
keyClinicalDrivers: string;
|
|
44
|
+
}
|
|
45
|
+
export declare class CharacterCreateDto {
|
|
46
|
+
name: string;
|
|
47
|
+
professionalProfile: ProfessionalProfileDto;
|
|
48
|
+
segment: SegmentType;
|
|
49
|
+
personalityAndBehaviour: PersonalityAndBehaviourDto;
|
|
50
|
+
context: ContextDto;
|
|
51
|
+
assistantGender: AssistantVoiceGender;
|
|
52
|
+
}
|
|
53
|
+
export declare class ProductConfig {
|
|
54
|
+
name: string;
|
|
55
|
+
description: string;
|
|
56
|
+
}
|
|
57
|
+
export declare class TrainingConfigurationDto {
|
|
58
|
+
readonly trainingDifficulty: number;
|
|
59
|
+
readonly communicationFormality: number;
|
|
60
|
+
readonly friendlinessLevel: number;
|
|
61
|
+
readonly subjectMatterExpertise: number;
|
|
62
|
+
}
|
|
63
|
+
export declare class CreateSimulationDto {
|
|
64
|
+
persona: CharacterCreateDto;
|
|
65
|
+
product: ProductConfig;
|
|
66
|
+
presentation?: string;
|
|
67
|
+
scenario: string;
|
|
68
|
+
objectives?: string[];
|
|
69
|
+
anticipatedObjections?: string[];
|
|
70
|
+
trainingConfiguration: TrainingConfigurationDto;
|
|
71
|
+
}
|
|
72
|
+
export interface CallCreateDto {
|
|
73
|
+
/**
|
|
74
|
+
* Call ID obtained
|
|
75
|
+
*/
|
|
76
|
+
callId: string;
|
|
77
|
+
/**
|
|
78
|
+
* Call Assistant ID
|
|
79
|
+
*/
|
|
80
|
+
assistantId: string;
|
|
81
|
+
}
|
|
82
|
+
export interface CallDTO {
|
|
83
|
+
/**
|
|
84
|
+
* call ID
|
|
85
|
+
*/
|
|
86
|
+
_id: string;
|
|
87
|
+
/**
|
|
88
|
+
* call ID obtained
|
|
89
|
+
*/
|
|
90
|
+
callId: string;
|
|
91
|
+
/**
|
|
92
|
+
* call User ID
|
|
93
|
+
*/
|
|
94
|
+
platoUserId: string;
|
|
95
|
+
/**
|
|
96
|
+
* call Assistant ID
|
|
97
|
+
*/
|
|
98
|
+
assistantId: string;
|
|
99
|
+
/**
|
|
100
|
+
* call summary of the conversation
|
|
101
|
+
*/
|
|
102
|
+
summary: string;
|
|
103
|
+
/**
|
|
104
|
+
* call transcript of the conversation
|
|
105
|
+
*/
|
|
106
|
+
transcript: string;
|
|
107
|
+
/**
|
|
108
|
+
* call feedback provided by the user
|
|
109
|
+
*/
|
|
110
|
+
feedback: string;
|
|
111
|
+
/**
|
|
112
|
+
* Success Evaluation returned by model
|
|
113
|
+
*/
|
|
114
|
+
successEvaluation: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* call Recording URL
|
|
117
|
+
*/
|
|
118
|
+
recordingUrl: string;
|
|
119
|
+
/**
|
|
120
|
+
* Date and Time of the creation of the message
|
|
121
|
+
*/
|
|
122
|
+
createdAt: Date;
|
|
123
|
+
/**
|
|
124
|
+
* Date and Time of the creation of the message
|
|
125
|
+
*/
|
|
126
|
+
endedAt: Date;
|
|
127
|
+
/**
|
|
128
|
+
* Rating of the call given by the user
|
|
129
|
+
*/
|
|
130
|
+
rating: number;
|
|
131
|
+
/**
|
|
132
|
+
* Main strenghts of the user conversation based on the analysis of the AI
|
|
133
|
+
*/
|
|
134
|
+
strengths: Array<string>;
|
|
135
|
+
/**
|
|
136
|
+
* Main weak points of the user conversation based on the analysis of the AI
|
|
137
|
+
*/
|
|
138
|
+
weaknesses: Array<string>;
|
|
139
|
+
/**
|
|
140
|
+
* Name of Metric for the AI feedback report
|
|
141
|
+
*/
|
|
142
|
+
metric1: string;
|
|
143
|
+
/**
|
|
144
|
+
* Name of Metric for the AI feedback report
|
|
145
|
+
*/
|
|
146
|
+
metric2: string;
|
|
147
|
+
/**
|
|
148
|
+
* Name of Metric for the AI feedback report
|
|
149
|
+
*/
|
|
150
|
+
metric3: string;
|
|
151
|
+
/**
|
|
152
|
+
* AI feedback value for Metric 1
|
|
153
|
+
*/
|
|
154
|
+
metric1Value: number;
|
|
155
|
+
/**
|
|
156
|
+
* AI feedback value for Metric 2
|
|
157
|
+
*/
|
|
158
|
+
metric2Value: number;
|
|
159
|
+
/**
|
|
160
|
+
* AI feedback value for Metric 3
|
|
161
|
+
*/
|
|
162
|
+
metric3Value: number;
|
|
163
|
+
/**
|
|
164
|
+
* AI feedback value for the call score
|
|
165
|
+
*/
|
|
166
|
+
score?: number;
|
|
167
|
+
/**
|
|
168
|
+
* Defines if the calls will be consider for the memory feature
|
|
169
|
+
*/
|
|
170
|
+
inMemory: boolean;
|
|
171
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CreateSimulationDto = exports.TrainingConfigurationDto = exports.ProductConfig = exports.CharacterCreateDto = exports.ContextDto = exports.ProfessionalProfileDto = exports.PersonalityAndBehaviourDto = exports.AssistantVoiceGender = exports.SegmentType = exports.PracticeType = exports.YearOfExperience = void 0;
|
|
4
|
+
var YearOfExperience;
|
|
5
|
+
(function (YearOfExperience) {
|
|
6
|
+
YearOfExperience["1-5"] = "1-5 years";
|
|
7
|
+
YearOfExperience["6-10"] = "6-10 years";
|
|
8
|
+
YearOfExperience["11-20"] = "16-20 years";
|
|
9
|
+
YearOfExperience["20+"] = "20+ years";
|
|
10
|
+
})(YearOfExperience || (exports.YearOfExperience = YearOfExperience = {}));
|
|
11
|
+
var PracticeType;
|
|
12
|
+
(function (PracticeType) {
|
|
13
|
+
PracticeType["Private"] = "Private Practice";
|
|
14
|
+
PracticeType["Hospital"] = "Hospital";
|
|
15
|
+
PracticeType["AcademicMedicalCenter"] = "Academic Medical Center";
|
|
16
|
+
PracticeType["Clinic"] = "Clinic";
|
|
17
|
+
})(PracticeType || (exports.PracticeType = PracticeType = {}));
|
|
18
|
+
var SegmentType;
|
|
19
|
+
(function (SegmentType) {
|
|
20
|
+
SegmentType["Traditionalist"] = "The Traditionalist";
|
|
21
|
+
SegmentType["Innovator"] = "The Innovator";
|
|
22
|
+
SegmentType["PatientOrientedPhysician"] = "The Patient-Oriented Physician";
|
|
23
|
+
SegmentType["FinanciallyDrivenPrescriber"] = "The Financially-Driven Prescriber";
|
|
24
|
+
SegmentType["EvidencePurist"] = "The Evidence-Purist";
|
|
25
|
+
SegmentType["CostConsciousPrescriber"] = "The Cost-Conscious Prescriber";
|
|
26
|
+
})(SegmentType || (exports.SegmentType = SegmentType = {}));
|
|
27
|
+
var AssistantVoiceGender;
|
|
28
|
+
(function (AssistantVoiceGender) {
|
|
29
|
+
AssistantVoiceGender["Male"] = "Male";
|
|
30
|
+
AssistantVoiceGender["Female"] = "Female";
|
|
31
|
+
})(AssistantVoiceGender || (exports.AssistantVoiceGender = AssistantVoiceGender = {}));
|
|
32
|
+
class PersonalityAndBehaviourDto {
|
|
33
|
+
riskTolerance;
|
|
34
|
+
researchOrientation;
|
|
35
|
+
recognitionNeed;
|
|
36
|
+
brandLoyalty;
|
|
37
|
+
patientEmpathy;
|
|
38
|
+
trainingDifficulty;
|
|
39
|
+
friendliness;
|
|
40
|
+
}
|
|
41
|
+
exports.PersonalityAndBehaviourDto = PersonalityAndBehaviourDto;
|
|
42
|
+
class ProfessionalProfileDto {
|
|
43
|
+
practiceSettings;
|
|
44
|
+
yearOfExperience;
|
|
45
|
+
specialityAndDepartment;
|
|
46
|
+
location;
|
|
47
|
+
}
|
|
48
|
+
exports.ProfessionalProfileDto = ProfessionalProfileDto;
|
|
49
|
+
class ContextDto {
|
|
50
|
+
subSpecialityOrTherapyFocus;
|
|
51
|
+
typicalPatientMix;
|
|
52
|
+
keyClinicalDrivers;
|
|
53
|
+
}
|
|
54
|
+
exports.ContextDto = ContextDto;
|
|
55
|
+
class CharacterCreateDto {
|
|
56
|
+
name;
|
|
57
|
+
professionalProfile;
|
|
58
|
+
segment;
|
|
59
|
+
personalityAndBehaviour;
|
|
60
|
+
context;
|
|
61
|
+
assistantGender;
|
|
62
|
+
}
|
|
63
|
+
exports.CharacterCreateDto = CharacterCreateDto;
|
|
64
|
+
class ProductConfig {
|
|
65
|
+
name;
|
|
66
|
+
description;
|
|
67
|
+
}
|
|
68
|
+
exports.ProductConfig = ProductConfig;
|
|
69
|
+
class TrainingConfigurationDto {
|
|
70
|
+
trainingDifficulty;
|
|
71
|
+
communicationFormality;
|
|
72
|
+
friendlinessLevel;
|
|
73
|
+
subjectMatterExpertise;
|
|
74
|
+
}
|
|
75
|
+
exports.TrainingConfigurationDto = TrainingConfigurationDto;
|
|
76
|
+
class CreateSimulationDto {
|
|
77
|
+
persona;
|
|
78
|
+
product;
|
|
79
|
+
presentation;
|
|
80
|
+
scenario;
|
|
81
|
+
objectives;
|
|
82
|
+
anticipatedObjections;
|
|
83
|
+
trainingConfiguration;
|
|
84
|
+
}
|
|
85
|
+
exports.CreateSimulationDto = CreateSimulationDto;
|
|
86
|
+
//# sourceMappingURL=plato-intefaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plato-intefaces.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/plato-intefaces.ts"],"names":[],"mappings":";;;AAAA,IAAY,gBAKX;AALD,WAAY,gBAAgB;IAC1B,qCAAmB,CAAA;IACnB,uCAAqB,CAAA;IACrB,yCAAuB,CAAA;IACvB,qCAAmB,CAAA;AACrB,CAAC,EALW,gBAAgB,gCAAhB,gBAAgB,QAK3B;AAGD,IAAY,YAKX;AALD,WAAY,YAAY;IACtB,4CAA4B,CAAA;IAC5B,qCAAqB,CAAA;IACrB,iEAAiD,CAAA;IACjD,iCAAiB,CAAA;AACnB,CAAC,EALW,YAAY,4BAAZ,YAAY,QAKvB;AACD,IAAY,WAOX;AAPD,WAAY,WAAW;IACrB,oDAAqC,CAAA;IACrC,0CAA2B,CAAA;IAC3B,0EAA2D,CAAA;IAC3D,gFAAiE,CAAA;IACjE,qDAAsC,CAAA;IACtC,wEAAyD,CAAA;AAC3D,CAAC,EAPW,WAAW,2BAAX,WAAW,QAOtB;AAED,IAAY,oBAGX;AAHD,WAAY,oBAAoB;IAC9B,qCAAa,CAAA;IACb,yCAAiB,CAAA;AACnB,CAAC,EAHW,oBAAoB,oCAApB,oBAAoB,QAG/B;AAED,MAAa,0BAA0B;IACrC,aAAa,CAAU;IACvB,mBAAmB,CAAU;IAC7B,eAAe,CAAU;IACzB,YAAY,CAAU;IACtB,cAAc,CAAU;IACxB,kBAAkB,CAAU;IAC5B,YAAY,CAAU;CACvB;AARD,gEAQC;AAED,MAAa,sBAAsB;IACjC,gBAAgB,CAAU;IAC1B,gBAAgB,CAAU;IAC1B,uBAAuB,CAAU;IACjC,QAAQ,CAAU;CACnB;AALD,wDAKC;AAED,MAAa,UAAU;IACrB,2BAA2B,CAAU;IACrC,iBAAiB,CAAU;IAC3B,kBAAkB,CAAU;CAC7B;AAJD,gCAIC;AAED,MAAa,kBAAkB;IAC7B,IAAI,CAAU;IACd,mBAAmB,CAA0B;IAC7C,OAAO,CAAgB;IACvB,uBAAuB,CAA8B;IACrD,OAAO,CAAc;IACrB,eAAe,CAAyB;CACzC;AAPD,gDAOC;AAED,MAAa,aAAa;IACxB,IAAI,CAAU;IACd,WAAW,CAAU;CACtB;AAHD,sCAGC;AAED,MAAa,wBAAwB;IAC1B,kBAAkB,CAAU;IAC5B,sBAAsB,CAAU;IAChC,iBAAiB,CAAU;IAC3B,sBAAsB,CAAU;CAC1C;AALD,4DAKC;AAED,MAAa,mBAAmB;IAC9B,OAAO,CAAsB;IAC7B,OAAO,CAAiB;IACxB,YAAY,CAAU;IACtB,QAAQ,CAAU;IAClB,UAAU,CAAY;IACtB,qBAAqB,CAAY;IACjC,qBAAqB,CAA4B;CAClD;AARD,kDAQC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { CreateSimulationDto } from './plato-intefaces';
|
|
2
|
+
export interface ApiClientConfig {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
token?: string;
|
|
5
|
+
user?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Event map for call events, providing strict typing for each event's payload.
|
|
9
|
+
*/
|
|
10
|
+
export interface CallEventMap {
|
|
11
|
+
'call-start': void;
|
|
12
|
+
'call-end': void;
|
|
13
|
+
'speech-start': void;
|
|
14
|
+
'speech-end': void;
|
|
15
|
+
'error': Error;
|
|
16
|
+
'message': {
|
|
17
|
+
type: string;
|
|
18
|
+
role: string;
|
|
19
|
+
transcript?: string;
|
|
20
|
+
transcriptType: 'final' | 'partial';
|
|
21
|
+
toolCallList?: any[];
|
|
22
|
+
toolCalls?: any[];
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
};
|
|
25
|
+
'volume-level': number;
|
|
26
|
+
}
|
|
27
|
+
export type CallEventNames = keyof CallEventMap;
|
|
28
|
+
export type CallEventListener<K extends CallEventNames> = (payload: CallEventMap[K]) => void;
|
|
29
|
+
export declare class PlatoApiClient {
|
|
30
|
+
private config;
|
|
31
|
+
private http;
|
|
32
|
+
private eventListeners;
|
|
33
|
+
private callControllerInstance?;
|
|
34
|
+
private eventsAttached;
|
|
35
|
+
eventNames: CallEventNames[];
|
|
36
|
+
constructor(config: ApiClientConfig);
|
|
37
|
+
/**
|
|
38
|
+
* Register a listener for a call event with strict typing.
|
|
39
|
+
* @param event Event name
|
|
40
|
+
* @param listener Listener function
|
|
41
|
+
*/
|
|
42
|
+
on<K extends CallEventNames>(event: K, listener: CallEventListener<K>): void;
|
|
43
|
+
/**
|
|
44
|
+
* Remove a listener for a call event with strict typing.
|
|
45
|
+
* @param event Event name
|
|
46
|
+
* @param listener Listener function
|
|
47
|
+
*/
|
|
48
|
+
off<K extends CallEventNames>(event: K, listener: CallEventListener<K>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Internal: Attach event listeners and propagate to registered listeners.
|
|
51
|
+
*/
|
|
52
|
+
private attachEvents;
|
|
53
|
+
createSimulation(createSimulationParams: CreateSimulationDto): Promise<{
|
|
54
|
+
simulationId: string;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Remove all listeners for all call events.
|
|
58
|
+
*/
|
|
59
|
+
private removeAllEventListeners;
|
|
60
|
+
startCall(simulationId: string): Promise<{
|
|
61
|
+
stopCall: () => void;
|
|
62
|
+
callId: string;
|
|
63
|
+
/**
|
|
64
|
+
* Subscribe to call events for this call with strict typing.
|
|
65
|
+
* @param event Event name
|
|
66
|
+
* @param listener Listener function
|
|
67
|
+
*/
|
|
68
|
+
on: <K extends CallEventNames>(event: K, listener: CallEventListener<K>) => void;
|
|
69
|
+
/**
|
|
70
|
+
* Unsubscribe from call events for this call with strict typing.
|
|
71
|
+
* @param event Event name
|
|
72
|
+
* @param listener Listener function
|
|
73
|
+
*/
|
|
74
|
+
off: <K extends CallEventNames>(event: K, listener: CallEventListener<K>) => void;
|
|
75
|
+
}>;
|
|
76
|
+
private createCall;
|
|
77
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PlatoApiClient = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const axios_1 = tslib_1.__importDefault(require("axios"));
|
|
6
|
+
const web_1 = tslib_1.__importDefault(require("@vapi-ai/web"));
|
|
7
|
+
class PlatoApiClient {
|
|
8
|
+
config;
|
|
9
|
+
http;
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
11
|
+
eventListeners = {};
|
|
12
|
+
callControllerInstance;
|
|
13
|
+
eventsAttached = false;
|
|
14
|
+
eventNames = [
|
|
15
|
+
'call-start',
|
|
16
|
+
'call-end',
|
|
17
|
+
'speech-start',
|
|
18
|
+
'speech-end',
|
|
19
|
+
'error',
|
|
20
|
+
'message',
|
|
21
|
+
'volume-level',
|
|
22
|
+
];
|
|
23
|
+
constructor(config) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
if (!config.baseUrl) {
|
|
26
|
+
throw new Error('baseUrl is required');
|
|
27
|
+
}
|
|
28
|
+
if (!config.token) {
|
|
29
|
+
throw new Error('token is required');
|
|
30
|
+
}
|
|
31
|
+
if (!config.user) {
|
|
32
|
+
throw new Error('user is required');
|
|
33
|
+
}
|
|
34
|
+
if (config.baseUrl.endsWith('/')) {
|
|
35
|
+
config.baseUrl = config.baseUrl.slice(0, -1);
|
|
36
|
+
}
|
|
37
|
+
this.http = axios_1.default.create({
|
|
38
|
+
baseURL: config.baseUrl,
|
|
39
|
+
headers: {
|
|
40
|
+
'x-api-key': config.token,
|
|
41
|
+
'x-api-key-user': config.user,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Register a listener for a call event with strict typing.
|
|
47
|
+
* @param event Event name
|
|
48
|
+
* @param listener Listener function
|
|
49
|
+
*/
|
|
50
|
+
on(event, listener) {
|
|
51
|
+
if (!this.eventListeners[event]) {
|
|
52
|
+
this.eventListeners[event] = [];
|
|
53
|
+
}
|
|
54
|
+
this.eventListeners[event].push(listener);
|
|
55
|
+
if (this.callControllerInstance && !this.eventsAttached) {
|
|
56
|
+
this.attachEvents();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Remove a listener for a call event with strict typing.
|
|
61
|
+
* @param event Event name
|
|
62
|
+
* @param listener Listener function
|
|
63
|
+
*/
|
|
64
|
+
off(event, listener) {
|
|
65
|
+
if (!this.eventListeners[event])
|
|
66
|
+
return;
|
|
67
|
+
this.eventListeners[event] = this.eventListeners[event].filter(l => l !== listener);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Internal: Attach event listeners and propagate to registered listeners.
|
|
71
|
+
*/
|
|
72
|
+
attachEvents() {
|
|
73
|
+
if (this.eventsAttached || !this.callControllerInstance)
|
|
74
|
+
return;
|
|
75
|
+
this.eventsAttached = true;
|
|
76
|
+
const vapi = this.callControllerInstance;
|
|
77
|
+
this.eventNames.forEach(event => {
|
|
78
|
+
vapi.on(event, (payload) => {
|
|
79
|
+
(this.eventListeners[event] || []).forEach(listener => listener(payload));
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
async createSimulation(createSimulationParams) {
|
|
84
|
+
try {
|
|
85
|
+
const res = await this.http.post('/api/v1/simulation', {
|
|
86
|
+
...createSimulationParams,
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
simulationId: res.data,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
if (axios_1.default.isAxiosError(e)) {
|
|
94
|
+
console.error('Error creating simulation:', e.response?.data.message);
|
|
95
|
+
}
|
|
96
|
+
throw e;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Remove all listeners for all call events.
|
|
101
|
+
*/
|
|
102
|
+
removeAllEventListeners() {
|
|
103
|
+
if (!this.callControllerInstance)
|
|
104
|
+
return;
|
|
105
|
+
this.eventNames.forEach(event => {
|
|
106
|
+
(this.eventListeners[event] || []).forEach(listener => {
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
108
|
+
// @ts-expect-error
|
|
109
|
+
this.callControllerInstance?.off(event, listener);
|
|
110
|
+
});
|
|
111
|
+
this.eventListeners[event] = [];
|
|
112
|
+
});
|
|
113
|
+
this.eventsAttached = false;
|
|
114
|
+
}
|
|
115
|
+
async startCall(simulationId) {
|
|
116
|
+
this.callControllerInstance = new web_1.default('677157de-0e16-4a6e-90d8-ab53ac1dbaab', 'https://d3mddz7y4coq6s.cloudfront.net');
|
|
117
|
+
if (!this.eventsAttached) {
|
|
118
|
+
this.attachEvents();
|
|
119
|
+
}
|
|
120
|
+
const { data } = await this.http.get(`/api/v1/simulation/${simulationId}`);
|
|
121
|
+
const assistantId = data;
|
|
122
|
+
const call = await this.callControllerInstance.start(assistantId);
|
|
123
|
+
if (!call || !call.assistantId) {
|
|
124
|
+
throw new Error('Cannot start a call, please try again later');
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const apiCall = await this.createCall({
|
|
128
|
+
callId: call.id,
|
|
129
|
+
assistantId: call.assistantId,
|
|
130
|
+
});
|
|
131
|
+
// Return stopCall, callId, and event subscription methods with strict typing
|
|
132
|
+
return {
|
|
133
|
+
stopCall: () => {
|
|
134
|
+
this.callControllerInstance?.stop();
|
|
135
|
+
this.removeAllEventListeners();
|
|
136
|
+
},
|
|
137
|
+
callId: apiCall._id,
|
|
138
|
+
/**
|
|
139
|
+
* Subscribe to call events for this call with strict typing.
|
|
140
|
+
* @param event Event name
|
|
141
|
+
* @param listener Listener function
|
|
142
|
+
*/
|
|
143
|
+
on: (event, listener) => this.on(event, listener),
|
|
144
|
+
/**
|
|
145
|
+
* Unsubscribe from call events for this call with strict typing.
|
|
146
|
+
* @param event Event name
|
|
147
|
+
* @param listener Listener function
|
|
148
|
+
*/
|
|
149
|
+
off: (event, listener) => this.off(event, listener),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
this.callControllerInstance?.stop();
|
|
154
|
+
this.removeAllEventListeners();
|
|
155
|
+
throw e;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async createCall(payload) {
|
|
159
|
+
const response = await this.http.post('/api/v1/simulation/call', {
|
|
160
|
+
...payload,
|
|
161
|
+
});
|
|
162
|
+
return response.data;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
exports.PlatoApiClient = PlatoApiClient;
|
|
166
|
+
//# sourceMappingURL=plato-sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plato-sdk.js","sourceRoot":"","sources":["../../../../../libs/plato-sdk/src/lib/plato-sdk.ts"],"names":[],"mappings":";;;;AAAA,0DAA6C;AAE7C,+DAAgC;AAkChC,MAAa,cAAc;IAiBL;IAhBZ,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;IAGF,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;IACH,EAAE,CAA2B,KAAQ,EAAE,QAA8B;QACnE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAClC,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,IAAI,CAAC,sBAAsB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACxD,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,GAAG,CAA2B,KAAQ,EAAE,QAA8B;QACpE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;YAAE,OAAO;QACxC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC;IACvF,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,OAAY,EAAE,EAAE;gBAC9B,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;QAGhE,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;aACvB,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;;OAEG;IACK,uBAAuB;QAE7B,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,uCAAuC,CACxC,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,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;gBACpG;;;;mBAIG;gBACH,GAAG,EAAE,CAA2B,KAAQ,EAAE,QAA8B,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC;aACvG,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;CACF;AA3KD,wCA2KC"}
|