@ctchealth/plato-sdk 0.0.9 → 0.0.10
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 +99 -17
- package/package.json +4 -3
- package/src/index.d.ts +14 -0
- package/src/index.js +18 -0
- package/src/index.js.map +1 -0
- package/src/lib/plato-intefaces.d.ts +243 -0
- package/src/lib/plato-intefaces.js +124 -0
- package/src/lib/plato-intefaces.js.map +1 -0
- package/src/lib/plato-sdk.d.ts +102 -0
- package/src/lib/plato-sdk.js +257 -0
- package/src/lib/plato-sdk.js.map +1 -0
- package/eslint.config.cjs +0 -121
- package/jest.config.ts +0 -10
- package/project.json +0 -24
- package/src/index.ts +0 -1
- package/src/lib/plato-intefaces.ts +0 -232
- package/src/lib/plato-sdk.ts +0 -265
- package/tsconfig.json +0 -22
- package/tsconfig.lib.json +0 -11
- package/tsconfig.spec.json +0 -10
package/src/lib/plato-sdk.ts
DELETED
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import axios, { AxiosInstance } from 'axios';
|
|
2
|
-
import {
|
|
3
|
-
CallCreateDto,
|
|
4
|
-
CallDTO,
|
|
5
|
-
CreateSimulationDto,
|
|
6
|
-
CreationPhase,
|
|
7
|
-
SimulationRecordingsDto,
|
|
8
|
-
SimulationRecordingsQueryDto,
|
|
9
|
-
} from './plato-intefaces';
|
|
10
|
-
import Vapi from '@vapi-ai/web';
|
|
11
|
-
import { Call } from '@vapi-ai/web/dist/api';
|
|
12
|
-
|
|
13
|
-
export interface ApiClientConfig {
|
|
14
|
-
baseUrl: string;
|
|
15
|
-
token?: string;
|
|
16
|
-
user?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Event map for call events, providing strict typing for each event's payload.
|
|
21
|
-
*/
|
|
22
|
-
export interface CallEventMap {
|
|
23
|
-
'call-start': void;
|
|
24
|
-
'call-end': void;
|
|
25
|
-
'speech-start': void;
|
|
26
|
-
'speech-end': void;
|
|
27
|
-
error: Error;
|
|
28
|
-
message: {
|
|
29
|
-
type: string;
|
|
30
|
-
role: string;
|
|
31
|
-
transcript?: string;
|
|
32
|
-
transcriptType: 'final' | 'partial';
|
|
33
|
-
toolCallList?: any[];
|
|
34
|
-
toolCalls?: any[];
|
|
35
|
-
[key: string]: any;
|
|
36
|
-
};
|
|
37
|
-
'volume-level': number;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type CallEventNames = keyof CallEventMap;
|
|
41
|
-
|
|
42
|
-
export type CallEventListener<K extends CallEventNames> = (payload: CallEventMap[K]) => void;
|
|
43
|
-
|
|
44
|
-
export class PlatoApiClient {
|
|
45
|
-
private http: AxiosInstance;
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
47
|
-
private eventListeners: Partial<Record<CallEventNames, Function[]>> = {};
|
|
48
|
-
private callControllerInstance?: Vapi;
|
|
49
|
-
private eventsAttached = false;
|
|
50
|
-
eventNames: CallEventNames[] = [
|
|
51
|
-
'call-start',
|
|
52
|
-
'call-end',
|
|
53
|
-
'speech-start',
|
|
54
|
-
'speech-end',
|
|
55
|
-
'error',
|
|
56
|
-
'message',
|
|
57
|
-
'volume-level',
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
constructor(private config: ApiClientConfig) {
|
|
61
|
-
if (!config.baseUrl) {
|
|
62
|
-
throw new Error('baseUrl is required');
|
|
63
|
-
}
|
|
64
|
-
if (!config.token) {
|
|
65
|
-
throw new Error('token is required');
|
|
66
|
-
}
|
|
67
|
-
if (!config.user) {
|
|
68
|
-
throw new Error('user is required');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (config.baseUrl.endsWith('/')) {
|
|
72
|
-
config.baseUrl = config.baseUrl.slice(0, -1);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
this.http = axios.create({
|
|
76
|
-
baseURL: config.baseUrl,
|
|
77
|
-
headers: {
|
|
78
|
-
'x-api-key': config.token,
|
|
79
|
-
'x-api-key-user': config.user,
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Register a listener for a call event with strict typing.
|
|
86
|
-
* @param event Event name
|
|
87
|
-
* @param listener Listener function
|
|
88
|
-
*/
|
|
89
|
-
private on<K extends CallEventNames>(event: K, listener: CallEventListener<K>): void {
|
|
90
|
-
if (!this.eventListeners[event]) {
|
|
91
|
-
this.eventListeners[event] = [];
|
|
92
|
-
}
|
|
93
|
-
this.eventListeners[event]!.push(listener);
|
|
94
|
-
if (this.callControllerInstance && !this.eventsAttached) {
|
|
95
|
-
this.attachEvents();
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Remove a listener for a call event with strict typing.
|
|
101
|
-
* @param event Event name
|
|
102
|
-
* @param listener Listener function
|
|
103
|
-
*/
|
|
104
|
-
private off<K extends CallEventNames>(event: K, listener: CallEventListener<K>): void {
|
|
105
|
-
if (!this.eventListeners[event]) return;
|
|
106
|
-
this.eventListeners[event] = this.eventListeners[event]!.filter(l => l !== listener);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Internal: Attach event listeners and propagate to registered listeners.
|
|
111
|
-
*/
|
|
112
|
-
private attachEvents(): void {
|
|
113
|
-
if (this.eventsAttached || !this.callControllerInstance) return;
|
|
114
|
-
this.eventsAttached = true;
|
|
115
|
-
const vapi = this.callControllerInstance;
|
|
116
|
-
|
|
117
|
-
this.eventNames.forEach(event => {
|
|
118
|
-
vapi.on(event, (payload: any) => {
|
|
119
|
-
(this.eventListeners[event] || []).forEach(listener => listener(payload));
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async createSimulation(createSimulationParams: CreateSimulationDto): Promise<{
|
|
125
|
-
simulationId: string;
|
|
126
|
-
phase: CreationPhase;
|
|
127
|
-
}> {
|
|
128
|
-
try {
|
|
129
|
-
const res = await this.http.post('/api/v1/simulation', {
|
|
130
|
-
...createSimulationParams,
|
|
131
|
-
});
|
|
132
|
-
return {
|
|
133
|
-
simulationId: res.data.simulationId,
|
|
134
|
-
phase: res.data.phase,
|
|
135
|
-
};
|
|
136
|
-
} catch (e) {
|
|
137
|
-
if (axios.isAxiosError(e)) {
|
|
138
|
-
console.error('Error creating simulation:', e.response?.data.message);
|
|
139
|
-
}
|
|
140
|
-
throw e;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async checkSimulationStatus(simulationId: string): Promise<{
|
|
145
|
-
phase: CreationPhase;
|
|
146
|
-
}> {
|
|
147
|
-
const res = await this.http.get(`/api/v1/simulation/status/${simulationId}`);
|
|
148
|
-
|
|
149
|
-
return res.data;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async getCallDetails(callId: string): Promise<CallDTO> {
|
|
153
|
-
try {
|
|
154
|
-
const res = await this.http.get(`/api/v1/simulation/call/${callId}`);
|
|
155
|
-
return res.data as CallDTO;
|
|
156
|
-
} catch (e) {
|
|
157
|
-
if (axios.isAxiosError(e)) {
|
|
158
|
-
console.error('Error getting call details:', e.response?.data.message);
|
|
159
|
-
}
|
|
160
|
-
throw e;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async getCallRecordings(
|
|
165
|
-
queryParams: SimulationRecordingsQueryDto
|
|
166
|
-
): Promise<SimulationRecordingsDto[]> {
|
|
167
|
-
try {
|
|
168
|
-
const res = await this.http.get(`/api/v1/simulation/call/recordings`, {
|
|
169
|
-
params: queryParams,
|
|
170
|
-
});
|
|
171
|
-
return res.data as SimulationRecordingsDto[];
|
|
172
|
-
} catch (e) {
|
|
173
|
-
if (axios.isAxiosError(e)) {
|
|
174
|
-
console.error('Error getting call recordings:', e.response?.data.message);
|
|
175
|
-
}
|
|
176
|
-
throw e;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
async getCallRecording(callId: string): Promise<string> {
|
|
181
|
-
try {
|
|
182
|
-
const res = await this.http.get(`/api/v1/simulation/call/recordings/${callId}`);
|
|
183
|
-
return res.data as string;
|
|
184
|
-
} catch (e) {
|
|
185
|
-
if (axios.isAxiosError(e)) {
|
|
186
|
-
console.error('Error getting call recording:', e.response?.data.message);
|
|
187
|
-
}
|
|
188
|
-
throw e;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Remove all listeners for all call events.
|
|
194
|
-
*/
|
|
195
|
-
private removeAllEventListeners(): void {
|
|
196
|
-
if (!this.callControllerInstance) return;
|
|
197
|
-
this.eventNames.forEach(event => {
|
|
198
|
-
(this.eventListeners[event] || []).forEach(listener => {
|
|
199
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
200
|
-
// @ts-expect-error
|
|
201
|
-
this.callControllerInstance?.off(event, listener);
|
|
202
|
-
});
|
|
203
|
-
this.eventListeners[event] = [];
|
|
204
|
-
});
|
|
205
|
-
this.eventsAttached = false;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
async startCall(simulationId: string) {
|
|
209
|
-
this.callControllerInstance = new Vapi(
|
|
210
|
-
'f07d17ec-d4e6-487d-a0b9-0539c01aecbb',
|
|
211
|
-
'https://db41aykk1gw9e.cloudfront.net' // base url
|
|
212
|
-
);
|
|
213
|
-
if (!this.eventsAttached) {
|
|
214
|
-
this.attachEvents();
|
|
215
|
-
}
|
|
216
|
-
const { data } = await this.http.get(`/api/v1/simulation/${simulationId}`);
|
|
217
|
-
const assistantId = data as string;
|
|
218
|
-
const call: Call | null = await this.callControllerInstance.start(assistantId);
|
|
219
|
-
|
|
220
|
-
if (!call || !call.assistantId) {
|
|
221
|
-
throw new Error('Cannot start a call, please try again later');
|
|
222
|
-
}
|
|
223
|
-
try {
|
|
224
|
-
const apiCall = await this.createCall({
|
|
225
|
-
callId: call.id,
|
|
226
|
-
assistantId: call.assistantId,
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Return stopCall, callId, and event subscription methods with strict typing
|
|
230
|
-
return {
|
|
231
|
-
stopCall: () => {
|
|
232
|
-
this.callControllerInstance?.stop();
|
|
233
|
-
this.removeAllEventListeners();
|
|
234
|
-
},
|
|
235
|
-
callId: apiCall._id,
|
|
236
|
-
/**
|
|
237
|
-
* Subscribe to call events for this call with strict typing.
|
|
238
|
-
* @param event Event name
|
|
239
|
-
* @param listener Listener function
|
|
240
|
-
*/
|
|
241
|
-
on: <K extends CallEventNames>(event: K, listener: CallEventListener<K>) =>
|
|
242
|
-
this.on(event, listener),
|
|
243
|
-
/**
|
|
244
|
-
* Unsubscribe from call events for this call with strict typing.
|
|
245
|
-
* @param event Event name
|
|
246
|
-
* @param listener Listener function
|
|
247
|
-
*/
|
|
248
|
-
off: <K extends CallEventNames>(event: K, listener: CallEventListener<K>) =>
|
|
249
|
-
this.off(event, listener),
|
|
250
|
-
};
|
|
251
|
-
} catch (e) {
|
|
252
|
-
this.callControllerInstance?.stop();
|
|
253
|
-
this.removeAllEventListeners();
|
|
254
|
-
throw e;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
private async createCall(payload: CallCreateDto) {
|
|
259
|
-
const response = await this.http.post('/api/v1/simulation/call', {
|
|
260
|
-
...payload,
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
return response.data as CallDTO;
|
|
264
|
-
}
|
|
265
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.base.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"forceConsistentCasingInFileNames": true,
|
|
6
|
-
"strict": true,
|
|
7
|
-
"noImplicitOverride": true,
|
|
8
|
-
"noImplicitReturns": true,
|
|
9
|
-
"noFallthroughCasesInSwitch": true,
|
|
10
|
-
"noPropertyAccessFromIndexSignature": true
|
|
11
|
-
},
|
|
12
|
-
"files": [],
|
|
13
|
-
"include": [],
|
|
14
|
-
"references": [
|
|
15
|
-
{
|
|
16
|
-
"path": "./tsconfig.lib.json"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"path": "./tsconfig.spec.json"
|
|
20
|
-
}
|
|
21
|
-
]
|
|
22
|
-
}
|
package/tsconfig.lib.json
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "./tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "../../dist/out-tsc",
|
|
5
|
-
"declaration": true,
|
|
6
|
-
"types": ["node"],
|
|
7
|
-
"esModuleInterop": true
|
|
8
|
-
},
|
|
9
|
-
"include": ["src/**/*.ts"],
|
|
10
|
-
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
|
|
11
|
-
}
|
package/tsconfig.spec.json
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "./tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "../../dist/out-tsc",
|
|
5
|
-
"module": "commonjs",
|
|
6
|
-
"moduleResolution": "node10",
|
|
7
|
-
"types": ["jest", "node"]
|
|
8
|
-
},
|
|
9
|
-
"include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"]
|
|
10
|
-
}
|